/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.
*/
#include <nativepower/power_manager_client.h>
#include <base/bind.h>
#include <base/logging.h>
#include <binder/IBinder.h>
#include <binderwrapper/binder_wrapper.h>
#include <nativepower/constants.h>
#include <nativepower/wake_lock.h>
#include <powermanager/PowerManager.h>
namespace android {
namespace {
// Returns the string corresponding to |reason|. Values are hardcoded in
// core/java/android/os/PowerManager.java.
String16 ShutdownReasonToString16(ShutdownReason reason) {
switch (reason) {
case ShutdownReason::DEFAULT:
return String16();
case ShutdownReason::USER_REQUESTED:
return String16(kShutdownReasonUserRequested);
default:
LOG(ERROR) << "Unknown shutdown reason " << static_cast<int>(reason);
return String16();
}
}
// Returns the string corresponding to |reason|. Values are hardcoded in
// core/java/android/os/PowerManager.java.
String16 RebootReasonToString16(RebootReason reason) {
switch (reason) {
case RebootReason::DEFAULT:
return String16();
case RebootReason::RECOVERY:
return String16(kRebootReasonRecovery);
default:
LOG(ERROR) << "Unknown reboot reason " << static_cast<int>(reason);
return String16();
}
}
} // namespace
PowerManagerClient::PowerManagerClient()
: weak_ptr_factory_(this) {}
PowerManagerClient::~PowerManagerClient() {
if (power_manager_.get()) {
BinderWrapper::Get()->UnregisterForDeathNotifications(
IInterface::asBinder(power_manager_));
}
}
bool PowerManagerClient::Init() {
sp<IBinder> power_manager_binder =
BinderWrapper::Get()->GetService(kPowerManagerServiceName);
if (!power_manager_binder.get()) {
LOG(ERROR) << "Didn't get " << kPowerManagerServiceName << " service";
return false;
}
BinderWrapper::Get()->RegisterForDeathNotifications(
power_manager_binder,
base::Bind(&PowerManagerClient::OnPowerManagerDied,
weak_ptr_factory_.GetWeakPtr()));
power_manager_ = interface_cast<IPowerManager>(power_manager_binder);
return true;
}
std::unique_ptr<WakeLock> PowerManagerClient::CreateWakeLock(
const std::string& tag,
const std::string& package) {
std::unique_ptr<WakeLock> lock(new WakeLock(tag, package, this));
if (!lock->Init())
lock.reset();
return lock;
}
bool PowerManagerClient::Suspend(base::TimeDelta event_uptime,
SuspendReason reason,
int flags) {
DCHECK(power_manager_.get());
status_t status = power_manager_->goToSleep(
event_uptime.InMilliseconds(), static_cast<int>(reason), flags);
if (status != OK) {
LOG(ERROR) << "Suspend request failed with status " << status;
return false;
}
return true;
}
bool PowerManagerClient::ShutDown(ShutdownReason reason) {
DCHECK(power_manager_.get());
status_t status = power_manager_->shutdown(false /* confirm */,
ShutdownReasonToString16(reason),
false /* wait */);
if (status != OK) {
LOG(ERROR) << "Shutdown request failed with status " << status;
return false;
}
return true;
}
bool PowerManagerClient::Reboot(RebootReason reason) {
DCHECK(power_manager_.get());
status_t status = power_manager_->reboot(false /* confirm */,
RebootReasonToString16(reason),
false /* wait */);
if (status != OK) {
LOG(ERROR) << "Reboot request failed with status " << status;
return false;
}
return true;
}
void PowerManagerClient::OnPowerManagerDied() {
LOG(WARNING) << "Power manager died";
power_manager_.clear();
// TODO: Try to get a new handle periodically; also consider notifying
// previously-created WakeLock objects so they can reacquire locks.
}
} // namespace android