summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTri Vo <trong@google.com>2019-06-20 15:25:39 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-06-20 15:25:39 -0700
commit8fbabc2d9a8c3547ad2a2e6cd325a77b7fb7346e (patch)
tree75c87d6bc7668279b07bdf86a1bd09ff66e1c1c3
parentd48d28f04253b33d7c991bcf7cacb1a6196d0374 (diff)
parentcc685232f760dcec1384db1c455d93b766f080ba (diff)
downloadplatform_hardware_libhardware_legacy-8fbabc2d9a8c3547ad2a2e6cd325a77b7fb7346e.tar.gz
platform_hardware_libhardware_legacy-8fbabc2d9a8c3547ad2a2e6cd325a77b7fb7346e.tar.bz2
platform_hardware_libhardware_legacy-8fbabc2d9a8c3547ad2a2e6cd325a77b7fb7346e.zip
Merge "libpower: RAII wake lock implementation"
am: cc685232f7 Change-Id: Ia6a2bbfe192b7fccfe1ac0f8b10c3a420460c24c
-rw-r--r--Android.bp5
-rw-r--r--include/hardware_legacy/power.h26
-rw-r--r--power.cpp25
-rw-r--r--power_test.cpp60
4 files changed, 107 insertions, 9 deletions
diff --git a/Android.bp b/Android.bp
index d198b18..bc453fe 100644
--- a/Android.bp
+++ b/Android.bp
@@ -35,7 +35,10 @@ cc_test {
defaults: ["libpower_defaults"],
srcs: ["power_test.cpp"],
static_libs: ["libpower"],
- shared_libs: ["android.system.suspend@1.0"],
+ shared_libs: [
+ "android.system.suspend@1.0",
+ "suspend_control_aidl_interface-cpp",
+ ],
test_suites: ["device-tests"],
require_root: true,
}
diff --git a/include/hardware_legacy/power.h b/include/hardware_legacy/power.h
index 604e0ed..a053583 100644
--- a/include/hardware_legacy/power.h
+++ b/include/hardware_legacy/power.h
@@ -17,6 +17,10 @@
#ifndef _HARDWARE_POWER_H
#define _HARDWARE_POWER_H
+#if __cplusplus
+#include <memory>
+#include <string>
+#endif
#include <stdint.h>
#if __cplusplus
@@ -33,9 +37,27 @@ enum {
int acquire_wake_lock(int lock, const char* id);
int release_wake_lock(const char* id);
+#if __cplusplus
+} // extern "C"
+#endif
#if __cplusplus
-} // extern "C"
+// RAII way to acquire wake locks.
+namespace android {
+namespace power {
+
+class WakeLock {
+ public:
+ WakeLock(const std::string& name);
+ ~WakeLock();
+
+ private:
+ class WakeLockImpl;
+ std::unique_ptr<WakeLockImpl> mImpl;
+};
+
+} // namespace power
+} // namespace android
#endif
-#endif // _HARDWARE_POWER_H
+#endif // _HARDWARE_POWER_H
diff --git a/power.cpp b/power.cpp
index 74abac9..39084d7 100644
--- a/power.cpp
+++ b/power.cpp
@@ -78,3 +78,28 @@ int release_wake_lock(const char* id) {
}
return -1;
}
+
+namespace android::power {
+
+WakeLock::WakeLock(const std::string& name) : mImpl(std::make_unique<WakeLockImpl>(name)) {}
+
+WakeLock::~WakeLock() = default;
+
+class WakeLock::WakeLockImpl {
+ public:
+ WakeLockImpl(const std::string& name) : mWakeLock(nullptr) {
+ static sp<ISystemSuspend> suspendService = ISystemSuspend::getService();
+ mWakeLock = suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
+ }
+ ~WakeLockImpl() {
+ auto ret = mWakeLock->release();
+ if (!ret.isOk()) {
+ LOG(ERROR) << "IWakeLock::release() call failed: " << ret.description();
+ }
+ }
+
+ private:
+ sp<IWakeLock> mWakeLock;
+};
+
+} // namespace android::power
diff --git a/power_test.cpp b/power_test.cpp
index 1ade263..5ae19d6 100644
--- a/power_test.cpp
+++ b/power_test.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#include <android/system/suspend/ISuspendControlService.h>
+#include <binder/IServiceManager.h>
+#include <gtest/gtest.h>
#include <hardware_legacy/power.h>
#include <csignal>
@@ -22,8 +25,9 @@
#include <thread>
#include <vector>
-#include <gtest/gtest.h>
-
+using android::sp;
+using android::system::suspend::ISuspendControlService;
+using android::system::suspend::WakeLockInfo;
using namespace std::chrono_literals;
namespace android {
@@ -73,10 +77,8 @@ TEST(LibpowerTest, WakeLockStressTest) {
for (int j = 0; j < numLocks; j++) {
// We want ids to be unique.
std::string id = std::to_string(i) + "/" + std::to_string(j);
- ASSERT_EQ(acquire_wake_lock(PARTIAL_WAKE_LOCK, id.c_str()), 0)
- << "id: " << id;
- ASSERT_EQ(release_wake_lock(id.c_str()), 0)
- << "id: " << id;;
+ ASSERT_EQ(acquire_wake_lock(PARTIAL_WAKE_LOCK, id.c_str()), 0) << "id: " << id;
+ ASSERT_EQ(release_wake_lock(id.c_str()), 0) << "id: " << id;
}
});
}
@@ -85,4 +87,50 @@ TEST(LibpowerTest, WakeLockStressTest) {
}
}
+// Returns true iff found.
+bool findWakeLockInfoByName(
+ const sp<ISuspendControlService>& service,
+ const std::string& name,
+ WakeLockInfo* info) {
+ std::vector<WakeLockInfo> wlStats;
+ service->getWakeLockStats(&wlStats);
+ auto it = std::find_if(wlStats.begin(), wlStats.end(),
+ [&name](const auto& x) { return x.name == name; });
+ if (it != wlStats.end()) {
+ *info = *it;
+ return true;
+ }
+ return false;
+}
+
+// Test RAII properties of WakeLock class.
+TEST(LibpowerTest, RAIIWakeLock) {
+ sp<IBinder> control =
+ android::defaultServiceManager()->getService(android::String16("suspend_control"));
+ ASSERT_NE(control, nullptr) << "failed to get the suspend control service";
+ sp<ISuspendControlService> controlService = interface_cast<ISuspendControlService>(control);
+
+ auto name = std::to_string(rand());
+ {
+ android::power::WakeLock wl{name};
+
+ WakeLockInfo info;
+ auto success = findWakeLockInfoByName(controlService, name, &info);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(info.name, name);
+ ASSERT_EQ(info.pid, getpid());
+ ASSERT_TRUE(info.isActive);
+ }
+
+ // SystemSuspend receives wake lock release requests on hwbinder thread, while stats requests
+ // come on binder thread. Sleep to make sure that stats are reported *after* wake lock release.
+ std::this_thread::sleep_for(1ms);
+ WakeLockInfo info;
+ auto success = findWakeLockInfoByName(controlService, name, &info);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(info.name, name);
+ ASSERT_EQ(info.pid, getpid());
+ ASSERT_FALSE(info.isActive);
+}
+
} // namespace android