• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/hardware/interfaces


Commit MetaInfo

Revisión4e53a2961d1f92b8265f3455b9e8d3c22472c5d0 (tree)
Tiempo2018-12-08 08:17:52
AutorTri Vo <trong@goog...>
Commiterandroid-build-merger

Log Message

system suspend: more information about wake locks am: ba81fb29c4
am: 6cd53dfb0c

Change-Id: I450c0d4769d664fdef5ae383660db6f4497f3c84

Cambiar Resumen

Diferencia incremental

--- a/suspend/1.0/default/SystemSuspend.cpp
+++ b/suspend/1.0/default/SystemSuspend.cpp
@@ -27,6 +27,7 @@
2727 #include <sys/types.h>
2828
2929 #include <fcntl.h>
30+#include <ctime>
3031 #include <string>
3132 #include <thread>
3233
@@ -57,7 +58,18 @@ static inline int getCallingPid() {
5758 return IPCThreadState::self()->getCallingPid();
5859 }
5960
60-WakeLock::WakeLock(SystemSuspend* systemSuspend) : mReleased(), mSystemSuspend(systemSuspend) {
61+static inline WakeLockIdType getWakeLockId(int pid, const string& name) {
62+ // Doesn't guarantee unique ids, but for debuging purposes this is adequate.
63+ return std::to_string(pid) + "/" + name;
64+}
65+
66+TimestampType getEpochTimeNow() {
67+ auto timeSinceEpoch = std::chrono::system_clock::now().time_since_epoch();
68+ return std::chrono::duration_cast<std::chrono::microseconds>(timeSinceEpoch).count();
69+}
70+
71+WakeLock::WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id)
72+ : mReleased(), mSystemSuspend(systemSuspend), mId(id) {
6173 mSystemSuspend->incSuspendCounter();
6274 }
6375
@@ -73,15 +85,16 @@ Return<void> WakeLock::release() {
7385 void WakeLock::releaseOnce() {
7486 std::call_once(mReleased, [this]() {
7587 mSystemSuspend->decSuspendCounter();
76- mSystemSuspend->deleteWakeLockStatsEntry(reinterpret_cast<WakeLockIdType>(this));
88+ mSystemSuspend->deleteWakeLockStatsEntry(mId);
7789 });
7890 }
7991
80-SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd,
92+SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t maxStatsEntries,
8193 std::chrono::milliseconds baseSleepTime)
8294 : mSuspendCounter(0),
8395 mWakeupCountFd(std::move(wakeupCountFd)),
8496 mStateFd(std::move(stateFd)),
97+ mMaxStatsEntries(maxStatsEntries),
8598 mBaseSleepTime(baseSleepTime),
8699 mSleepTime(baseSleepTime) {}
87100
@@ -99,14 +112,28 @@ Return<bool> SystemSuspend::enableAutosuspend() {
99112
100113 Return<sp<IWakeLock>> SystemSuspend::acquireWakeLock(WakeLockType /* type */,
101114 const hidl_string& name) {
102- IWakeLock* wl = new WakeLock{this};
115+ auto pid = getCallingPid();
116+ auto wlId = getWakeLockId(pid, name);
117+ IWakeLock* wl = new WakeLock{this, wlId};
103118 {
104119 auto l = std::lock_guard(mStatsLock);
105- WakeLockStats wlStats{};
106- wlStats.set_name(name);
107- wlStats.set_pid(getCallingPid());
108- // Use WakeLock's address as a unique identifier.
109- (*mStats.mutable_wake_lock_stats())[reinterpret_cast<WakeLockIdType>(wl)] = wlStats;
120+
121+ auto& wlStatsEntry = (*mStats.mutable_wl_stats())[wlId];
122+ auto lastUpdated = wlStatsEntry.last_updated();
123+ auto timeNow = getEpochTimeNow();
124+ mLruWakeLockId.erase(lastUpdated);
125+ mLruWakeLockId[timeNow] = wlId;
126+
127+ wlStatsEntry.set_name(name);
128+ wlStatsEntry.set_pid(pid);
129+ wlStatsEntry.set_active(true);
130+ wlStatsEntry.set_last_updated(timeNow);
131+
132+ if (mStats.wl_stats().size() > mMaxStatsEntries) {
133+ auto lruWakeLockId = mLruWakeLockId.begin()->second;
134+ mLruWakeLockId.erase(mLruWakeLockId.begin());
135+ mStats.mutable_wl_stats()->erase(lruWakeLockId);
136+ }
110137 }
111138 return wl;
112139 }
@@ -164,7 +191,16 @@ void SystemSuspend::decSuspendCounter() {
164191
165192 void SystemSuspend::deleteWakeLockStatsEntry(WakeLockIdType id) {
166193 auto l = std::lock_guard(mStatsLock);
167- mStats.mutable_wake_lock_stats()->erase(id);
194+ auto* wlStats = mStats.mutable_wl_stats();
195+ if (wlStats->find(id) != wlStats->end()) {
196+ auto& wlStatsEntry = (*wlStats)[id];
197+ auto timeNow = getEpochTimeNow();
198+ auto lastUpdated = wlStatsEntry.last_updated();
199+ wlStatsEntry.set_active(false);
200+ wlStatsEntry.set_last_updated(timeNow);
201+ mLruWakeLockId.erase(lastUpdated);
202+ mLruWakeLockId[timeNow] = id;
203+ }
168204 }
169205
170206 void SystemSuspend::initAutosuspend() {
--- a/suspend/1.0/default/SystemSuspend.h
+++ b/suspend/1.0/default/SystemSuspend.h
@@ -40,17 +40,19 @@ using ::android::hardware::hidl_vec;
4040 using ::android::hardware::interfacesEqual;
4141 using ::android::hardware::Return;
4242
43-using WakeLockIdType = uint64_t;
43+using TimestampType = uint64_t;
44+using WakeLockIdType = std::string;
4445
4546 using namespace std::chrono_literals;
4647
4748 class SystemSuspend;
4849
4950 std::string readFd(int fd);
51+TimestampType getEpochTimeNow();
5052
5153 class WakeLock : public IWakeLock {
5254 public:
53- WakeLock(SystemSuspend* systemSuspend);
55+ WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id);
5456 ~WakeLock();
5557
5658 Return<void> release();
@@ -60,11 +62,12 @@ class WakeLock : public IWakeLock {
6062 std::once_flag mReleased;
6163
6264 SystemSuspend* mSystemSuspend;
65+ WakeLockIdType mId;
6366 };
6467
6568 class SystemSuspend : public ISystemSuspend, public hidl_death_recipient {
6669 public:
67- SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd,
70+ SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t maxStatsEntries,
6871 std::chrono::milliseconds baseSleepTime);
6972 Return<bool> enableAutosuspend() override;
7073 Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
@@ -88,6 +91,12 @@ class SystemSuspend : public ISystemSuspend, public hidl_death_recipient {
8891 // protect these. However, since mStats is only for debugging we prioritize performance.
8992 // Never hold both locks at the same time to avoid deadlock.
9093 std::mutex mStatsLock;
94+ // We don't want mStats to grow unboundedly in memory. This constant limits amount of
95+ // information mStats can collect on the device.
96+ size_t mMaxStatsEntries;
97+ // Used to evict the least recently used wake lock stats entry in case mMaxStatsEntries is
98+ // reached.
99+ std::map<TimestampType, WakeLockIdType> mLruWakeLockId;
91100 SystemSuspendStats mStats;
92101
93102 using CbType = sp<ISystemSuspendCallback>;
--- a/suspend/1.0/default/SystemSuspendStats.proto
+++ b/suspend/1.0/default/SystemSuspendStats.proto
@@ -14,13 +14,15 @@
1414
1515 syntax = "proto3";
1616
17-// Collects information about individual WakeLock instances.
17+// Collects information about an individual live WakeLock instances.
1818 message WakeLockStats {
1919 string name = 1;
2020 int32 pid = 2;
21+ bool active = 3;
22+ uint64 last_updated = 4;
2123 }
2224
2325 message SystemSuspendStats {
2426 // Maps a unique id of a WakeLock instance to the corresponding WakeLockStats message.
25- map<uint64, WakeLockStats> wake_lock_stats = 1;
27+ map<string, WakeLockStats> wl_stats = 1;
2628 }
--- a/suspend/1.0/default/SystemSuspendUnitTest.cpp
+++ b/suspend/1.0/default/SystemSuspendUnitTest.cpp
@@ -44,6 +44,7 @@ using android::hardware::configureRpcThreadpool;
4444 using android::hardware::joinRpcThreadpool;
4545 using android::hardware::Return;
4646 using android::hardware::Void;
47+using android::system::suspend::V1_0::getEpochTimeNow;
4748 using android::system::suspend::V1_0::ISystemSuspend;
4849 using android::system::suspend::V1_0::ISystemSuspendCallback;
4950 using android::system::suspend::V1_0::IWakeLock;
@@ -80,8 +81,9 @@ class SystemSuspendTestEnvironment : public ::testing::Environment {
8081 void registerTestService() {
8182 std::thread testService([this] {
8283 configureRpcThreadpool(1, true /* callerWillJoin */);
83- sp<ISystemSuspend> suspend = new SystemSuspend(
84- std::move(wakeupCountFds[1]), std::move(stateFds[1]), 0ms /* baseSleepTime */);
84+ sp<ISystemSuspend> suspend =
85+ new SystemSuspend(std::move(wakeupCountFds[1]), std::move(stateFds[1]),
86+ 1 /* maxStatsEntries */, 0ms /* baseSleepTime */);
8587 status_t status = suspend->registerAsService(kServiceName);
8688 if (android::OK != status) {
8789 LOG(FATAL) << "Unable to register service: " << status;
@@ -155,7 +157,10 @@ class SystemSuspendTest : public ::testing::Test {
155157 return stats;
156158 }
157159
158- size_t getWakeLockCount() { return getDebugDump().wake_lock_stats().size(); }
160+ size_t getActiveWakeLockCount() {
161+ const auto& wlStats = getDebugDump().wl_stats();
162+ return count_if(wlStats.begin(), wlStats.end(), [](auto x) { return x.second.active(); });
163+ }
159164
160165 void checkLoop(int numIter) {
161166 for (int i = 0; i < numIter; i++) {
@@ -248,15 +253,43 @@ TEST_F(SystemSuspendTest, CleanupOnAbort) {
248253 ASSERT_FALSE(isSystemSuspendBlocked());
249254 }
250255
251-// Test that debug dump has correct information about acquired WakeLocks.
252-TEST_F(SystemSuspendTest, DebugDump) {
256+// Test that debug dump has correct information about WakeLocks.
257+TEST_F(SystemSuspendTest, DebugDumpWakeLocks) {
258+ uint64_t timeNow = getEpochTimeNow();
253259 {
254260 sp<IWakeLock> wl = acquireWakeLock();
255- SystemSuspendStats debugDump = getDebugDump();
256- ASSERT_EQ(debugDump.wake_lock_stats().size(), 1);
257- ASSERT_EQ(debugDump.wake_lock_stats().begin()->second.name(), "TestLock");
261+ auto wlStats = getDebugDump().wl_stats();
262+ ASSERT_EQ(wlStats.size(), 1);
263+ ASSERT_EQ(wlStats.begin()->second.name(), "TestLock");
264+ ASSERT_EQ(wlStats.begin()->second.pid(), getpid());
265+ ASSERT_EQ(wlStats.begin()->second.active(), true);
266+ ASSERT_GT(wlStats.begin()->second.last_updated(), timeNow);
267+ // We sleep so that the wake lock stats entry get updated with a different timestamp.
268+ std::this_thread::sleep_for(1s);
258269 }
259- ASSERT_EQ(getWakeLockCount(), 0);
270+ auto wlStats = getDebugDump().wl_stats();
271+ ASSERT_EQ(wlStats.size(), 1);
272+ ASSERT_EQ(wlStats.begin()->second.name(), "TestLock");
273+ ASSERT_EQ(wlStats.begin()->second.pid(), getpid());
274+ ASSERT_EQ(wlStats.begin()->second.active(), false);
275+ // The updated timestamp is not deterministic. However, all SystemSuspend HAL calls run in the
276+ // order of microseconds, so in practice the updated timestamp should be 1 second newer than the
277+ // old one.
278+ ASSERT_GT(wlStats.begin()->second.last_updated(), timeNow + 1000000);
279+}
280+
281+// Test that the least recently used wake stats entry is evicted after a given threshold.
282+TEST_F(SystemSuspendTest, LruWakeLockStatsEviction) {
283+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "foo");
284+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "bar");
285+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "bar");
286+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "baz");
287+
288+ auto wlStats = getDebugDump().wl_stats();
289+ // Max number of stats entries was set to 1 in SystemSuspend constructor.
290+ ASSERT_EQ(wlStats.size(), 1);
291+ ASSERT_EQ(wlStats.begin()->second.name(), "baz");
292+ ASSERT_EQ(wlStats.begin()->second.active(), false);
260293 }
261294
262295 // Stress test acquiring/releasing WakeLocks.
@@ -268,7 +301,7 @@ TEST_F(SystemSuspendTest, WakeLockStressTest) {
268301
269302 for (int i = 0; i < numThreads; i++) {
270303 tds[i] = std::thread([this] {
271- for (int i = 0; i < numLocks; i++) {
304+ for (int j = 0; j < numLocks; j++) {
272305 sp<IWakeLock> wl1 = acquireWakeLock();
273306 sp<IWakeLock> wl2 = acquireWakeLock();
274307 wl2->release();
@@ -278,7 +311,7 @@ TEST_F(SystemSuspendTest, WakeLockStressTest) {
278311 for (int i = 0; i < numThreads; i++) {
279312 tds[i].join();
280313 }
281- ASSERT_EQ(getWakeLockCount(), 0);
314+ ASSERT_EQ(getActiveWakeLockCount(), 0);
282315 }
283316
284317 // Callbacks are passed around as sp<>. However, mock expectations are verified when mock objects
--- a/suspend/1.0/default/main.cpp
+++ b/suspend/1.0/default/main.cpp
@@ -36,7 +36,8 @@ int main() {
3636
3737 configureRpcThreadpool(1, true /* callerWillJoin */);
3838 sp<ISystemSuspend> suspend =
39- new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd), 100ms /* baseSleepTime */);
39+ new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd), 100 /* maxStatsEntries */,
40+ 100ms /* baseSleepTime */);
4041 status_t status = suspend->registerAsService();
4142 if (android::OK != status) {
4243 LOG(FATAL) << "Unable to register service: " << status;