Project import
diff --git a/nativepower/Android.mk b/nativepower/Android.mk new file mode 100644 index 0000000..178cb8a --- /dev/null +++ b/nativepower/Android.mk
@@ -0,0 +1,17 @@ +# +# 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 $(call all-subdir-makefiles)
diff --git a/nativepower/MODULE_LICENSE_APACHE2 b/nativepower/MODULE_LICENSE_APACHE2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/nativepower/MODULE_LICENSE_APACHE2
diff --git a/nativepower/NOTICE b/nativepower/NOTICE new file mode 100644 index 0000000..a849a94 --- /dev/null +++ b/nativepower/NOTICE
@@ -0,0 +1,190 @@ + + Copyright (c) 2014-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. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS +
diff --git a/nativepower/README b/nativepower/README new file mode 100644 index 0000000..bf8a5c7 --- /dev/null +++ b/nativepower/README
@@ -0,0 +1,7 @@ +This directory contains a C++ implementation of power management for use by +Brillo: + + client/ - libnativepower, a client library for calling nativepowerman + daemon/ - nativepowerman, a daemon that performs power management + example/ - power_example, an example executable that uses libnativepower + include/ - exported header files
diff --git a/nativepower/client/Android.mk b/nativepower/client/Android.mk new file mode 100644 index 0000000..af2f50f --- /dev/null +++ b/nativepower/client/Android.mk
@@ -0,0 +1,65 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +libnativepower_CommonCFlags := -Wall -Werror -Wno-unused-parameter +libnativepower_CommonCFlags += -Wno-sign-promo # for libchrome +libnativepower_CommonCIncludes := $(LOCAL_PATH)/../include +libnativepower_CommonSharedLibraries := \ + libbinder \ + libbinderwrapper \ + libbrillo \ + libchrome \ + libpowermanager \ + libutils \ + +# libnativepower shared library +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE := libnativepower +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := $(libnativepower_CommonCFlags) +LOCAL_C_INCLUDES := $(libnativepower_CommonCIncludes) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include +LOCAL_SHARED_LIBRARIES := $(libnativepower_CommonSharedLibraries) +LOCAL_SRC_FILES := \ + power_manager_client.cc \ + wake_lock.cc \ + +include $(BUILD_SHARED_LIBRARY) + +# libnativepower_tests executable +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE := libnativepower_tests +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := $(libnativepower_CommonCFlags) +LOCAL_C_INCLUDES := $(libnativepower_CommonCIncludes) +LOCAL_STATIC_LIBRARIES := libgtest libBionicGtestMain +LOCAL_SHARED_LIBRARIES := \ + $(libnativepower_CommonSharedLibraries) \ + libbinderwrapper_test_support \ + libnativepower \ + libnativepower_test_support \ + +LOCAL_SRC_FILES := \ + power_manager_client_unittest.cc \ + wake_lock_unittest.cc \ + +include $(BUILD_NATIVE_TEST)
diff --git a/nativepower/client/power_manager_client.cc b/nativepower/client/power_manager_client.cc new file mode 100644 index 0000000..20c437a --- /dev/null +++ b/nativepower/client/power_manager_client.cc
@@ -0,0 +1,140 @@ +/* + * 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
diff --git a/nativepower/client/power_manager_client_unittest.cc b/nativepower/client/power_manager_client_unittest.cc new file mode 100644 index 0000000..f27265e --- /dev/null +++ b/nativepower/client/power_manager_client_unittest.cc
@@ -0,0 +1,82 @@ +/* + * 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 <base/logging.h> +#include <base/macros.h> +#include <base/time/time.h> +#include <binderwrapper/binder_test_base.h> +#include <binderwrapper/stub_binder_wrapper.h> +#include <nativepower/constants.h> +#include <nativepower/power_manager_client.h> +#include <nativepower/power_manager_stub.h> + +namespace android { + +class PowerManagerClientTest : public BinderTestBase { + public: + PowerManagerClientTest() + : power_manager_(new PowerManagerStub()), + power_manager_binder_(power_manager_) { + binder_wrapper()->SetBinderForService(kPowerManagerServiceName, + power_manager_binder_); + CHECK(client_.Init()); + } + ~PowerManagerClientTest() override = default; + + protected: + PowerManagerStub* power_manager_; // Owned by |power_manager_binder_|. + sp<IBinder> power_manager_binder_; + PowerManagerClient client_; + + private: + DISALLOW_COPY_AND_ASSIGN(PowerManagerClientTest); +}; + +TEST_F(PowerManagerClientTest, Suspend) { + EXPECT_EQ(0, power_manager_->num_suspend_requests()); + + const auto kEventTime = base::TimeDelta::FromMilliseconds(123); + const int kFlags = 0x456; + EXPECT_TRUE(client_.Suspend(kEventTime, SuspendReason::POWER_BUTTON, kFlags)); + EXPECT_EQ(1, power_manager_->num_suspend_requests()); + EXPECT_EQ(PowerManagerStub::ConstructSuspendRequestString( + kEventTime.InMilliseconds(), + static_cast<int>(SuspendReason::POWER_BUTTON), kFlags), + power_manager_->GetSuspendRequestString(0)); +} + +TEST_F(PowerManagerClientTest, ShutDown) { + EXPECT_TRUE(client_.ShutDown(ShutdownReason::DEFAULT)); + ASSERT_EQ(1u, power_manager_->shutdown_reasons().size()); + EXPECT_EQ("", power_manager_->shutdown_reasons()[0]); + + EXPECT_TRUE(client_.ShutDown(ShutdownReason::USER_REQUESTED)); + ASSERT_EQ(2u, power_manager_->shutdown_reasons().size()); + EXPECT_EQ(kShutdownReasonUserRequested, + power_manager_->shutdown_reasons()[1]); +} + +TEST_F(PowerManagerClientTest, Reboot) { + EXPECT_TRUE(client_.Reboot(RebootReason::DEFAULT)); + ASSERT_EQ(1u, power_manager_->reboot_reasons().size()); + EXPECT_EQ("", power_manager_->reboot_reasons()[0]); + + EXPECT_TRUE(client_.Reboot(RebootReason::RECOVERY)); + ASSERT_EQ(2u, power_manager_->reboot_reasons().size()); + EXPECT_EQ(kRebootReasonRecovery, power_manager_->reboot_reasons()[1]); +} + +} // namespace android
diff --git a/nativepower/client/wake_lock.cc b/nativepower/client/wake_lock.cc new file mode 100644 index 0000000..bf65b00 --- /dev/null +++ b/nativepower/client/wake_lock.cc
@@ -0,0 +1,71 @@ +/* + * 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/wake_lock.h> + +#include <base/logging.h> +#include <binderwrapper/binder_wrapper.h> +#include <nativepower/power_manager_client.h> +#include <powermanager/IPowerManager.h> +#include <powermanager/PowerManager.h> + +namespace android { + +WakeLock::WakeLock(const std::string& tag, + const std::string& package, + PowerManagerClient* client) + : acquired_lock_(false), + tag_(tag), + package_(package), + client_(client) { + DCHECK(client_); +} + +WakeLock::~WakeLock() { + sp<IPowerManager> power_manager = client_->power_manager(); + if (acquired_lock_ && power_manager.get()) { + status_t status = + power_manager->releaseWakeLock(lock_binder_, 0 /* flags */); + if (status != OK) { + LOG(ERROR) << "Wake lock release request for \"" << tag_ << "\" failed " + << "with status " << status; + } + } +} + +bool WakeLock::Init() { + sp<IPowerManager> power_manager = client_->power_manager(); + if (!power_manager.get()) { + LOG(ERROR) << "Can't acquire wake lock for \"" << tag_ << "\"; no " + << "connection to power manager"; + return false; + } + + lock_binder_ = BinderWrapper::Get()->CreateLocalBinder(); + status_t status = power_manager->acquireWakeLock( + POWERMANAGER_PARTIAL_WAKE_LOCK, + lock_binder_, String16(tag_.c_str()), String16(package_.c_str())); + if (status != OK) { + LOG(ERROR) << "Wake lock acquire request for \"" << tag_ << "\" failed " + << "with status " << status; + return false; + } + + acquired_lock_ = true; + return true; +} + +} // namespace android
diff --git a/nativepower/client/wake_lock_unittest.cc b/nativepower/client/wake_lock_unittest.cc new file mode 100644 index 0000000..dbd1505 --- /dev/null +++ b/nativepower/client/wake_lock_unittest.cc
@@ -0,0 +1,76 @@ +/* + * 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 <memory> + +#include <base/logging.h> +#include <base/macros.h> +#include <binder/Binder.h> +#include <binder/IBinder.h> +#include <binderwrapper/binder_test_base.h> +#include <binderwrapper/stub_binder_wrapper.h> +#include <nativepower/constants.h> +#include <nativepower/power_manager_client.h> +#include <nativepower/power_manager_stub.h> +#include <nativepower/wake_lock.h> + +namespace android { + +class WakeLockTest : public BinderTestBase { + public: + WakeLockTest() + : power_manager_(new PowerManagerStub()), + power_manager_binder_(power_manager_) { + binder_wrapper()->SetBinderForService(kPowerManagerServiceName, + power_manager_binder_); + CHECK(client_.Init()); + } + ~WakeLockTest() override = default; + + protected: + PowerManagerStub* power_manager_; // Owned by |power_manager_binder_|. + sp<IBinder> power_manager_binder_; + PowerManagerClient client_; + + private: + DISALLOW_COPY_AND_ASSIGN(WakeLockTest); +}; + +TEST_F(WakeLockTest, CreateAndDestroy) { + const uid_t kUid = 123; + binder_wrapper()->set_calling_uid(kUid); + std::unique_ptr<WakeLock> lock(client_.CreateWakeLock("foo", "bar")); + ASSERT_EQ(1, power_manager_->GetNumWakeLocks()); + ASSERT_EQ(1u, binder_wrapper()->local_binders().size()); + EXPECT_EQ( + PowerManagerStub::ConstructWakeLockString("foo", "bar", kUid), + power_manager_->GetWakeLockString(binder_wrapper()->local_binders()[0])); + + lock.reset(); + EXPECT_EQ(0, power_manager_->GetNumWakeLocks()); +} + +TEST_F(WakeLockTest, PowerManagerDeath) { + std::unique_ptr<WakeLock> lock(client_.CreateWakeLock("foo", "bar")); + binder_wrapper()->NotifyAboutBinderDeath(power_manager_binder_); + + // Since PowerManagerClient was informed that the power manager died, WakeLock + // shouldn't try to release its lock on destruction. + lock.reset(); + EXPECT_EQ(1, power_manager_->GetNumWakeLocks()); +} + +} // namespace android
diff --git a/nativepower/daemon/Android.mk b/nativepower/daemon/Android.mk new file mode 100644 index 0000000..4a97794 --- /dev/null +++ b/nativepower/daemon/Android.mk
@@ -0,0 +1,125 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +nativepowerman_CommonCFlags := -Wall -Werror -Wno-unused-parameter +nativepowerman_CommonCFlags += -Wno-sign-promo # for libchrome +nativepowerman_CommonCIncludes := \ + $(LOCAL_PATH)/../include \ + external/gtest/include \ + +nativepowerman_CommonSharedLibraries := \ + libbinder \ + libbinderwrapper \ + libchrome \ + libcutils \ + libpowermanager \ + libutils \ + +# nativepowerman executable +# ======================================================== + +include $(CLEAR_VARS) +# "nativepowermanager" would probably be a better name, but Android service +# names are limited to 16 characters. +LOCAL_MODULE := nativepowerman +LOCAL_REQUIRED_MODULES := nativepowerman.rc +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := $(nativepowerman_CommonCFlags) +LOCAL_STATIC_LIBRARIES := libnativepowerman +LOCAL_SHARED_LIBRARIES := \ + $(nativepowerman_CommonSharedLibraries) \ + libbrillo \ + libbrillo-binder \ + +LOCAL_SRC_FILES := main.cc + +include $(BUILD_EXECUTABLE) + +# nativepowerman.rc script +# ======================================================== + +ifdef INITRC_TEMPLATE +include $(CLEAR_VARS) +LOCAL_MODULE := nativepowerman.rc +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_INITRCD) + +include $(BUILD_SYSTEM)/base_rules.mk + +$(LOCAL_BUILT_MODULE): $(INITRC_TEMPLATE) + $(call generate-initrc-file,nativepowerman,,wakelock) +endif + +# libnativepowerman client library (for daemon and tests) +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE := libnativepowerman +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := $(nativepowerman_CommonCFlags) +LOCAL_C_INCLUDES := $(nativepowerman_CommonCIncludes) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include +LOCAL_SHARED_LIBRARIES := \ + $(nativepowerman_CommonSharedLibraries) \ + libbrillo \ + +LOCAL_SRC_FILES := \ + BnPowerManager.cc \ + power_manager.cc \ + system_property_setter.cc \ + wake_lock_manager.cc \ + +include $(BUILD_STATIC_LIBRARY) + +# nativepowerman_tests executable +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE := nativepowerman_tests +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := $(nativepowerman_CommonCFlags) +LOCAL_STATIC_LIBRARIES := libnativepowerman libgtest libBionicGtestMain +LOCAL_SHARED_LIBRARIES := \ + $(nativepowerman_CommonSharedLibraries) \ + libbinderwrapper_test_support \ + libnativepower_test_support \ + +LOCAL_SRC_FILES := \ + power_manager_unittest.cc \ + system_property_setter_stub.cc \ + wake_lock_manager_unittest.cc \ + +include $(BUILD_NATIVE_TEST) + +# libnativepower_test_support shared library +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE := libnativepower_test_support +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := $(nativepowerman_CommonCFlags) +LOCAL_C_INCLUDES := $(nativepowerman_CommonCIncludes) +LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../include +LOCAL_SHARED_LIBRARIES := $(nativepowerman_CommonSharedLibraries) +LOCAL_SRC_FILES := \ + BnPowerManager.cc \ + power_manager_stub.cc \ + wake_lock_manager.cc \ + wake_lock_manager_stub.cc \ + +include $(BUILD_SHARED_LIBRARY)
diff --git a/nativepower/daemon/BnPowerManager.cc b/nativepower/daemon/BnPowerManager.cc new file mode 100644 index 0000000..f3bf8bc --- /dev/null +++ b/nativepower/daemon/BnPowerManager.cc
@@ -0,0 +1,98 @@ +/* + * 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/BnPowerManager.h> + +#include <binder/Parcel.h> + +namespace android { + +status_t BnPowerManager::onTransact(uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags) { + switch (code) { + case IPowerManager::ACQUIRE_WAKE_LOCK: { + // The parameter orders in IPowerManager.aidl and IPowerManager.h don't + // match. :-( (BpPowerManager in IPowerManager.cpp passes arguments in the + // order that the AIDL file describes and that we use here, though.) + CHECK_INTERFACE(IPowerManager, data, reply); + sp<IBinder> lock = data.readStrongBinder(); + int32_t flags = data.readInt32(); + String16 tag = data.readString16(); + String16 package_name = data.readString16(); + // Ignore work source and history. + return acquireWakeLock(flags, lock, tag, package_name); + } + case IPowerManager::ACQUIRE_WAKE_LOCK_UID: { + CHECK_INTERFACE(IPowerManager, data, reply); + sp<IBinder> lock = data.readStrongBinder(); + int32_t flags = data.readInt32(); + String16 tag = data.readString16(); + String16 package_name = data.readString16(); + int32_t uid = data.readInt32(); + return acquireWakeLockWithUid(flags, lock, tag, package_name, uid); + } + case IPowerManager::RELEASE_WAKE_LOCK: { + CHECK_INTERFACE(IPowerManager, data, reply); + sp<IBinder> lock = data.readStrongBinder(); + int32_t flags = data.readInt32(); + return releaseWakeLock(lock, flags); + } + case IPowerManager::UPDATE_WAKE_LOCK_UIDS: { + CHECK_INTERFACE(IPowerManager, data, reply); + sp<IBinder> lock = data.readStrongBinder(); + // TODO: There's no Parcel::readInt32Array(). Add one. + return updateWakeLockUids(lock, 0, nullptr); + } + case IPowerManager::POWER_HINT: { + CHECK_INTERFACE(IPowerManager, data, reply); + int32_t hint_id = data.readInt32(); + int32_t params = data.readInt32(); + return powerHint(hint_id, params); + } + case IPowerManager::GO_TO_SLEEP: { + CHECK_INTERFACE(IPowerManager, data, reply); + int64_t event_time_ms = data.readInt64(); + int32_t reason = data.readInt32(); + int32_t flags = data.readInt32(); + return goToSleep(event_time_ms, reason, flags); + } + case IPowerManager::REBOOT: { + CHECK_INTERFACE(IPowerManager, data, reply); + bool confirm = data.readInt32(); + String16 reason = data.readString16(); + bool wait = data.readInt32(); + return reboot(confirm, reason, wait); + } + case IPowerManager::SHUTDOWN: { + CHECK_INTERFACE(IPowerManager, data, reply); + bool confirm = data.readInt32(); + String16 reason = data.readString16(); + bool wait = data.readInt32(); + return shutdown(confirm, reason, wait); + } + case IPowerManager::CRASH: { + CHECK_INTERFACE(IPowerManager, data, reply); + String16 message = data.readString16(); + return crash(message); + } + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace android
diff --git a/nativepower/daemon/main.cc b/nativepower/daemon/main.cc new file mode 100644 index 0000000..479d86f --- /dev/null +++ b/nativepower/daemon/main.cc
@@ -0,0 +1,65 @@ +/* + * 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 <sysexits.h> + +#include <base/logging.h> +#include <base/macros.h> +#include <binderwrapper/binder_wrapper.h> +#include <brillo/binder_watcher.h> +#include <brillo/daemons/daemon.h> +#include <brillo/flag_helper.h> + +#include "power_manager.h" + +namespace { + +class PowerManagerDaemon : public brillo::Daemon { + public: + PowerManagerDaemon() = default; + ~PowerManagerDaemon() override = default; + + private: + // brillo::Daemon: + int OnInit() override { + int result = brillo::Daemon::OnInit(); + if (result != EX_OK) + return result; + + android::BinderWrapper::Create(); + if (!binder_watcher_.Init()) + return EX_OSERR; + if (!power_manager_.Init()) + return EX_OSERR; + + LOG(INFO) << "Initialization complete"; + return EX_OK; + } + + brillo::BinderWatcher binder_watcher_; + android::PowerManager power_manager_; + + DISALLOW_COPY_AND_ASSIGN(PowerManagerDaemon); +}; + +} // namespace + +int main(int argc, char *argv[]) { + // This also initializes base::CommandLine(), which is needed for logging. + brillo::FlagHelper::Init(argc, argv, "Power management daemon"); + logging::InitLogging(logging::LoggingSettings()); + return PowerManagerDaemon().Run(); +}
diff --git a/nativepower/daemon/power_manager.cc b/nativepower/daemon/power_manager.cc new file mode 100644 index 0000000..2f961b7 --- /dev/null +++ b/nativepower/daemon/power_manager.cc
@@ -0,0 +1,173 @@ +/* + * 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
diff --git a/nativepower/daemon/power_manager.h b/nativepower/daemon/power_manager.h new file mode 100644 index 0000000..0428b81 --- /dev/null +++ b/nativepower/daemon/power_manager.h
@@ -0,0 +1,112 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_DAEMON_POWER_MANAGER_H_ +#define SYSTEM_NATIVEPOWER_DAEMON_POWER_MANAGER_H_ + +#include <memory> + +#include <base/files/file_path.h> +#include <base/macros.h> +#include <base/time/time.h> +#include <nativepower/BnPowerManager.h> + +#include "system_property_setter.h" +#include "wake_lock_manager.h" + +namespace android { + +class PowerManager : public BnPowerManager { + public: + // The part of the reboot or shutdown system properties' values that appears + // before the reason. These strings are hardcoded in + // system/core/init/builtins.cpp. + static const char kRebootPrefix[]; + static const char kShutdownPrefix[]; + + // Value written to |power_state_path_| to suspend the system to memory. + static const char kPowerStateSuspend[]; + + PowerManager(); + ~PowerManager() override; + + // Must be called before Init(). + void set_property_setter_for_testing( + std::unique_ptr<SystemPropertySetterInterface> setter) { + property_setter_ = std::move(setter); + } + + // Must be called before Init(). + void set_wake_lock_manager_for_testing( + std::unique_ptr<WakeLockManagerInterface> manager) { + wake_lock_manager_ = std::move(manager); + } + + void set_power_state_path_for_testing(const base::FilePath& path) { + power_state_path_ = path; + } + + // Initializes the object, returning true on success. + bool Init(); + + // BnPowerManager: + status_t acquireWakeLock(int flags, + const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + bool isOneWay=false) override; + status_t acquireWakeLockWithUid(int flags, + const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + int uid, + bool isOneWay=false) override; + status_t releaseWakeLock(const sp<IBinder>& lock, + int flags, + bool isOneWay=false) override; + status_t updateWakeLockUids(const sp<IBinder>& lock, + int len, + const int* uids, + bool isOneWay=false) override; + status_t powerHint(int hintId, int data) override; + status_t goToSleep(int64_t event_time_ms, int reason, int flags) override; + status_t reboot(bool confirm, const String16& reason, bool wait) override; + status_t shutdown(bool confirm, const String16& reason, bool wait) override; + status_t crash(const String16& message) override; + + private: + // Helper method for acquireWakeLock*(). Returns true on success. + bool AddWakeLockRequest(const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + int uid); + + std::unique_ptr<SystemPropertySetterInterface> property_setter_; + std::unique_ptr<WakeLockManagerInterface> wake_lock_manager_; + + // Path to sysfs file that can be written to change the power state. + base::FilePath power_state_path_; + + // System uptime (as duration since boot) when userspace was last resumed from + // suspend. Initially unset. + base::TimeDelta last_resume_uptime_; + + DISALLOW_COPY_AND_ASSIGN(PowerManager); +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_DAEMON_POWER_MANAGER_H_
diff --git a/nativepower/daemon/power_manager_stub.cc b/nativepower/daemon/power_manager_stub.cc new file mode 100644 index 0000000..bb2588a --- /dev/null +++ b/nativepower/daemon/power_manager_stub.cc
@@ -0,0 +1,140 @@ +/* + * 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 <base/format_macros.h> +#include <base/logging.h> +#include <base/strings/stringprintf.h> +#include <binderwrapper/binder_wrapper.h> +#include <nativepower/power_manager_stub.h> +#include <utils/String8.h> + +#include "wake_lock_manager_stub.h" + +namespace android { + +PowerManagerStub::SuspendRequest::SuspendRequest(int64_t event_time_ms, + int reason, + int flags) + : event_time_ms(event_time_ms), + reason(reason), + flags(flags) {} + +// static +std::string PowerManagerStub::ConstructWakeLockString( + const std::string& tag, + const std::string& package, + uid_t uid) { + return WakeLockManagerStub::ConstructRequestString(tag, package, uid); +} + +// static +std::string PowerManagerStub::ConstructSuspendRequestString( + int64_t event_time_ms, + int reason, + int flags) { + return base::StringPrintf("%" PRId64 ",%d,%d", event_time_ms, reason, flags); +} + +PowerManagerStub::PowerManagerStub() + : wake_lock_manager_(new WakeLockManagerStub()) {} + +PowerManagerStub::~PowerManagerStub() = default; + +int PowerManagerStub::GetNumWakeLocks() const { + return wake_lock_manager_->num_requests(); +} + +std::string PowerManagerStub::GetWakeLockString( + const sp<IBinder>& binder) const { + return wake_lock_manager_->GetRequestString(binder); +} + +std::string PowerManagerStub::GetSuspendRequestString(size_t index) const { + if (index >= suspend_requests_.size()) + return std::string(); + + const SuspendRequest& request = suspend_requests_[index]; + return ConstructSuspendRequestString(request.event_time_ms, request.reason, + request.flags); +} + +status_t PowerManagerStub::acquireWakeLock(int flags, + const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + bool isOneWay) { + CHECK(wake_lock_manager_->AddRequest(lock, String8(tag).string(), + String8(packageName).string(), + BinderWrapper::Get()->GetCallingUid())); + return OK; +} + +status_t PowerManagerStub::acquireWakeLockWithUid(int flags, + const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + int uid, + bool isOneWay) { + CHECK(wake_lock_manager_->AddRequest(lock, String8(tag).string(), + String8(packageName).string(), + static_cast<uid_t>(uid))); + return OK; +} + +status_t PowerManagerStub::releaseWakeLock(const sp<IBinder>& lock, + int flags, + bool isOneWay) { + CHECK(wake_lock_manager_->RemoveRequest(lock)); + return OK; +} + +status_t PowerManagerStub::updateWakeLockUids(const sp<IBinder>& lock, + int len, + const int* uids, + bool isOneWay) { + return OK; +} + +status_t PowerManagerStub::powerHint(int hintId, int data) { + return OK; +} + +status_t PowerManagerStub::goToSleep(int64_t event_time_ms, + int reason, + int flags) { + suspend_requests_.emplace_back(event_time_ms, reason, flags); + return OK; +} + +status_t PowerManagerStub::reboot(bool confirm, + const String16& reason, + bool wait) { + reboot_reasons_.push_back(String8(reason).string()); + return OK; +} + +status_t PowerManagerStub::shutdown(bool confirm, + const String16& reason, + bool wait) { + shutdown_reasons_.push_back(String8(reason).string()); + return OK; +} + +status_t PowerManagerStub::crash(const String16& message) { + return OK; +} + +} // namespace android
diff --git a/nativepower/daemon/power_manager_unittest.cc b/nativepower/daemon/power_manager_unittest.cc new file mode 100644 index 0000000..c221ace --- /dev/null +++ b/nativepower/daemon/power_manager_unittest.cc
@@ -0,0 +1,176 @@ +/* + * 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 <base/files/file_util.h> +#include <base/files/scoped_temp_dir.h> +#include <base/macros.h> +#include <base/sys_info.h> +#include <binder/IBinder.h> +#include <binder/IInterface.h> +#include <binderwrapper/binder_test_base.h> +#include <binderwrapper/stub_binder_wrapper.h> +#include <cutils/android_reboot.h> +#include <nativepower/constants.h> +#include <powermanager/PowerManager.h> + +#include "power_manager.h" +#include "system_property_setter_stub.h" +#include "wake_lock_manager_stub.h" + +namespace android { + +class PowerManagerTest : public BinderTestBase { + public: + PowerManagerTest() + : power_manager_(new PowerManager()), + interface_(interface_cast<IPowerManager>(power_manager_)), + property_setter_(new SystemPropertySetterStub()), + wake_lock_manager_(new WakeLockManagerStub()) { + CHECK(temp_dir_.CreateUniqueTempDir()); + + power_state_path_ = temp_dir_.path().Append("power_state"); + power_manager_->set_power_state_path_for_testing(power_state_path_); + ClearPowerState(); + + power_manager_->set_property_setter_for_testing( + std::unique_ptr<SystemPropertySetterInterface>(property_setter_)); + power_manager_->set_wake_lock_manager_for_testing( + std::unique_ptr<WakeLockManagerInterface>(wake_lock_manager_)); + + CHECK(power_manager_->Init()); + } + ~PowerManagerTest() override = default; + + protected: + // Returns the value in |power_state_path_|. + std::string ReadPowerState() { + std::string state; + PCHECK(base::ReadFileToString(power_state_path_, &state)) + << "Failed to read " << power_state_path_.value(); + return state; + } + + // Clears |power_state_path_|. + void ClearPowerState() { + PCHECK(base::WriteFile(power_state_path_, "", 0) == 0) + << "Failed to write " << power_state_path_.value(); + } + + base::ScopedTempDir temp_dir_; + sp<PowerManager> power_manager_; + sp<IPowerManager> interface_; + SystemPropertySetterStub* property_setter_; // Owned by |power_manager_|. + WakeLockManagerStub* wake_lock_manager_; // Owned by |power_manager_|. + + // File under |temp_dir_| used in place of /sys/power/state. + base::FilePath power_state_path_; + + private: + DISALLOW_COPY_AND_ASSIGN(PowerManagerTest); +}; + +TEST_F(PowerManagerTest, RegisterService) { + EXPECT_EQ(power_manager_, + binder_wrapper()->GetRegisteredService(kPowerManagerServiceName)); +} + +TEST_F(PowerManagerTest, AcquireAndReleaseWakeLock) { + const char kTag[] = "foo"; + const char kPackage[] = "bar"; + sp<BBinder> binder = binder_wrapper()->CreateLocalBinder(); + + // Check that PowerManager looks up the calling UID when necessary. + const uid_t kCallingUid = 100; + binder_wrapper()->set_calling_uid(kCallingUid); + EXPECT_EQ(OK, interface_->acquireWakeLock(0, binder, String16(kTag), + String16(kPackage))); + EXPECT_EQ(1, wake_lock_manager_->num_requests()); + EXPECT_EQ( + WakeLockManagerStub::ConstructRequestString(kTag, kPackage, kCallingUid), + wake_lock_manager_->GetRequestString( + binder_wrapper()->local_binders()[0])); + + EXPECT_EQ(OK, interface_->releaseWakeLock(binder, 0)); + EXPECT_EQ(0, wake_lock_manager_->num_requests()); + + // If a UID is passed, it should be used instead. + const uid_t kPassedUid = 200; + EXPECT_EQ(OK, interface_->acquireWakeLockWithUid( + 0, binder, String16(kTag), String16(kPackage), kPassedUid)); + EXPECT_EQ(1, wake_lock_manager_->num_requests()); + EXPECT_EQ( + WakeLockManagerStub::ConstructRequestString(kTag, kPackage, kPassedUid), + wake_lock_manager_->GetRequestString( + binder_wrapper()->local_binders()[0])); +} + +TEST_F(PowerManagerTest, GoToSleep) { + EXPECT_EQ("", ReadPowerState()); + + const int64_t kStartTime = base::SysInfo::Uptime().InMilliseconds(); + EXPECT_EQ(OK, + interface_->goToSleep(kStartTime, 0 /* reason */, 0 /* flags */)); + EXPECT_EQ(PowerManager::kPowerStateSuspend, ReadPowerState()); + + // A request with a timestamp preceding the last resume should be ignored. + ClearPowerState(); + EXPECT_EQ(BAD_VALUE, interface_->goToSleep(kStartTime - 1, 0, 0)); + EXPECT_EQ("", ReadPowerState()); + + // A second attempt with a timestamp occurring after the last + // resume should be honored. + ClearPowerState(); + EXPECT_EQ( + OK, + interface_->goToSleep(base::SysInfo::Uptime().InMilliseconds(), 0, 0)); + EXPECT_EQ(PowerManager::kPowerStateSuspend, ReadPowerState()); +} + +TEST_F(PowerManagerTest, Reboot) { + EXPECT_EQ(OK, interface_->reboot(false, String16(), false)); + EXPECT_EQ(PowerManager::kRebootPrefix, + property_setter_->GetProperty(ANDROID_RB_PROPERTY)); + + EXPECT_EQ(OK, interface_->reboot(false, String16(kRebootReasonRecovery), + false)); + EXPECT_EQ(std::string(PowerManager::kRebootPrefix) + kRebootReasonRecovery, + property_setter_->GetProperty(ANDROID_RB_PROPERTY)); + + // Invalid values should be rejected. + ASSERT_TRUE(property_setter_->SetProperty(ANDROID_RB_PROPERTY, "")); + EXPECT_EQ(BAD_VALUE, interface_->reboot(false, String16("foo"), false)); + EXPECT_EQ("", property_setter_->GetProperty(ANDROID_RB_PROPERTY)); +} + +TEST_F(PowerManagerTest, Shutdown) { + EXPECT_EQ(OK, interface_->shutdown(false, String16(), false)); + EXPECT_EQ(PowerManager::kShutdownPrefix, + property_setter_->GetProperty(ANDROID_RB_PROPERTY)); + + EXPECT_EQ(OK, interface_->shutdown(false, + String16(kShutdownReasonUserRequested), + false)); + EXPECT_EQ(std::string(PowerManager::kShutdownPrefix) + + kShutdownReasonUserRequested, + property_setter_->GetProperty(ANDROID_RB_PROPERTY)); + + // Invalid values should be rejected. + ASSERT_TRUE(property_setter_->SetProperty(ANDROID_RB_PROPERTY, "")); + EXPECT_EQ(BAD_VALUE, interface_->shutdown(false, String16("foo"), false)); + EXPECT_EQ("", property_setter_->GetProperty(ANDROID_RB_PROPERTY)); +} + +} // namespace android
diff --git a/nativepower/daemon/system_property_setter.cc b/nativepower/daemon/system_property_setter.cc new file mode 100644 index 0000000..9368f54 --- /dev/null +++ b/nativepower/daemon/system_property_setter.cc
@@ -0,0 +1,32 @@ +/* + * 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 "system_property_setter.h" + +#include <cutils/properties.h> + +namespace android { + +SystemPropertySetter::SystemPropertySetter() = default; + +SystemPropertySetter::~SystemPropertySetter() = default; + +bool SystemPropertySetter::SetProperty(const std::string& key, + const std::string& value) { + return property_set(key.c_str(), value.c_str()) == 0; +} + +} // namespace android
diff --git a/nativepower/daemon/system_property_setter.h b/nativepower/daemon/system_property_setter.h new file mode 100644 index 0000000..8ccd2c3 --- /dev/null +++ b/nativepower/daemon/system_property_setter.h
@@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_DAEMON_SYSTEM_PROPERTY_SETTER_H_ +#define SYSTEM_NATIVEPOWER_DAEMON_SYSTEM_PROPERTY_SETTER_H_ + +#include <string> + +#include <base/macros.h> + +namespace android { + +// An interface for setting Android system properties. +class SystemPropertySetterInterface { + public: + SystemPropertySetterInterface() {} + virtual ~SystemPropertySetterInterface() {} + + // Sets the property named |key| to |value|, returning true on success. + virtual bool SetProperty(const std::string& key, + const std::string& value) = 0; +}; + +// The real implementation of SystemPropertySetterInterface. +class SystemPropertySetter : public SystemPropertySetterInterface { + public: + SystemPropertySetter(); + ~SystemPropertySetter() override; + + // SystemPropertySetterInterface: + bool SetProperty(const std::string& key, const std::string& value) override; + + private: + DISALLOW_COPY_AND_ASSIGN(SystemPropertySetter); +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_DAEMON_SYSTEM_PROPERTY_SETTER_H_
diff --git a/nativepower/daemon/system_property_setter_stub.cc b/nativepower/daemon/system_property_setter_stub.cc new file mode 100644 index 0000000..d07212f --- /dev/null +++ b/nativepower/daemon/system_property_setter_stub.cc
@@ -0,0 +1,37 @@ +/* + * 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 "system_property_setter_stub.h" + +namespace android { + +SystemPropertySetterStub::SystemPropertySetterStub() = default; + +SystemPropertySetterStub::~SystemPropertySetterStub() = default; + +std::string SystemPropertySetterStub::GetProperty( + const std::string& key) const { + const auto it = properties_.find(key); + return it != properties_.end() ? it->second : std::string(); +} + +bool SystemPropertySetterStub::SetProperty(const std::string& key, + const std::string& value) { + properties_[key] = value; + return true; +} + +} // namespace android
diff --git a/nativepower/daemon/system_property_setter_stub.h b/nativepower/daemon/system_property_setter_stub.h new file mode 100644 index 0000000..b84a72a --- /dev/null +++ b/nativepower/daemon/system_property_setter_stub.h
@@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_DAEMON_SYSTEM_PROPERTY_SETTER_STUB_H_ +#define SYSTEM_NATIVEPOWER_DAEMON_SYSTEM_PROPERTY_SETTER_STUB_H_ + +#include <map> +#include <string> + +#include <base/macros.h> + +#include "system_property_setter.h" + +namespace android { + +// A stub implementation of SystemPropertySetterInterface for use by tests. +class SystemPropertySetterStub : public SystemPropertySetterInterface { + public: + SystemPropertySetterStub(); + ~SystemPropertySetterStub() override; + + // Returns the value for |key|. An empty string is returned for an unset + // property. + std::string GetProperty(const std::string& key) const; + + // SystemPropertySetterInterface: + bool SetProperty(const std::string& key, const std::string& value) override; + + private: + std::map<std::string, std::string> properties_; + + DISALLOW_COPY_AND_ASSIGN(SystemPropertySetterStub); +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_DAEMON_SYSTEM_PROPERTY_SETTER_STUB_H_
diff --git a/nativepower/daemon/wake_lock_manager.cc b/nativepower/daemon/wake_lock_manager.cc new file mode 100644 index 0000000..37de1e3 --- /dev/null +++ b/nativepower/daemon/wake_lock_manager.cc
@@ -0,0 +1,130 @@ +/* + * 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 "wake_lock_manager.h" + +#include <base/bind.h> +#include <base/files/file_util.h> +#include <base/format_macros.h> +#include <base/logging.h> +#include <base/strings/stringprintf.h> +#include <binder/IBinder.h> +#include <binderwrapper/binder_wrapper.h> + +namespace android { +namespace { + +// Paths to the sysfs lock and unlock files. +const char kLockPath[] = "/sys/power/wake_lock"; +const char kUnlockPath[] = "/sys/power/wake_unlock"; + +// Writes |data| to |path|, returning true on success or logging an error and +// returning false otherwise. +bool WriteToFile(const base::FilePath& path, const std::string& data) { + // This are sysfs "files" in real life, so it doesn't matter if we overwrite + // them or append to them, but appending makes it easier for tests to detect + // multiple writes when using real temporary files. + VLOG(1) << "Writing \"" << data << "\" to " << path.value(); + if (!base::AppendToFile(path, data.data(), data.size())) { + PLOG(ERROR) << "Failed to write \"" << data << "\" to " << path.value(); + return false; + } + return true; +} + +} // namespace + +const char WakeLockManager::kLockName[] = "nativepowerman"; + +WakeLockManager::Request::Request(const std::string& tag, + const std::string& package, + uid_t uid) + : tag(tag), + package(package), + uid(uid) {} + +WakeLockManager::Request::Request(const Request& request) = default; + +WakeLockManager::Request::Request() : uid(-1) {} + +WakeLockManager::WakeLockManager() + : lock_path_(kLockPath), + unlock_path_(kUnlockPath) {} + +WakeLockManager::~WakeLockManager() { + while (!requests_.empty()) + RemoveRequest(requests_.begin()->first); +} + +bool WakeLockManager::Init() { + if (!base::PathIsWritable(lock_path_) || + !base::PathIsWritable(unlock_path_)) { + LOG(ERROR) << lock_path_.value() << " and/or " << unlock_path_.value() + << " are not writable"; + return false; + } + return true; +} + +bool WakeLockManager::AddRequest(sp<IBinder> client_binder, + const std::string& tag, + const std::string& package, + uid_t uid) { + const bool new_request = !requests_.count(client_binder); + LOG(INFO) << (new_request ? "Adding" : "Updating") << " request for binder " + << client_binder.get() << ": tag=\"" << tag << "\"" + << " package=\"" << package << "\" uid=" << uid; + + const bool first_request = requests_.empty(); + + if (new_request) { + if (!BinderWrapper::Get()->RegisterForDeathNotifications( + client_binder, + base::Bind(&WakeLockManager::HandleBinderDeath, + base::Unretained(this), client_binder))) { + return false; + } + } + requests_[client_binder] = Request(tag, package, uid); + + if (first_request && !WriteToFile(lock_path_, kLockName)) + return false; + + return true; +} + +bool WakeLockManager::RemoveRequest(sp<IBinder> client_binder) { + LOG(INFO) << "Removing request for binder " << client_binder.get(); + + if (!requests_.erase(client_binder)) { + LOG(WARNING) << "Ignoring removal request for unknown binder " + << client_binder.get(); + return false; + } + BinderWrapper::Get()->UnregisterForDeathNotifications(client_binder); + + if (requests_.empty() && !WriteToFile(unlock_path_, kLockName)) + return false; + + return true; +} + +void WakeLockManager::HandleBinderDeath(sp<IBinder> binder) { + LOG(INFO) << "Received death notification for binder " << binder.get(); + RemoveRequest(binder); +} + +} // namespace android
diff --git a/nativepower/daemon/wake_lock_manager.h b/nativepower/daemon/wake_lock_manager.h new file mode 100644 index 0000000..cc4dcc9 --- /dev/null +++ b/nativepower/daemon/wake_lock_manager.h
@@ -0,0 +1,95 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_DAEMON_WAKE_LOCK_MANAGER_H_ +#define SYSTEM_NATIVEPOWER_DAEMON_WAKE_LOCK_MANAGER_H_ + +#include <sys/types.h> + +#include <map> +#include <string> + +#include <base/files/file_path.h> +#include <base/macros.h> +#include <base/time/time.h> +#include <utils/StrongPointer.h> + +namespace android { + +class IBinder; + +class WakeLockManagerInterface { + public: + WakeLockManagerInterface() {} + virtual ~WakeLockManagerInterface() {} + + virtual bool AddRequest(sp<IBinder> client_binder, + const std::string& tag, + const std::string& package, + uid_t uid) = 0; + virtual bool RemoveRequest(sp<IBinder> client_binder) = 0; + + protected: + // Information about a request from a client. + struct Request { + Request(const std::string& tag, const std::string& package, uid_t uid); + Request(const Request& request); + Request(); + + std::string tag; + std::string package; + uid_t uid; + }; +}; + +class WakeLockManager : public WakeLockManagerInterface { + public: + // Name of the kernel wake lock created by this class. + static const char kLockName[]; + + WakeLockManager(); + ~WakeLockManager() override; + + void set_paths_for_testing(const base::FilePath& lock_path, + const base::FilePath& unlock_path) { + lock_path_ = lock_path; + unlock_path_ = unlock_path; + } + + bool Init(); + + // WakeLockManagerInterface: + bool AddRequest(sp<IBinder> client_binder, + const std::string& tag, + const std::string& package, + uid_t uid) override; + bool RemoveRequest(sp<IBinder> client_binder) override; + + private: + void HandleBinderDeath(sp<IBinder> binder); + + base::FilePath lock_path_; + base::FilePath unlock_path_; + + // Currently-active requests, keyed by client binders. + std::map<sp<IBinder>, Request> requests_; + + DISALLOW_COPY_AND_ASSIGN(WakeLockManager); +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_DAEMON_WAKE_LOCK_MANAGER_H_
diff --git a/nativepower/daemon/wake_lock_manager_stub.cc b/nativepower/daemon/wake_lock_manager_stub.cc new file mode 100644 index 0000000..3b56c4e --- /dev/null +++ b/nativepower/daemon/wake_lock_manager_stub.cc
@@ -0,0 +1,62 @@ +/* + * 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 "wake_lock_manager_stub.h" + +#include <base/strings/stringprintf.h> +#include <binder/IBinder.h> + +namespace android { + +// static +std::string WakeLockManagerStub::ConstructRequestString( + const std::string& tag, + const std::string& package, + uid_t uid) { + return base::StringPrintf("%s,%s,%d", tag.c_str(), package.c_str(), uid); +} + +WakeLockManagerStub::WakeLockManagerStub() = default; + +WakeLockManagerStub::~WakeLockManagerStub() = default; + +std::string WakeLockManagerStub::GetRequestString( + const sp<IBinder>& binder) const { + const auto it = requests_.find(binder); + if (it == requests_.end()) + return std::string(); + + const Request& req = it->second; + return ConstructRequestString(req.tag, req.package, req.uid); +} + +bool WakeLockManagerStub::AddRequest(sp<IBinder> client_binder, + const std::string& tag, + const std::string& package, + uid_t uid) { + requests_[client_binder] = Request(tag, package, uid); + return true; +} + +bool WakeLockManagerStub::RemoveRequest(sp<IBinder> client_binder) { + if (!requests_.count(client_binder)) + return false; + + requests_.erase(client_binder); + return true; +} + +} // namespace android
diff --git a/nativepower/daemon/wake_lock_manager_stub.h b/nativepower/daemon/wake_lock_manager_stub.h new file mode 100644 index 0000000..d720143 --- /dev/null +++ b/nativepower/daemon/wake_lock_manager_stub.h
@@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_DAEMON_WAKE_LOCK_MANAGER_STUB_H_ +#define SYSTEM_NATIVEPOWER_DAEMON_WAKE_LOCK_MANAGER_STUB_H_ + +#include <set> +#include <string> +#include <sys/types.h> + +#include <base/macros.h> +#include <utils/StrongPointer.h> + +#include "wake_lock_manager.h" + +namespace android { + +class IBinder; + +// Stub implementation used by tests. +class WakeLockManagerStub : public WakeLockManagerInterface { + public: + WakeLockManagerStub(); + ~WakeLockManagerStub() override; + + // Constructs a string that can be compared with one returned by + // GetRequestString(). + static std::string ConstructRequestString(const std::string& tag, + const std::string& package, + uid_t uid); + + int num_requests() const { return requests_.size(); } + + // Returns a string describing the request associated with |binder|, or an + // empty string if no request is present. + std::string GetRequestString(const sp<IBinder>& binder) const; + + // WakeLockManagerInterface: + bool AddRequest(sp<IBinder> client_binder, + const std::string& tag, + const std::string& package, + uid_t uid) override; + bool RemoveRequest(sp<IBinder> client_binder) override; + + private: + // Currently-active requests, keyed by client binders. + std::map<sp<IBinder>, Request> requests_; + + DISALLOW_COPY_AND_ASSIGN(WakeLockManagerStub); +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_DAEMON_WAKE_LOCK_MANAGER_STUB_H_
diff --git a/nativepower/daemon/wake_lock_manager_unittest.cc b/nativepower/daemon/wake_lock_manager_unittest.cc new file mode 100644 index 0000000..887b564 --- /dev/null +++ b/nativepower/daemon/wake_lock_manager_unittest.cc
@@ -0,0 +1,142 @@ +/* + * 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 <base/files/file_path.h> +#include <base/files/file_util.h> +#include <base/files/scoped_temp_dir.h> +#include <base/logging.h> +#include <base/macros.h> +#include <binder/IBinder.h> +#include <binderwrapper/binder_test_base.h> +#include <binderwrapper/stub_binder_wrapper.h> + +#include "wake_lock_manager.h" + +namespace android { + +class WakeLockManagerTest : public BinderTestBase { + public: + WakeLockManagerTest() { + CHECK(temp_dir_.CreateUniqueTempDir()); + lock_path_ = temp_dir_.path().Append("lock"); + unlock_path_ = temp_dir_.path().Append("unlock"); + ClearFiles(); + + manager_.set_paths_for_testing(lock_path_, unlock_path_); + CHECK(manager_.Init()); + } + ~WakeLockManagerTest() override = default; + + protected: + // Returns the contents of |path|. + std::string ReadFile(const base::FilePath& path) const { + std::string value; + CHECK(base::ReadFileToString(path, &value)); + return value; + } + + // Clears |lock_path_| and |unlock_path_|. + void ClearFiles() { + CHECK(base::WriteFile(lock_path_, "", 0) == 0); + CHECK(base::WriteFile(unlock_path_, "", 0) == 0); + } + + base::ScopedTempDir temp_dir_; + + // Files within |temp_dir_| simulating /sys/power/wake_lock and wake_unlock. + base::FilePath lock_path_; + base::FilePath unlock_path_; + + WakeLockManager manager_; + + private: + DISALLOW_COPY_AND_ASSIGN(WakeLockManagerTest); +}; + +TEST_F(WakeLockManagerTest, AddAndRemoveRequests) { + // A kernel wake lock should be created for the first request. + sp<BBinder> binder1 = binder_wrapper()->CreateLocalBinder(); + EXPECT_TRUE(manager_.AddRequest(binder1, "1", "1", -1)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); + + // Nothing should happen when a second request is made. + ClearFiles(); + sp<BBinder> binder2 = binder_wrapper()->CreateLocalBinder(); + EXPECT_TRUE(manager_.AddRequest(binder2, "2", "2", -1)); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); + + // The wake lock should still be held after the first request is withdrawn. + ClearFiles(); + EXPECT_TRUE(manager_.RemoveRequest(binder1)); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); + + // When there are no more requests, the wake lock should be released. + ClearFiles(); + EXPECT_TRUE(manager_.RemoveRequest(binder2)); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(unlock_path_)); +} + +TEST_F(WakeLockManagerTest, DuplicateRequest) { + sp<BBinder> binder = binder_wrapper()->CreateLocalBinder(); + EXPECT_TRUE(manager_.AddRequest(binder, "foo", "bar", -1)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); + + // Send a second request using the same binder and check a new wake lock isn't + // created. + ClearFiles(); + EXPECT_TRUE(manager_.AddRequest(binder, "a", "b", -1)); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); + + ClearFiles(); + EXPECT_TRUE(manager_.RemoveRequest(binder)); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(unlock_path_)); +} + +TEST_F(WakeLockManagerTest, InvalidRemoval) { + // Trying to remove an unknown binder should fail and not do anything. + sp<BBinder> binder = binder_wrapper()->CreateLocalBinder(); + EXPECT_FALSE(manager_.RemoveRequest(binder)); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); +} + +TEST_F(WakeLockManagerTest, BinderDeath) { + sp<BBinder> binder = binder_wrapper()->CreateLocalBinder(); + EXPECT_TRUE(manager_.AddRequest(binder, "foo", "bar", -1)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); + + // If the binder dies, the wake lock should be released. + ClearFiles(); + binder_wrapper()->NotifyAboutBinderDeath(binder); + EXPECT_EQ("", ReadFile(lock_path_)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(unlock_path_)); + + // Check that a new request can be created using the same binder. + ClearFiles(); + EXPECT_TRUE(manager_.AddRequest(binder, "foo", "bar", -1)); + EXPECT_EQ(WakeLockManager::kLockName, ReadFile(lock_path_)); + EXPECT_EQ("", ReadFile(unlock_path_)); +} + +} // namespace android
diff --git a/nativepower/example/Android.mk b/nativepower/example/Android.mk new file mode 100644 index 0000000..88ad156 --- /dev/null +++ b/nativepower/example/Android.mk
@@ -0,0 +1,39 @@ +# +# 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. +# + +LOCAL_PATH := $(call my-dir) + +# power_example executable +# ======================================================== + +include $(CLEAR_VARS) +LOCAL_MODULE := power_example +LOCAL_CPP_EXTENSION := .cc +LOCAL_CFLAGS := -Wall -Werror -Wno-unused-parameter +LOCAL_CFLAGS += -Wno-sign-promo # for libchrome +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + libbinderwrapper \ + libbrillo \ + libchrome \ + libnativepower \ + libpowermanager \ + libutils \ + +LOCAL_SRC_FILES := \ + power_example.cc \ + +include $(BUILD_EXECUTABLE)
diff --git a/nativepower/example/power_example.cc b/nativepower/example/power_example.cc new file mode 100644 index 0000000..494c052 --- /dev/null +++ b/nativepower/example/power_example.cc
@@ -0,0 +1,75 @@ +/* + * 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 <unistd.h> + +#include <memory> + +#include <base/at_exit.h> +#include <base/logging.h> +#include <base/message_loop/message_loop.h> +#include <base/sys_info.h> +#include <base/time/time.h> +#include <binderwrapper/binder_wrapper.h> +#include <brillo/flag_helper.h> +#include <nativepower/power_manager_client.h> +#include <nativepower/wake_lock.h> + +namespace { + +// Seconds to sleep after acquiring a wake lock. +const int kWakeLockSleepSec = 5; + +} // namespace + +int main(int argc, char *argv[]) { + DEFINE_string(action, "", + "Action to perform (\"reboot\", \"shut_down\", \"suspend\", " + "\"wake_lock\")"); + + brillo::FlagHelper::Init(argc, argv, "Example power-management client."); + logging::InitLogging(logging::LoggingSettings()); + base::AtExitManager at_exit; + base::MessageLoopForIO loop; + android::BinderWrapper::Create(); + + android::PowerManagerClient client; + CHECK(client.Init()); + + if (FLAGS_action == "reboot") { + LOG(INFO) << "Requesting reboot"; + CHECK(client.Reboot(android::RebootReason::DEFAULT)); + } else if (FLAGS_action == "shut_down") { + LOG(INFO) << "Requesting shutdown"; + CHECK(client.ShutDown(android::ShutdownReason::DEFAULT)); + } else if (FLAGS_action == "suspend") { + LOG(INFO) << "Requesting suspend"; + CHECK(client.Suspend(base::SysInfo::Uptime(), + android::SuspendReason::APPLICATION, 0 /* flags */)); + } else if (FLAGS_action == "wake_lock") { + LOG(INFO) << "Creating wake lock"; + std::unique_ptr<android::WakeLock> lock( + client.CreateWakeLock("power_example", "power")); + CHECK(lock) << "Lock not created"; + LOG(INFO) << "Sleeping for " << kWakeLockSleepSec << " seconds"; + sleep(kWakeLockSleepSec); + } else { + LOG(FATAL) << "Unknown action \"" << FLAGS_action << "\""; + } + + LOG(INFO) << "Exiting"; + return 0; +}
diff --git a/nativepower/include/nativepower/BnPowerManager.h b/nativepower/include/nativepower/BnPowerManager.h new file mode 100644 index 0000000..db14ef3 --- /dev/null +++ b/nativepower/include/nativepower/BnPowerManager.h
@@ -0,0 +1,37 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_BN_POWER_MANAGER_H_ +#define SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_BN_POWER_MANAGER_H_ + +#include <binder/IInterface.h> +#include <powermanager/IPowerManager.h> + +namespace android { + +// Receiver-side binder implementation. +class BnPowerManager : public BnInterface<IPowerManager> { +public: + // BnInterface: + status_t onTransact(uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags=0) override; +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_BN_POWER_MANAGER_H_
diff --git a/nativepower/include/nativepower/constants.h b/nativepower/include/nativepower/constants.h new file mode 100644 index 0000000..9ceeb40 --- /dev/null +++ b/nativepower/include/nativepower/constants.h
@@ -0,0 +1,32 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_CONSTANTS_H_ +#define SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_CONSTANTS_H_ + +namespace android { + +// Name used to register the power manager with the service manager. +const char kPowerManagerServiceName[] = "power"; + +// Reasons that can be supplied for reboot or shutdown requests. +// These strings are hardcoded in system/core/init/builtins.cpp. +const char kRebootReasonRecovery[] = "recovery"; +const char kShutdownReasonUserRequested[] = "userrequested"; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_CONSTANTS_H_
diff --git a/nativepower/include/nativepower/power_manager_client.h b/nativepower/include/nativepower/power_manager_client.h new file mode 100644 index 0000000..e8528b4 --- /dev/null +++ b/nativepower/include/nativepower/power_manager_client.h
@@ -0,0 +1,106 @@ +/* + * 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 <string> + +#include <base/macros.h> +#include <base/memory/weak_ptr.h> +#include <base/time/time.h> +#include <nativepower/wake_lock.h> +#include <powermanager/IPowerManager.h> +#include <utils/StrongPointer.h> + +namespace android { + +// Reasons that can be passed to PowerManagerClient::Suspend(). +enum class SuspendReason { + // These values must match the ones in android.os.PowerManager. + APPLICATION = 0, + DEVICE_ADMIN = 1, + TIMEOUT = 2, + LID_SWITCH = 3, + POWER_BUTTON = 4, + HDMI = 5, + SLEEP_BUTTON = 6, +}; + +enum class SuspendFlags { + // Corresponds to GO_TO_SLEEP_FLAG_NO_DOZE in android.os.PowerManager. + NO_DOZE = 1 << 0, +}; + +// Reasons that can be passed to PowerManagerClient::ShutDown(). +enum class ShutdownReason { + DEFAULT, + USER_REQUESTED, +}; + +// Reasons that can be passed to PowerManagerClient::Reboot(). +enum class RebootReason { + DEFAULT, + RECOVERY, +}; + +// Class used to communicate with the system power manager. +// +// android::BinderWrapper must be initialized before constructing this class. +class PowerManagerClient { + public: + PowerManagerClient(); + ~PowerManagerClient(); + + // This should not be used directly; it's just exposed for WakeLock. + const sp<IPowerManager>& power_manager() { return power_manager_; } + + // Initializes the object, returning true on success. Must be called before + // any other methods. + bool Init(); + + // Creates and returns a wake lock identified by |tag| and |package|. The + // returned WakeLock object will block power management until it is destroyed. + // An empty pointer is returned on failure (e.g. due to issues communicating + // with the power manager). + std::unique_ptr<WakeLock> CreateWakeLock(const std::string& tag, + const std::string& package); + + // Suspends the system immediately, returning true on success. + // + // |event_uptime| contains the time since the system was booted (e.g. + // base::SysInfo::Uptime()) of the event that triggered the suspend request. + // It is used to avoid acting on stale suspend requests that are sent before + // the currently-active suspend request completes. + // |reason| is currently only used by android.view.WindowManagerPolicy. + // |flags| is a bitfield of SuspendFlag values. + bool Suspend(base::TimeDelta event_uptime, SuspendReason reason, int flags); + + // Shuts down or reboots the system, returning true on success. + bool ShutDown(ShutdownReason reason); + bool Reboot(RebootReason reason); + + private: + // Called in response to |power_manager_|'s binder dying. + void OnPowerManagerDied(); + + // Interface for communicating with the power manager. + sp<IPowerManager> power_manager_; + + // Keep this member last. + base::WeakPtrFactory<PowerManagerClient> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(PowerManagerClient); +}; + +} // namespace android
diff --git a/nativepower/include/nativepower/power_manager_stub.h b/nativepower/include/nativepower/power_manager_stub.h new file mode 100644 index 0000000..572a403 --- /dev/null +++ b/nativepower/include/nativepower/power_manager_stub.h
@@ -0,0 +1,118 @@ +/* + * 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 <sys/types.h> + +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include <base/macros.h> +#include <nativepower/BnPowerManager.h> + +namespace android { + +class WakeLockManagerStub; + +// Stub implementation of BnPowerManager for use in tests. +// +// The BinderWrapper singleton must be initialized before using this class. +class PowerManagerStub : public BnPowerManager { + public: + PowerManagerStub(); + ~PowerManagerStub() override; + + // Constructs a string that can be compared with one returned by + // GetWakeLockString(). + static std::string ConstructWakeLockString(const std::string& tag, + const std::string& package, + uid_t uid); + + // Constructs a string that can be compared with one returned by + // GetSuspendRequestString(). + static std::string ConstructSuspendRequestString(int64_t event_time_ms, + int reason, + int flags); + + size_t num_suspend_requests() const { return suspend_requests_.size(); } + const std::vector<std::string>& reboot_reasons() const { + return reboot_reasons_; + } + const std::vector<std::string>& shutdown_reasons() const { + return shutdown_reasons_; + } + + // Returns the number of currently-registered wake locks. + int GetNumWakeLocks() const; + + // Returns a string describing the wake lock registered for |binder|, or an + // empty string if no wake lock is present. + std::string GetWakeLockString(const sp<IBinder>& binder) const; + + // Returns a string describing position |index| in |suspend_requests_|. + std::string GetSuspendRequestString(size_t index) const; + + // BnPowerManager: + status_t acquireWakeLock(int flags, + const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + bool isOneWay=false) override; + status_t acquireWakeLockWithUid(int flags, + const sp<IBinder>& lock, + const String16& tag, + const String16& packageName, + int uid, + bool isOneWay=false) override; + status_t releaseWakeLock(const sp<IBinder>& lock, + int flags, + bool isOneWay=false) override; + status_t updateWakeLockUids(const sp<IBinder>& lock, + int len, + const int* uids, + bool isOneWay=false) override; + status_t powerHint(int hintId, int data) override; + status_t goToSleep(int64_t event_time_ms, int reason, int flags) override; + status_t reboot(bool confirm, const String16& reason, bool wait) override; + status_t shutdown(bool confirm, const String16& reason, bool wait) override; + status_t crash(const String16& message) override; + + private: + // Details about a request passed to goToSleep(). + struct SuspendRequest { + SuspendRequest(int64_t uptime_ms, int reason, int flags); + + int64_t event_time_ms; + int reason; + int flags; + }; + + std::unique_ptr<WakeLockManagerStub> wake_lock_manager_; + + // Information about calls to goToSleep(), in the order they were made. + using SuspendRequests = std::vector<SuspendRequest>; + SuspendRequests suspend_requests_; + + // Reasons passed to reboot() and shutdown(), in the order in which they were + // received. + std::vector<std::string> reboot_reasons_; + std::vector<std::string> shutdown_reasons_; + + DISALLOW_COPY_AND_ASSIGN(PowerManagerStub); +}; + +} // namespace android
diff --git a/nativepower/include/nativepower/wake_lock.h b/nativepower/include/nativepower/wake_lock.h new file mode 100644 index 0000000..faa9d8a --- /dev/null +++ b/nativepower/include/nativepower/wake_lock.h
@@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_WAKE_LOCK_H_ +#define SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_WAKE_LOCK_H_ + +#include <string> + +#include <base/macros.h> +#include <utils/StrongPointer.h> + +namespace android { + +class IBinder; +class PowerManagerClient; + +// RAII-style class that prevents the system from suspending. +// +// Instantiate by calling PowerManagerClient::CreateWakeLock(). +class WakeLock { + public: + ~WakeLock(); + + private: + friend class PowerManagerClient; + + // Ownership of |client| remains with the caller. + WakeLock(const std::string& tag, + const std::string& package, + PowerManagerClient* client); + + // Initializes the object and acquires the lock, returning true on success. + bool Init(); + + // Was a lock successfully acquired from the power manager? + bool acquired_lock_; + + std::string tag_; + std::string package_; + + // Weak pointer to the client that created this wake lock. + PowerManagerClient* client_; + + // Locally-created binder passed to the power manager. + sp<IBinder> lock_binder_; + + DISALLOW_COPY_AND_ASSIGN(WakeLock); +}; + +} // namespace android + +#endif // SYSTEM_NATIVEPOWER_INCLUDE_NATIVEPOWER_WAKE_LOCK_H_