/****************************************************************************** * * Copyright 2021 Google, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ #define LOG_TAG "BtGdWakelockNative" #include "os/internal/wakelock_native.h" #include #include #include #include #include #include #include #include // We want the os/log.h definitions #undef LOG_DEBUG #undef LOG_INFO #include "os/log.h" // Save the os/log.h definitions #pragma push_macro("LOG_DEBUG") #pragma push_macro("LOG_INFO") // Undef these to avoid conflicting with later imports #undef LOG_DEBUG #undef LOG_INFO using ::aidl::android::system::suspend::ISystemSuspend; using ::aidl::android::system::suspend::IWakeLock; using ::aidl::android::system::suspend::WakeLockType; namespace bluetooth { namespace os { namespace internal { // Restore the os/log.h definitions after all imported headers #pragma pop_macro("LOG_DEBUG") #pragma pop_macro("LOG_INFO") static void onSuspendDeath(void* cookie) { auto onDeath = static_cast*>(cookie); (*onDeath)(); } struct WakelockNative::Impl { Impl() : suspend_death_recipient(AIBinder_DeathRecipient_new(onSuspendDeath)) {} std::function onDeath = [this] { LOG_ERROR("ISystemSuspend HAL service died!"); this->suspend_service = nullptr; }; std::shared_ptr suspend_service = nullptr; std::shared_ptr current_wakelock = nullptr; ::ndk::ScopedAIBinder_DeathRecipient suspend_death_recipient; }; void WakelockNative::Initialize() { LOG_INFO("Initializing native wake locks"); const std::string suspendInstance = std::string() + ISystemSuspend::descriptor + "/default"; pimpl_->suspend_service = ISystemSuspend::fromBinder( ndk::SpAIBinder(AServiceManager_waitForService(suspendInstance.c_str()))); ASSERT_LOG(pimpl_->suspend_service, "Cannot get ISystemSuspend service"); AIBinder_linkToDeath( pimpl_->suspend_service->asBinder().get(), pimpl_->suspend_death_recipient.get(), static_cast(&pimpl_->onDeath)); } WakelockNative::StatusCode WakelockNative::Acquire(const std::string& lock_name) { if (!pimpl_->suspend_service) { LOG_ERROR("lock not acquired, ISystemService is not available"); return StatusCode::NATIVE_SERVICE_NOT_AVAILABLE; } if (pimpl_->current_wakelock) { LOG_INFO("wakelock is already acquired"); return StatusCode::SUCCESS; } auto status = pimpl_->suspend_service->acquireWakeLock( WakeLockType::PARTIAL, lock_name, &pimpl_->current_wakelock); if (!pimpl_->current_wakelock) { LOG_ERROR("wake lock not acquired: %s", status.getDescription().c_str()); return StatusCode::NATIVE_API_ERROR; } return StatusCode::SUCCESS; } WakelockNative::StatusCode WakelockNative::Release(const std::string& lock_name) { if (!pimpl_->current_wakelock) { LOG_WARN("no lock is currently acquired"); return StatusCode::SUCCESS; } pimpl_->current_wakelock->release(); pimpl_->current_wakelock = nullptr; return StatusCode::SUCCESS; } void WakelockNative::CleanUp() { LOG_INFO("Cleaning up native wake locks"); if (pimpl_->current_wakelock) { LOG_INFO("releasing current wakelock during clean up"); pimpl_->current_wakelock->release(); pimpl_->current_wakelock = nullptr; } if (pimpl_->suspend_service) { LOG_INFO("Unlink death recipient"); AIBinder_unlinkToDeath( pimpl_->suspend_service->asBinder().get(), pimpl_->suspend_death_recipient.get(), static_cast(&pimpl_->onDeath)); pimpl_->suspend_service = nullptr; } } WakelockNative::WakelockNative() : pimpl_(std::make_unique()) {} WakelockNative::~WakelockNative() = default; } // namespace internal } // namespace os } // namespace bluetooth