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 <aidl/android/system/suspend/ISystemSuspend.h>
24 #include <aidl/android/system/suspend/IWakeLock.h>
25 #include <android/binder_ibinder.h>
26 #include <android/binder_manager.h>
27 #include <bluetooth/log.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30
31 #include <cerrno>
32 #include <functional>
33 #include <string>
34
35 using ::aidl::android::system::suspend::ISystemSuspend;
36 using ::aidl::android::system::suspend::IWakeLock;
37 using ::aidl::android::system::suspend::WakeLockType;
38
39 namespace bluetooth {
40 namespace os {
41 namespace internal {
42
onSuspendDeath(void * cookie)43 static void onSuspendDeath(void* cookie) {
44 auto onDeath = static_cast<std::function<void(void)>*>(cookie);
45 (*onDeath)();
46 }
47
48 struct WakelockNative::Impl {
Implbluetooth::os::internal::WakelockNative::Impl49 Impl() : suspend_death_recipient(AIBinder_DeathRecipient_new(onSuspendDeath)) {}
50
__anone69ca00a0102bluetooth::os::internal::WakelockNative::Impl51 std::function<void(void)> onDeath = [this] {
52 log::error("ISystemSuspend HAL service died!");
53 this->suspend_service = nullptr;
54 };
55
56 std::shared_ptr<ISystemSuspend> suspend_service = nullptr;
57 std::shared_ptr<IWakeLock> current_wakelock = nullptr;
58 ::ndk::ScopedAIBinder_DeathRecipient suspend_death_recipient;
59 };
60
Initialize()61 void WakelockNative::Initialize() {
62 log::info("Initializing native wake locks");
63 const std::string suspendInstance = std::string() + ISystemSuspend::descriptor + "/default";
64 pimpl_->suspend_service = ISystemSuspend::fromBinder(
65 ndk::SpAIBinder(AServiceManager_waitForService(suspendInstance.c_str())));
66 log::assert_that(pimpl_->suspend_service != nullptr, "Cannot get ISystemSuspend service");
67 AIBinder_linkToDeath(pimpl_->suspend_service->asBinder().get(),
68 pimpl_->suspend_death_recipient.get(), static_cast<void*>(&pimpl_->onDeath));
69 }
70
Acquire(const std::string & lock_name)71 WakelockNative::StatusCode WakelockNative::Acquire(const std::string& lock_name) {
72 if (!pimpl_->suspend_service) {
73 log::error("lock not acquired, ISystemService is not available");
74 return StatusCode::NATIVE_SERVICE_NOT_AVAILABLE;
75 }
76
77 if (pimpl_->current_wakelock) {
78 log::info("wakelock is already acquired");
79 return StatusCode::SUCCESS;
80 }
81
82 auto status = pimpl_->suspend_service->acquireWakeLock(WakeLockType::PARTIAL, lock_name,
83 &pimpl_->current_wakelock);
84 if (!pimpl_->current_wakelock) {
85 log::error("wake lock not acquired: {}", status.getDescription());
86 return StatusCode::NATIVE_API_ERROR;
87 }
88
89 return StatusCode::SUCCESS;
90 }
91
Release(const std::string &)92 WakelockNative::StatusCode WakelockNative::Release(const std::string& /* lock_name */) {
93 if (!pimpl_->current_wakelock) {
94 log::warn("no lock is currently acquired");
95 return StatusCode::SUCCESS;
96 }
97 pimpl_->current_wakelock->release();
98 pimpl_->current_wakelock = nullptr;
99 return StatusCode::SUCCESS;
100 }
101
CleanUp()102 void WakelockNative::CleanUp() {
103 log::info("Cleaning up native wake locks");
104 if (pimpl_->current_wakelock) {
105 log::info("releasing current wakelock during clean up");
106 pimpl_->current_wakelock->release();
107 pimpl_->current_wakelock = nullptr;
108 }
109 if (pimpl_->suspend_service) {
110 log::info("Unlink death recipient");
111 AIBinder_unlinkToDeath(pimpl_->suspend_service->asBinder().get(),
112 pimpl_->suspend_death_recipient.get(),
113 static_cast<void*>(&pimpl_->onDeath));
114 pimpl_->suspend_service = nullptr;
115 }
116 }
117
WakelockNative()118 WakelockNative::WakelockNative() : pimpl_(std::make_unique<Impl>()) {}
119
120 WakelockNative::~WakelockNative() = default;
121
122 } // namespace internal
123 } // namespace os
124 } // namespace bluetooth
125