• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 #include <fcntl.h>
29 #include <unistd.h>
30 
31 #include <cerrno>
32 #include <string>
33 
34 // We want the os/log.h definitions
35 #undef LOG_DEBUG
36 #undef LOG_INFO
37 
38 #include "os/log.h"
39 
40 // Save the os/log.h definitions
41 #pragma push_macro("LOG_DEBUG")
42 #pragma push_macro("LOG_INFO")
43 
44 // Undef these to avoid conflicting with later imports
45 #undef LOG_DEBUG
46 #undef LOG_INFO
47 
48 using ::aidl::android::system::suspend::ISystemSuspend;
49 using ::aidl::android::system::suspend::IWakeLock;
50 using ::aidl::android::system::suspend::WakeLockType;
51 
52 namespace bluetooth {
53 namespace os {
54 namespace internal {
55 
56 // Restore the os/log.h definitions after all imported headers
57 #pragma pop_macro("LOG_DEBUG")
58 #pragma pop_macro("LOG_INFO")
59 
onSuspendDeath(void * cookie)60 static void onSuspendDeath(void* cookie) {
61   auto onDeath = static_cast<std::function<void(void)>*>(cookie);
62   (*onDeath)();
63 }
64 
65 struct WakelockNative::Impl {
Implbluetooth::os::internal::WakelockNative::Impl66   Impl() : suspend_death_recipient(AIBinder_DeathRecipient_new(onSuspendDeath)) {}
67 
__anon9c8d1f190102bluetooth::os::internal::WakelockNative::Impl68   std::function<void(void)> onDeath = [this] {
69     LOG_ERROR("ISystemSuspend HAL service died!");
70     this->suspend_service = nullptr;
71   };
72 
73   std::shared_ptr<ISystemSuspend> suspend_service = nullptr;
74   std::shared_ptr<IWakeLock> current_wakelock = nullptr;
75   ::ndk::ScopedAIBinder_DeathRecipient suspend_death_recipient;
76 };
77 
Initialize()78 void WakelockNative::Initialize() {
79   LOG_INFO("Initializing native wake locks");
80   const std::string suspendInstance = std::string() + ISystemSuspend::descriptor + "/default";
81   pimpl_->suspend_service = ISystemSuspend::fromBinder(
82       ndk::SpAIBinder(AServiceManager_waitForService(suspendInstance.c_str())));
83   ASSERT_LOG(pimpl_->suspend_service, "Cannot get ISystemSuspend service");
84   AIBinder_linkToDeath(
85       pimpl_->suspend_service->asBinder().get(),
86       pimpl_->suspend_death_recipient.get(),
87       static_cast<void*>(&pimpl_->onDeath));
88 }
89 
Acquire(const std::string & lock_name)90 WakelockNative::StatusCode WakelockNative::Acquire(const std::string& lock_name) {
91   if (!pimpl_->suspend_service) {
92     LOG_ERROR("lock not acquired, ISystemService is not available");
93     return StatusCode::NATIVE_SERVICE_NOT_AVAILABLE;
94   }
95 
96   if (pimpl_->current_wakelock) {
97     LOG_INFO("wakelock is already acquired");
98     return StatusCode::SUCCESS;
99   }
100 
101   auto status = pimpl_->suspend_service->acquireWakeLock(
102       WakeLockType::PARTIAL, lock_name, &pimpl_->current_wakelock);
103   if (!pimpl_->current_wakelock) {
104     LOG_ERROR("wake lock not acquired: %s", status.getDescription().c_str());
105     return StatusCode::NATIVE_API_ERROR;
106   }
107 
108   return StatusCode::SUCCESS;
109 }
110 
Release(const std::string & lock_name)111 WakelockNative::StatusCode WakelockNative::Release(const std::string& lock_name) {
112   if (!pimpl_->current_wakelock) {
113     LOG_WARN("no lock is currently acquired");
114     return StatusCode::SUCCESS;
115   }
116   pimpl_->current_wakelock->release();
117   pimpl_->current_wakelock = nullptr;
118   return StatusCode::SUCCESS;
119 }
120 
CleanUp()121 void WakelockNative::CleanUp() {
122   LOG_INFO("Cleaning up native wake locks");
123   if (pimpl_->current_wakelock) {
124     LOG_INFO("releasing current wakelock during clean up");
125     pimpl_->current_wakelock->release();
126     pimpl_->current_wakelock = nullptr;
127   }
128   if (pimpl_->suspend_service) {
129     LOG_INFO("Unlink death recipient");
130     AIBinder_unlinkToDeath(
131         pimpl_->suspend_service->asBinder().get(),
132         pimpl_->suspend_death_recipient.get(),
133         static_cast<void*>(&pimpl_->onDeath));
134     pimpl_->suspend_service = nullptr;
135   }
136 }
137 
WakelockNative()138 WakelockNative::WakelockNative() : pimpl_(std::make_unique<Impl>()) {}
139 
140 WakelockNative::~WakelockNative() = default;
141 
142 }  // namespace internal
143 }  // namespace os
144 }  // namespace bluetooth
145