145 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
/******************************************************************************
 | 
						|
 *
 | 
						|
 *  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 <aidl/android/system/suspend/ISystemSuspend.h>
 | 
						|
#include <aidl/android/system/suspend/IWakeLock.h>
 | 
						|
#include <android/binder_ibinder.h>
 | 
						|
#include <android/binder_manager.h>
 | 
						|
 | 
						|
#include <fcntl.h>
 | 
						|
#include <unistd.h>
 | 
						|
 | 
						|
#include <cerrno>
 | 
						|
#include <string>
 | 
						|
 | 
						|
// 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<std::function<void(void)>*>(cookie);
 | 
						|
  (*onDeath)();
 | 
						|
}
 | 
						|
 | 
						|
struct WakelockNative::Impl {
 | 
						|
  Impl() : suspend_death_recipient(AIBinder_DeathRecipient_new(onSuspendDeath)) {}
 | 
						|
 | 
						|
  std::function<void(void)> onDeath = [this] {
 | 
						|
    LOG_ERROR("ISystemSuspend HAL service died!");
 | 
						|
    this->suspend_service = nullptr;
 | 
						|
  };
 | 
						|
 | 
						|
  std::shared_ptr<ISystemSuspend> suspend_service = nullptr;
 | 
						|
  std::shared_ptr<IWakeLock> 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<void*>(&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<void*>(&pimpl_->onDeath));
 | 
						|
    pimpl_->suspend_service = nullptr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
WakelockNative::WakelockNative() : pimpl_(std::make_unique<Impl>()) {}
 | 
						|
 | 
						|
WakelockNative::~WakelockNative() = default;
 | 
						|
 | 
						|
}  // namespace internal
 | 
						|
}  // namespace os
 | 
						|
}  // namespace bluetooth
 |