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