Merge "Handle concurrent exit and wake lock acquisition."
This commit is contained in:
commit
8803d61599
3 changed files with 53 additions and 30 deletions
18
Android.bp
18
Android.bp
|
@ -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,
|
||||
|
|
26
power.cpp
26
power.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
Loading…
Reference in a new issue