diff options
author | Tri Vo <trong@google.com> | 2018-11-29 11:40:28 -0800 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-11-29 11:40:28 -0800 |
commit | a376f0ceacd55e0be20f55f5553298e8d1b624f8 (patch) | |
tree | 26ec92187e8baa8e516fb05cfcce22e934c73bdd | |
parent | 88479ce7a443655c7ff1915aa696f225f27b6286 (diff) | |
parent | d3429a0c7299540e47bd4d51dce7a82bcaa3fc39 (diff) | |
download | libhardware_legacy-a376f0ceacd55e0be20f55f5553298e8d1b624f8.tar.gz |
Merge "Handle concurrent exit and wake lock acquisition." am: 8803d61599 am: b69e9a62c7
am: d3429a0c72
Change-Id: I423a17cfd5b25d4dc7cce7d3191f637bf9106b45
-rw-r--r-- | Android.bp | 18 | ||||
-rw-r--r-- | power.cpp | 26 | ||||
-rw-r--r-- | power_test.cpp | 39 |
3 files changed, 53 insertions, 30 deletions
@@ -9,9 +9,18 @@ cc_library_headers { export_header_lib_headers: ["libcutils_headers"], } +cc_defaults { + name: "libpower_defaults", + defaults: ["system_suspend_defaults"], + cflags: [ + "-Wexit-time-destructors", + "-fno-c++-static-destructors", + ], +} + cc_library { name: "libpower", - defaults: ["system_suspend_defaults"], + defaults: ["libpower_defaults"], srcs: ["power.cpp"], export_include_dirs: ["include"], shared_libs: ["android.system.suspend@1.0"], @@ -23,14 +32,15 @@ cc_library { cc_test { name: "libpower_test", - defaults: ["system_suspend_defaults"], + defaults: ["libpower_defaults"], srcs: ["power_test.cpp"], - shared_libs: ["libpower"], + static_libs: ["libpower"], + shared_libs: ["android.system.suspend@1.0"], } cc_library_shared { name: "libhardware_legacy", - defaults: ["system_suspend_defaults"], + defaults: ["libpower_defaults"], vendor_available: true, vndk: { enabled: true, @@ -18,7 +18,6 @@ #define ATRACE_TAG ATRACE_TAG_POWER #include <android-base/logging.h> -#include <android/system/suspend/1.0/BpHwSystemSuspend.h> #include <android/system/suspend/1.0/ISystemSuspend.h> #include <hardware_legacy/power.h> #include <utils/Trace.h> @@ -37,30 +36,7 @@ static std::mutex gLock; static std::unordered_map<std::string, sp<IWakeLock>> gWakeLockMap; static const sp<ISystemSuspend>& getSystemSuspendServiceOnce() { - using android::system::suspend::V1_0::BpHwSystemSuspend; - static std::once_flag initFlag; - static sp<ISystemSuspend> suspendService = nullptr; - - // TODO(b/117575503): We use this buffer to make sure that suspendService pointer and the - // underlying memory are not corrupted before using it. Ideally, memory corruption should be - // fixed. - static constexpr size_t bufSize = sizeof(BpHwSystemSuspend); - static char buf[bufSize]; - - std::call_once(initFlag, []() { - // It's possible for the calling process to not have permissions to - // ISystemSuspend. getService will then return nullptr. - suspendService = ISystemSuspend::getService(); - if (suspendService) { - std::memcpy(buf, static_cast<void*>(suspendService.get()), bufSize); - } - }); - if (suspendService) { - if (std::memcmp(buf, static_cast<void*>(suspendService.get()), bufSize) != 0) { - LOG(FATAL) << "Memory corrupted. Aborting."; - } - } - + static sp<ISystemSuspend> suspendService = ISystemSuspend::getService(); return suspendService; } diff --git a/power_test.cpp b/power_test.cpp index bb8e97d..601df64 100644 --- a/power_test.cpp +++ b/power_test.cpp @@ -16,19 +16,56 @@ #include <hardware_legacy/power.h> +#include <csignal> +#include <cstdlib> #include <string> #include <thread> #include <vector> #include <gtest/gtest.h> +using namespace std::chrono_literals; + namespace android { +// Test acquiring/releasing WakeLocks concurrently with process exit. +TEST(LibpowerTest, ProcessExitTest) { + std::atexit([] { + // We want to give the other thread enough time trigger a failure and + // dump the stack traces. + std::this_thread::sleep_for(1s); + }); + + ASSERT_EXIT( + { + constexpr int numThreads = 20; + std::vector<std::thread> tds; + for (int i = 0; i < numThreads; i++) { + tds.emplace_back([] { + while (true) { + // We want ids to be unique. + std::string id = std::to_string(rand()); + ASSERT_EQ(acquire_wake_lock(PARTIAL_WAKE_LOCK, id.c_str()), 0); + ASSERT_EQ(release_wake_lock(id.c_str()), 0); + } + }); + } + for (auto& td : tds) { + td.detach(); + } + + // Give some time for the threads to actually start. + std::this_thread::sleep_for(100ms); + std::exit(0); + }, + ::testing::ExitedWithCode(0), ""); +} + // Stress test acquiring/releasing WakeLocks. TEST(LibpowerTest, WakeLockStressTest) { // numThreads threads will acquire/release numLocks locks each. constexpr int numThreads = 20; - constexpr int numLocks = 10000; + constexpr int numLocks = 1000; std::vector<std::thread> tds; for (int i = 0; i < numThreads; i++) { |