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