1 /******************************************************************************
2  *
3  *  Copyright 2021 Google, Inc.
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 #define LOG_TAG "BtGdWakelockNative"
20 
21 #include "os/internal/wakelock_native.h"
22 
23 #include <android/system/suspend/1.0/ISystemSuspend.h>
24 #include <fcntl.h>
25 #include <unistd.h>
26 
27 #include <cerrno>
28 #include <string>
29 
30 #include "os/log.h"
31 
32 namespace bluetooth {
33 namespace os {
34 namespace internal {
35 
36 using android::sp;
37 using android::system::suspend::V1_0::ISystemSuspend;
38 using android::system::suspend::V1_0::IWakeLock;
39 using android::system::suspend::V1_0::WakeLockType;
40 
41 struct WakelockNative::Impl {
42   sp<ISystemSuspend> suspend_service = nullptr;
43   sp<IWakeLock> current_wakelock = nullptr;
44 
45   class SystemSuspendDeathRecipient : public ::android::hardware::hidl_death_recipient {
46    public:
SystemSuspendDeathRecipient(WakelockNative::Impl * impl)47     explicit SystemSuspendDeathRecipient(WakelockNative::Impl* impl) : impl_(impl) {}
serviceDied(uint64_t,const android::wp<::android::hidl::base::V1_0::IBase> &)48     void serviceDied(uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) override {
49       LOG_ERROR("ISystemSuspend HAL service died!");
50       impl_->suspend_service = nullptr;
51     }
52 
53    private:
54     WakelockNative::Impl* impl_ = nullptr;
55   };
56   sp<SystemSuspendDeathRecipient> suspend_death_recipient;
57 };
58 
Initialize()59 void WakelockNative::Initialize() {
60   LOG_INFO("Initializing native wake locks");
61   pimpl_->suspend_service = ISystemSuspend::getService();
62   ASSERT_LOG(pimpl_->suspend_service, "Cannot get ISystemSuspend service");
63   pimpl_->suspend_death_recipient = new Impl::SystemSuspendDeathRecipient(pimpl_.get());
64   pimpl_->suspend_service->linkToDeath(pimpl_->suspend_death_recipient, 0 /* cookie */);
65 }
66 
Acquire(const std::string & lock_name)67 WakelockNative::StatusCode WakelockNative::Acquire(const std::string& lock_name) {
68   if (!pimpl_->suspend_service) {
69     LOG_ERROR("lock not acquired, ISystemService is not available");
70     return StatusCode::NATIVE_SERVICE_NOT_AVAILABLE;
71   }
72 
73   if (pimpl_->current_wakelock) {
74     LOG_INFO("wakelock is already acquired");
75     return StatusCode::SUCCESS;
76   }
77 
78   pimpl_->current_wakelock = pimpl_->suspend_service->acquireWakeLock(WakeLockType::PARTIAL, lock_name);
79   if (!pimpl_->current_wakelock) {
80     LOG_ERROR("wake lock not acquired: %s", strerror(errno));
81     return StatusCode::NATIVE_API_ERROR;
82   }
83 
84   return StatusCode::SUCCESS;
85 }
86 
Release(const std::string & lock_name)87 WakelockNative::StatusCode WakelockNative::Release(const std::string& lock_name) {
88   if (!pimpl_->current_wakelock) {
89     LOG_WARN("no lock is currently acquired");
90     return StatusCode::SUCCESS;
91   }
92   pimpl_->current_wakelock->release();
93   pimpl_->current_wakelock.clear();
94   return StatusCode::SUCCESS;
95 }
96 
CleanUp()97 void WakelockNative::CleanUp() {
98   LOG_INFO("Cleaning up native wake locks");
99   if (pimpl_->current_wakelock) {
100     LOG_INFO("releasing current wakelock during clean up");
101     pimpl_->current_wakelock->release();
102     pimpl_->current_wakelock.clear();
103   }
104   if (pimpl_->suspend_service) {
105     LOG_INFO("Unlink death recipient");
106     pimpl_->suspend_service->unlinkToDeath(pimpl_->suspend_death_recipient);
107     pimpl_->suspend_death_recipient.clear();
108     pimpl_->suspend_service.clear();
109   }
110 }
111 
WakelockNative()112 WakelockNative::WakelockNative() : pimpl_(std::make_unique<Impl>()) {}
113 
114 WakelockNative::~WakelockNative() = default;
115 
116 }  // namespace internal
117 }  // namespace os
118 }  // namespace bluetooth