| /* |
| * 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 "power_manager.h" |
| |
| #include <base/files/file_util.h> |
| #include <base/logging.h> |
| #include <base/sys_info.h> |
| #include <binderwrapper/binder_wrapper.h> |
| #include <cutils/android_reboot.h> |
| #include <nativepower/constants.h> |
| #include <powermanager/IPowerManager.h> |
| #include <utils/Errors.h> |
| #include <utils/String8.h> |
| |
| namespace android { |
| namespace { |
| |
| // Path to real sysfs file that can be written to change the power state. |
| const char kDefaultPowerStatePath[] = "/sys/power/state"; |
| |
| } // namespace |
| |
| const char PowerManager::kRebootPrefix[] = "reboot,"; |
| const char PowerManager::kShutdownPrefix[] = "shutdown,"; |
| const char PowerManager::kPowerStateSuspend[] = "mem"; |
| |
| PowerManager::PowerManager() |
| : power_state_path_(kDefaultPowerStatePath) {} |
| |
| PowerManager::~PowerManager() = default; |
| |
| bool PowerManager::Init() { |
| if (!property_setter_) |
| property_setter_.reset(new SystemPropertySetter()); |
| if (!wake_lock_manager_) { |
| wake_lock_manager_.reset(new WakeLockManager()); |
| if (!static_cast<WakeLockManager*>(wake_lock_manager_.get())->Init()) |
| return false; |
| } |
| |
| LOG(INFO) << "Registering with service manager as \"" |
| << kPowerManagerServiceName << "\""; |
| return BinderWrapper::Get()->RegisterService(kPowerManagerServiceName, this); |
| } |
| |
| status_t PowerManager::acquireWakeLock(int flags, |
| const sp<IBinder>& lock, |
| const String16& tag, |
| const String16& packageName, |
| bool isOneWay) { |
| return AddWakeLockRequest(lock, tag, packageName, |
| BinderWrapper::Get()->GetCallingUid()) |
| ? OK |
| : UNKNOWN_ERROR; |
| } |
| |
| status_t PowerManager::acquireWakeLockWithUid(int flags, |
| const sp<IBinder>& lock, |
| const String16& tag, |
| const String16& packageName, |
| int uid, |
| bool isOneWay) { |
| return AddWakeLockRequest(lock, tag, packageName, static_cast<uid_t>(uid)) |
| ? OK |
| : UNKNOWN_ERROR; |
| } |
| |
| status_t PowerManager::releaseWakeLock(const sp<IBinder>& lock, |
| int flags, |
| bool isOneWay) { |
| return wake_lock_manager_->RemoveRequest(lock) ? OK : UNKNOWN_ERROR; |
| } |
| |
| status_t PowerManager::updateWakeLockUids(const sp<IBinder>& lock, |
| int len, |
| const int* uids, |
| bool isOneWay) { |
| NOTIMPLEMENTED() << "updateWakeLockUids: lock=" << lock.get() |
| << " len=" << len; |
| return OK; |
| } |
| |
| status_t PowerManager::powerHint(int hintId, int data) { |
| NOTIMPLEMENTED() << "powerHint: hintId=" << hintId << " data=" << data; |
| return OK; |
| } |
| |
| status_t PowerManager::goToSleep(int64_t event_time_ms, int reason, int flags) { |
| if (event_time_ms < last_resume_uptime_.InMilliseconds()) { |
| LOG(WARNING) << "Ignoring request to suspend in response to event at " |
| << event_time_ms << " preceding last resume time " |
| << last_resume_uptime_.InMilliseconds(); |
| return BAD_VALUE; |
| } |
| |
| LOG(INFO) << "Suspending immediately for event at " << event_time_ms |
| << " (reason=" << reason << " flags=" << flags << ")"; |
| if (base::WriteFile(power_state_path_, kPowerStateSuspend, |
| strlen(kPowerStateSuspend)) != |
| static_cast<int>(strlen(kPowerStateSuspend))) { |
| PLOG(ERROR) << "Failed to write \"" << kPowerStateSuspend << "\" to " |
| << power_state_path_.value(); |
| return UNKNOWN_ERROR; |
| } |
| |
| last_resume_uptime_ = base::SysInfo::Uptime(); |
| LOG(INFO) << "Resumed from suspend at " |
| << last_resume_uptime_.InMilliseconds(); |
| return OK; |
| } |
| |
| status_t PowerManager::reboot(bool confirm, const String16& reason, bool wait) { |
| const std::string reason_str(String8(reason).string()); |
| if (!(reason_str.empty() || reason_str == kRebootReasonRecovery)) { |
| LOG(WARNING) << "Ignoring reboot request with invalid reason \"" |
| << reason_str << "\""; |
| return BAD_VALUE; |
| } |
| |
| LOG(INFO) << "Rebooting with reason \"" << reason_str << "\""; |
| if (!property_setter_->SetProperty(ANDROID_RB_PROPERTY, |
| kRebootPrefix + reason_str)) { |
| return UNKNOWN_ERROR; |
| } |
| return OK; |
| } |
| |
| status_t PowerManager::shutdown(bool confirm, |
| const String16& reason, |
| bool wait) { |
| const std::string reason_str(String8(reason).string()); |
| if (!(reason_str.empty() || reason_str == kShutdownReasonUserRequested)) { |
| LOG(WARNING) << "Ignoring shutdown request with invalid reason \"" |
| << reason_str << "\""; |
| return BAD_VALUE; |
| } |
| |
| LOG(INFO) << "Shutting down with reason \"" << reason_str << "\""; |
| if (!property_setter_->SetProperty(ANDROID_RB_PROPERTY, |
| kShutdownPrefix + reason_str)) { |
| return UNKNOWN_ERROR; |
| } |
| return OK; |
| } |
| |
| status_t PowerManager::crash(const String16& message) { |
| NOTIMPLEMENTED() << "crash: message=" << message; |
| return OK; |
| } |
| |
| bool PowerManager::AddWakeLockRequest(const sp<IBinder>& lock, |
| const String16& tag, |
| const String16& packageName, |
| int uid) { |
| return wake_lock_manager_->AddRequest(lock, String8(tag).string(), |
| String8(packageName).string(), uid); |
| } |
| |
| } // namespace android |