summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:26:52 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-04-28 20:26:52 +0000
commitc0a29a703e72ece2c1ab87c3e1ee1587476da040 (patch)
tree76082fe06c0f187f38e2689e34556459018579f6
parent265fe2e6fa12e521f41248be088595758bf4b78b (diff)
parent2987e6b9e5e5ea02124c67e880aaeb942a3e4c17 (diff)
downloadinterfaces-android12-mainline-tzdata-release.tar.gz
Change-Id: If409c0581ca1761d11a8d92aa7aacc25ea5d65c5
-rw-r--r--OWNERS3
-rw-r--r--TEST_MAPPING8
-rw-r--r--net/netd/1.0/Android.bp1
-rw-r--r--net/netd/1.1/Android.bp1
-rw-r--r--suspend/1.0/Android.bp1
-rw-r--r--suspend/1.0/default/Android.bp28
-rw-r--r--suspend/1.0/default/SuspendControlService.cpp96
-rw-r--r--suspend/1.0/default/SuspendControlService.h3
-rw-r--r--suspend/1.0/default/SystemSuspend.cpp172
-rw-r--r--suspend/1.0/default/SystemSuspend.h59
-rw-r--r--suspend/1.0/default/SystemSuspendStats.proto28
-rw-r--r--suspend/1.0/default/SystemSuspendUnitTest.cpp578
-rw-r--r--suspend/1.0/default/WakeLockEntryList.cpp375
-rw-r--r--suspend/1.0/default/WakeLockEntryList.h88
-rw-r--r--suspend/1.0/default/android.system.suspend@1.0-service.rc2
-rw-r--r--suspend/1.0/default/main.cpp28
-rw-r--r--suspend/aidl/Android.bp7
-rw-r--r--suspend/aidl/android/system/suspend/ISuspendControlService.aidl6
-rw-r--r--suspend/aidl/android/system/suspend/WakeLockInfo.aidl66
-rw-r--r--wifi/keystore/1.0/Android.bp1
-rw-r--r--wifi/keystore/1.0/default/Android.bp3
-rw-r--r--wifi/keystore/1.0/vts/functional/Android.bp2
-rw-r--r--wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp15
23 files changed, 273 insertions, 1298 deletions
diff --git a/OWNERS b/OWNERS
index adf3893..289a174 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,6 +1,3 @@
-per-file *.hal,*.aidl,OWNERS = set noparent
-per-file *.hal,*.aidl,OWNERS = elsk@google.com,malchev@google.com,smoreland@google.com
-
elsk@google.com
hridya@google.com
maco@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
deleted file mode 100644
index 98e125b..0000000
--- a/TEST_MAPPING
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "presubmit": [
- {
- "name": "hidl_implementation_test"
- }
- ]
-}
-
diff --git a/net/netd/1.0/Android.bp b/net/netd/1.0/Android.bp
index c2cebd3..14a79eb 100644
--- a/net/netd/1.0/Android.bp
+++ b/net/netd/1.0/Android.bp
@@ -14,3 +14,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/net/netd/1.1/Android.bp b/net/netd/1.1/Android.bp
index 6eeb384..e9b2417 100644
--- a/net/netd/1.1/Android.bp
+++ b/net/netd/1.1/Android.bp
@@ -15,3 +15,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/suspend/1.0/Android.bp b/suspend/1.0/Android.bp
index bf334ec..5502d63 100644
--- a/suspend/1.0/Android.bp
+++ b/suspend/1.0/Android.bp
@@ -16,3 +16,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/suspend/1.0/default/Android.bp b/suspend/1.0/default/Android.bp
index a3bf2d5..0453f8a 100644
--- a/suspend/1.0/default/Android.bp
+++ b/suspend/1.0/default/Android.bp
@@ -19,6 +19,8 @@ cc_defaults {
"libbinder",
"libcutils",
"libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
"liblog",
"libutils",
],
@@ -31,6 +33,26 @@ cc_defaults {
cc_defaults {
name: "system_suspend_stats_defaults",
+ shared_libs: [
+ "libprotobuf-cpp-full",
+ ],
+ static_libs: ["SystemSuspendStatsProto"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+}
+
+cc_library {
+ name: "SystemSuspendStatsProto",
+ srcs: [
+ "SystemSuspendStats.proto",
+ ],
+ proto: {
+ export_proto_headers: true,
+ type: "full",
+ },
cflags: [
"-Wall",
"-Werror",
@@ -51,11 +73,11 @@ cc_binary {
"android.system.suspend@1.0",
"suspend_control_aidl_interface-cpp",
],
+ static_libs: ["SystemSuspendStatsProto"],
srcs: [
"main.cpp",
"SuspendControlService.cpp",
"SystemSuspend.cpp",
- "WakeLockEntryList.cpp",
],
}
@@ -75,10 +97,8 @@ cc_test {
srcs: [
"SuspendControlService.cpp",
"SystemSuspend.cpp",
- "SystemSuspendUnitTest.cpp",
- "WakeLockEntryList.cpp",
+ "SystemSuspendUnitTest.cpp"
],
test_suites: ["device-tests"],
- require_root: true,
}
diff --git a/suspend/1.0/default/SuspendControlService.cpp b/suspend/1.0/default/SuspendControlService.cpp
index e74cd76..9dad40d 100644
--- a/suspend/1.0/default/SuspendControlService.cpp
+++ b/suspend/1.0/default/SuspendControlService.cpp
@@ -16,13 +16,9 @@
#include "SuspendControlService.h"
-#include <android-base/logging.h>
-#include <android-base/stringprintf.h>
-
#include "SystemSuspend.h"
-using ::android::base::Result;
-using ::android::base::StringPrintf;
+#include <android-base/logging.h>
namespace android {
namespace system {
@@ -89,96 +85,6 @@ void SuspendControlService::notifyWakeup(bool success) {
}
}
-binder::Status SuspendControlService::getWakeLockStats(std::vector<WakeLockInfo>* _aidl_return) {
- const auto suspendService = mSuspend.promote();
- if (!suspendService) {
- return binder::Status::fromExceptionCode(binder::Status::Exception::EX_NULL_POINTER,
- String8("Null reference to suspendService"));
- }
-
- suspendService->updateStatsNow();
- suspendService->getStatsList().getWakeLockStats(_aidl_return);
-
- return binder::Status::ok();
-}
-
-static std::string dumpUsage() {
- return "\nUsage: adb shell dumpsys suspend_control [option]\n\n"
- " Options:\n"
- " --wakelocks : returns wakelock stats.\n"
- " --suspend_stats : returns suspend stats.\n"
- " --help or -h : prints this message.\n\n"
- " Note: All stats are returned if no or (an\n"
- " invalid) option is specified.\n\n";
-}
-
-status_t SuspendControlService::dump(int fd, const Vector<String16>& args) {
- const auto suspendService = mSuspend.promote();
- if (!suspendService) {
- return DEAD_OBJECT;
- }
-
- bool wakelocks = true;
- bool suspend_stats = true;
-
- if (args.size() > 0) {
- std::string arg(String8(args[0]).string());
- if (arg == "--wakelocks") {
- suspend_stats = false;
- } else if (arg == "--suspend_stats") {
- wakelocks = false;
- } else if (arg == "-h" || arg == "--help") {
- std::string usage = dumpUsage();
- dprintf(fd, "%s\n", usage.c_str());
- return OK;
- }
- }
-
- if (wakelocks) {
- suspendService->updateStatsNow();
- std::stringstream wlStats;
- wlStats << suspendService->getStatsList();
- dprintf(fd, "\n%s\n", wlStats.str().c_str());
- }
- if (suspend_stats) {
- Result<SuspendStats> res = suspendService->getSuspendStats();
- if (!res) {
- LOG(ERROR) << "SuspendControlService: " << res.error().message();
- return OK;
- }
-
- SuspendStats stats = res.value();
- // clang-format off
- std::string suspendStats = StringPrintf(
- "----- Suspend Stats -----\n"
- "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
- "%s: %d\n%s: %d\n%s: %d\n%s: %d\n%s: %d\n"
- "\nLast Failures:\n"
- " %s: %s\n"
- " %s: %d\n"
- " %s: %s\n"
- "----------\n\n",
-
- "success", stats.success,
- "fail", stats.fail,
- "failed_freeze", stats.failedFreeze,
- "failed_prepare", stats.failedPrepare,
- "failed_suspend", stats.failedSuspend,
- "failed_suspend_late", stats.failedSuspendLate,
- "failed_suspend_noirq", stats.failedSuspendNoirq,
- "failed_resume", stats.failedResume,
- "failed_resume_early", stats.failedResumeEarly,
- "failed_resume_noirq", stats.failedResumeNoirq,
- "last_failed_dev", stats.lastFailedDev.c_str(),
- "last_failed_errno", stats.lastFailedErrno,
- "last_failed_step", stats.lastFailedStep.c_str());
- // clang-format on
- dprintf(fd, "\n%s\n", suspendStats.c_str());
- }
-
- return OK;
-}
-
} // namespace V1_0
} // namespace suspend
} // namespace system
diff --git a/suspend/1.0/default/SuspendControlService.h b/suspend/1.0/default/SuspendControlService.h
index d8b91d7..5e8de3c 100644
--- a/suspend/1.0/default/SuspendControlService.h
+++ b/suspend/1.0/default/SuspendControlService.h
@@ -39,13 +39,10 @@ class SuspendControlService : public BnSuspendControlService,
binder::Status registerCallback(const sp<ISuspendCallback>& callback,
bool* _aidl_return) override;
binder::Status forceSuspend(bool* _aidl_return) override;
- binder::Status getWakeLockStats(std::vector<WakeLockInfo>* _aidl_return) override;
-
void binderDied(const wp<IBinder>& who) override;
void setSuspendService(const wp<SystemSuspend>& suspend);
void notifyWakeup(bool success);
- status_t dump(int fd, const Vector<String16>& args) override;
private:
wp<SystemSuspend> mSuspend;
diff --git a/suspend/1.0/default/SystemSuspend.cpp b/suspend/1.0/default/SystemSuspend.cpp
index 9da1a18..8eb91e5 100644
--- a/suspend/1.0/default/SystemSuspend.cpp
+++ b/suspend/1.0/default/SystemSuspend.cpp
@@ -19,16 +19,18 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
-#include <fcntl.h>
+#include <google/protobuf/text_format.h>
#include <hidl/Status.h>
#include <hwbinder/IPCThreadState.h>
+
#include <sys/stat.h>
#include <sys/types.h>
+#include <fcntl.h>
+#include <ctime>
#include <string>
#include <thread>
-using ::android::base::Error;
using ::android::base::ReadFdToString;
using ::android::base::WriteStringToFd;
using ::android::hardware::Void;
@@ -59,8 +61,18 @@ static inline int getCallingPid() {
return ::android::hardware::IPCThreadState::self()->getCallingPid();
}
-WakeLock::WakeLock(SystemSuspend* systemSuspend, const string& name, int pid)
- : mReleased(), mSystemSuspend(systemSuspend), mName(name), mPid(pid) {
+static inline WakeLockIdType getWakeLockId(int pid, const string& name) {
+ // Doesn't guarantee unique ids, but for debuging purposes this is adequate.
+ return std::to_string(pid) + "/" + name;
+}
+
+TimestampType getEpochTimeNow() {
+ auto timeSinceEpoch = std::chrono::system_clock::now().time_since_epoch();
+ return std::chrono::duration_cast<std::chrono::microseconds>(timeSinceEpoch).count();
+}
+
+WakeLock::WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id, const string& name)
+ : mReleased(), mSystemSuspend(systemSuspend), mId(id), mName(name) {
mSystemSuspend->incSuspendCounter(mName);
}
@@ -76,23 +88,21 @@ Return<void> WakeLock::release() {
void WakeLock::releaseOnce() {
std::call_once(mReleased, [this]() {
mSystemSuspend->decSuspendCounter(mName);
- mSystemSuspend->updateWakeLockStatOnRelease(mName, mPid, getTimeNow());
+ mSystemSuspend->deleteWakeLockStatsEntry(mId);
});
}
-SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, unique_fd suspendStatsFd,
- size_t maxNativeStatsEntries, unique_fd kernelWakelockStatsFd,
+SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t maxStatsEntries,
std::chrono::milliseconds baseSleepTime,
const sp<SuspendControlService>& controlService,
bool useSuspendCounter)
: mSuspendCounter(0),
mWakeupCountFd(std::move(wakeupCountFd)),
mStateFd(std::move(stateFd)),
- mSuspendStatsFd(std::move(suspendStatsFd)),
+ mMaxStatsEntries(maxStatsEntries),
mBaseSleepTime(baseSleepTime),
mSleepTime(baseSleepTime),
mControlService(controlService),
- mStatsList(maxNativeStatsEntries, std::move(kernelWakelockStatsFd)),
mUseSuspendCounter(useSuspendCounter),
mWakeLockFd(-1),
mWakeUnlockFd(-1) {
@@ -141,12 +151,48 @@ bool SystemSuspend::forceSuspend() {
Return<sp<IWakeLock>> SystemSuspend::acquireWakeLock(WakeLockType /* type */,
const hidl_string& name) {
auto pid = getCallingPid();
- auto timeNow = getTimeNow();
- IWakeLock* wl = new WakeLock{this, name, pid};
- mStatsList.updateOnAcquire(name, pid, timeNow);
+ auto wlId = getWakeLockId(pid, name);
+ IWakeLock* wl = new WakeLock{this, wlId, name};
+ {
+ auto l = std::lock_guard(mStatsLock);
+
+ auto& wlStatsEntry = (*mStats.mutable_wl_stats())[wlId];
+ auto lastUpdated = wlStatsEntry.last_updated();
+ auto timeNow = getEpochTimeNow();
+ mLruWakeLockId.erase(lastUpdated);
+ mLruWakeLockId[timeNow] = wlId;
+
+ wlStatsEntry.set_name(name);
+ wlStatsEntry.set_pid(pid);
+ wlStatsEntry.set_active(true);
+ wlStatsEntry.set_last_updated(timeNow);
+
+ if (mStats.wl_stats().size() > mMaxStatsEntries) {
+ auto lruWakeLockId = mLruWakeLockId.begin()->second;
+ mLruWakeLockId.erase(mLruWakeLockId.begin());
+ mStats.mutable_wl_stats()->erase(lruWakeLockId);
+ }
+ }
return wl;
}
+Return<void> SystemSuspend::debug(const hidl_handle& handle,
+ const hidl_vec<hidl_string>& /* options */) {
+ if (handle == nullptr || handle->numFds < 1 || handle->data[0] < 0) {
+ LOG(ERROR) << "no valid fd";
+ return Void();
+ }
+ int fd = handle->data[0];
+ string debugStr;
+ {
+ auto l = std::lock_guard(mStatsLock);
+ google::protobuf::TextFormat::PrintToString(mStats, &debugStr);
+ }
+ WriteStringToFd(debugStr, fd);
+ fsync(fd);
+ return Void();
+}
+
void SystemSuspend::incSuspendCounter(const string& name) {
auto l = std::lock_guard(mCounterLock);
if (mUseSuspendCounter) {
@@ -171,6 +217,20 @@ void SystemSuspend::decSuspendCounter(const string& name) {
}
}
+void SystemSuspend::deleteWakeLockStatsEntry(WakeLockIdType id) {
+ auto l = std::lock_guard(mStatsLock);
+ auto* wlStats = mStats.mutable_wl_stats();
+ if (wlStats->find(id) != wlStats->end()) {
+ auto& wlStatsEntry = (*wlStats)[id];
+ auto timeNow = getEpochTimeNow();
+ auto lastUpdated = wlStatsEntry.last_updated();
+ wlStatsEntry.set_active(false);
+ wlStatsEntry.set_last_updated(timeNow);
+ mLruWakeLockId.erase(lastUpdated);
+ mLruWakeLockId[timeNow] = id;
+ }
+}
+
void SystemSuspend::initAutosuspend() {
std::thread autosuspendThread([this] {
while (true) {
@@ -218,94 +278,6 @@ void SystemSuspend::updateSleepTime(bool success) {
mSleepTime = std::min(mSleepTime * 2, kMaxSleepTime);
}
-void SystemSuspend::updateWakeLockStatOnRelease(const std::string& name, int pid,
- TimestampType timeNow) {
- mStatsList.updateOnRelease(name, pid, timeNow);
-}
-
-const WakeLockEntryList& SystemSuspend::getStatsList() const {
- return mStatsList;
-}
-
-void SystemSuspend::updateStatsNow() {
- mStatsList.updateNow();
-}
-
-/**
- * Returns suspend stats.
- */
-Result<SuspendStats> SystemSuspend::getSuspendStats() {
- std::unique_ptr<DIR, decltype(&closedir)> dp(fdopendir(dup(mSuspendStatsFd.get())), &closedir);
- if (!dp) {
- return Error() << "Failed to get directory pointer to suspend_stats dir";
- }
-
- SuspendStats stats;
-
- // rewinddir, else subsequent calls will not get any suspend_stats
- rewinddir(dp.get());
-
- struct dirent* de;
-
- // Grab a wakelock before reading suspend stats,
- // to ensure a consistent snapshot.
- sp<IWakeLock> suspendStatsLock = acquireWakeLock(WakeLockType::PARTIAL, "suspend_stats_lock");
-
- while ((de = readdir(dp.get()))) {
- std::string statName(de->d_name);
- if ((statName == ".") || (statName == "..")) {
- continue;
- }
-
- unique_fd statFd{TEMP_FAILURE_RETRY(
- openat(mSuspendStatsFd.get(), statName.c_str(), O_CLOEXEC | O_RDONLY))};
- if (statFd < 0) {
- return Error() << "Failed to open " << statName;
- }
-
- std::string valStr;
- if (!ReadFdToString(statFd.get(), &valStr)) {
- return Error() << "Failed to read " << statName;
- }
-
- // Trim newline
- valStr.erase(std::remove(valStr.begin(), valStr.end(), '\n'), valStr.end());
-
- if (statName == "last_failed_dev") {
- stats.lastFailedDev = valStr;
- } else if (statName == "last_failed_step") {
- stats.lastFailedStep = valStr;
- } else {
- int statVal = std::stoi(valStr);
- if (statName == "success") {
- stats.success = statVal;
- } else if (statName == "fail") {
- stats.fail = statVal;
- } else if (statName == "failed_freeze") {
- stats.failedFreeze = statVal;
- } else if (statName == "failed_prepare") {
- stats.failedPrepare = statVal;
- } else if (statName == "failed_suspend") {
- stats.failedSuspend = statVal;
- } else if (statName == "failed_suspend_late") {
- stats.failedSuspendLate = statVal;
- } else if (statName == "failed_suspend_noirq") {
- stats.failedSuspendNoirq = statVal;
- } else if (statName == "failed_resume") {
- stats.failedResume = statVal;
- } else if (statName == "failed_resume_early") {
- stats.failedResumeEarly = statVal;
- } else if (statName == "failed_resume_noirq") {
- stats.failedResumeNoirq = statVal;
- } else if (statName == "last_failed_errno") {
- stats.lastFailedErrno = statVal;
- }
- }
- }
-
- return stats;
-}
-
} // namespace V1_0
} // namespace suspend
} // namespace system
diff --git a/suspend/1.0/default/SystemSuspend.h b/suspend/1.0/default/SystemSuspend.h
index 9fe9319..ed19f2a 100644
--- a/suspend/1.0/default/SystemSuspend.h
+++ b/suspend/1.0/default/SystemSuspend.h
@@ -17,54 +17,43 @@
#ifndef ANDROID_SYSTEM_SYSTEM_SUSPEND_V1_0_H
#define ANDROID_SYSTEM_SYSTEM_SUSPEND_V1_0_H
-#include <android-base/result.h>
+#include "SuspendControlService.h"
+
#include <android-base/unique_fd.h>
#include <android/system/suspend/1.0/ISystemSuspend.h>
#include <hidl/HidlTransportSupport.h>
+#include <system/hardware/interfaces/suspend/1.0/default/SystemSuspendStats.pb.h>
#include <condition_variable>
#include <mutex>
#include <string>
-#include "SuspendControlService.h"
-#include "WakeLockEntryList.h"
-
namespace android {
namespace system {
namespace suspend {
namespace V1_0 {
-using ::android::base::Result;
using ::android::base::unique_fd;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_handle;
using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
using ::android::hardware::interfacesEqual;
using ::android::hardware::Return;
+using TimestampType = uint64_t;
+using WakeLockIdType = std::string;
+
using namespace std::chrono_literals;
class SystemSuspend;
-struct SuspendStats {
- int success = 0;
- int fail = 0;
- int failedFreeze = 0;
- int failedPrepare = 0;
- int failedSuspend = 0;
- int failedSuspendLate = 0;
- int failedSuspendNoirq = 0;
- int failedResume = 0;
- int failedResumeEarly = 0;
- int failedResumeNoirq = 0;
- std::string lastFailedDev;
- int lastFailedErrno = 0;
- std::string lastFailedStep;
-};
-
std::string readFd(int fd);
+TimestampType getEpochTimeNow();
class WakeLock : public IWakeLock {
public:
- WakeLock(SystemSuspend* systemSuspend, const std::string& name, int pid);
+ WakeLock(SystemSuspend* systemSuspend, const WakeLockIdType& id, const std::string& name);
~WakeLock();
Return<void> release();
@@ -74,27 +63,23 @@ class WakeLock : public IWakeLock {
std::once_flag mReleased;
SystemSuspend* mSystemSuspend;
+ WakeLockIdType mId;
std::string mName;
- int mPid;
};
class SystemSuspend : public ISystemSuspend {
public:
- SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, unique_fd suspendStatsFd,
- size_t maxNativeStatsEntries, unique_fd kernelWakelockStatsFd,
+ SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t maxStatsEntries,
std::chrono::milliseconds baseSleepTime,
const sp<SuspendControlService>& controlService, bool useSuspendCounter = true);
Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
+ Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override;
void incSuspendCounter(const std::string& name);
void decSuspendCounter(const std::string& name);
+ void deleteWakeLockStatsEntry(WakeLockIdType id);
bool enableAutosuspend();
bool forceSuspend();
- const WakeLockEntryList& getStatsList() const;
- void updateWakeLockStatOnRelease(const std::string& name, int pid, TimestampType timeNow);
- void updateStatsNow();
- Result<SuspendStats> getSuspendStats();
-
private:
void initAutosuspend();
@@ -104,7 +89,17 @@ class SystemSuspend : public ISystemSuspend {
unique_fd mWakeupCountFd;
unique_fd mStateFd;
- unique_fd mSuspendStatsFd;
+ // mStats can be inconsistent with with mSuspendCounter since we use two separate locks to
+ // protect these. However, since mStats is only for debugging we prioritize performance.
+ // Never hold both locks at the same time to avoid deadlock.
+ std::mutex mStatsLock;
+ // We don't want mStats to grow unboundedly in memory. This constant limits amount of
+ // information mStats can collect on the device.
+ size_t mMaxStatsEntries;
+ // Used to evict the least recently used wake lock stats entry in case mMaxStatsEntries is
+ // reached.
+ std::map<TimestampType, WakeLockIdType> mLruWakeLockId;
+ SystemSuspendStats mStats;
// Amount of sleep time between consecutive iterations of the suspend loop.
std::chrono::milliseconds mBaseSleepTime;
@@ -114,8 +109,6 @@ class SystemSuspend : public ISystemSuspend {
sp<SuspendControlService> mControlService;
- WakeLockEntryList mStatsList;
-
// If true, use mSuspendCounter to keep track of native wake locks. Otherwise, rely on
// /sys/power/wake_lock interface to block suspend.
// TODO(b/128923994): remove dependency on /sys/power/wake_lock interface.
diff --git a/suspend/1.0/default/SystemSuspendStats.proto b/suspend/1.0/default/SystemSuspendStats.proto
new file mode 100644
index 0000000..4be6bc2
--- /dev/null
+++ b/suspend/1.0/default/SystemSuspendStats.proto
@@ -0,0 +1,28 @@
+// Copyright 2018 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.
+
+syntax = "proto3";
+
+// Collects information about an individual live WakeLock instances.
+message WakeLockStats {
+ string name = 1;
+ int32 pid = 2;
+ bool active = 3;
+ uint64 last_updated = 4;
+}
+
+message SystemSuspendStats {
+ // Maps a unique id of a WakeLock instance to the corresponding WakeLockStats message.
+ map<string, WakeLockStats> wl_stats = 1;
+}
diff --git a/suspend/1.0/default/SystemSuspendUnitTest.cpp b/suspend/1.0/default/SystemSuspendUnitTest.cpp
index 2298de6..3923812 100644
--- a/suspend/1.0/default/SystemSuspendUnitTest.cpp
+++ b/suspend/1.0/default/SystemSuspendUnitTest.cpp
@@ -14,36 +14,34 @@
* limitations under the License.
*/
+#include "SuspendControlService.h"
+#include "SystemSuspend.h"
+
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <android/system/suspend/BnSuspendCallback.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/native_handle.h>
-#include <ftw.h>
#include <gmock/gmock.h>
+#include <google/protobuf/text_format.h>
#include <gtest/gtest.h>
#include <hidl/HidlTransportSupport.h>
+
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <chrono>
-#include <cmath>
#include <csignal>
#include <cstdlib>
#include <future>
#include <string>
#include <thread>
-#include "SuspendControlService.h"
-#include "SystemSuspend.h"
-
using android::sp;
-using android::base::Result;
using android::base::Socketpair;
using android::base::unique_fd;
using android::base::WriteStringToFd;
@@ -53,15 +51,12 @@ using android::hardware::Return;
using android::hardware::Void;
using android::system::suspend::BnSuspendCallback;
using android::system::suspend::ISuspendControlService;
-using android::system::suspend::WakeLockInfo;
-using android::system::suspend::V1_0::getTimeNow;
+using android::system::suspend::V1_0::getEpochTimeNow;
using android::system::suspend::V1_0::ISystemSuspend;
using android::system::suspend::V1_0::IWakeLock;
using android::system::suspend::V1_0::readFd;
using android::system::suspend::V1_0::SuspendControlService;
-using android::system::suspend::V1_0::SuspendStats;
using android::system::suspend::V1_0::SystemSuspend;
-using android::system::suspend::V1_0::TimestampType;
using android::system::suspend::V1_0::WakeLockType;
using namespace std::chrono_literals;
@@ -77,10 +72,21 @@ static bool isReadBlocked(int fd, int timeout_ms = 20) {
return poll(&pfd, 1, timeout_ms) == 0;
}
-class SystemSuspendTest : public ::testing::Test {
- protected:
- static void registerTestService() {
- std::thread testService([] {
+class SystemSuspendTestEnvironment : public ::testing::Environment {
+ public:
+ using Env = SystemSuspendTestEnvironment;
+ static Env* Instance() {
+ static Env* instance = new Env{};
+ return instance;
+ }
+
+ SystemSuspendTestEnvironment() {
+ Socketpair(SOCK_STREAM, &wakeupCountFds[0], &wakeupCountFds[1]);
+ Socketpair(SOCK_STREAM, &stateFds[0], &stateFds[1]);
+ }
+
+ void registerTestService() {
+ std::thread testService([this] {
configureRpcThreadpool(1, true /* callerWillJoin */);
sp<SuspendControlService> suspendControl = new SuspendControlService();
@@ -94,10 +100,9 @@ class SystemSuspendTest : public ::testing::Test {
sp<android::ProcessState> ps{android::ProcessState::self()};
ps->startThreadPool();
- sp<ISystemSuspend> suspend = new SystemSuspend(
- std::move(wakeupCountFds[1]), std::move(stateFds[1]),
- unique_fd(-1) /*suspendStatsFd*/, 1 /* maxNativeStatsEntries */,
- unique_fd(-1) /* kernelWakelockStatsFd */, 0ms /* baseSleepTime */, suspendControl);
+ sp<ISystemSuspend> suspend =
+ new SystemSuspend(std::move(wakeupCountFds[1]), std::move(stateFds[1]),
+ 1 /* maxStatsEntries */, 0ms /* baseSleepTime */, suspendControl);
status_t status = suspend->registerAsService(kServiceName);
if (android::OK != status) {
LOG(FATAL) << "Unable to register service: " << status;
@@ -108,10 +113,7 @@ class SystemSuspendTest : public ::testing::Test {
testService.detach();
}
- static void SetUpTestSuite() {
- Socketpair(SOCK_STREAM, &wakeupCountFds[0], &wakeupCountFds[1]);
- Socketpair(SOCK_STREAM, &stateFds[0], &stateFds[1]);
-
+ virtual void SetUp() {
registerTestService();
::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, kServiceName);
sp<ISystemSuspend> suspendService = ISystemSuspend::getService(kServiceName);
@@ -128,6 +130,11 @@ class SystemSuspendTest : public ::testing::Test {
ASSERT_EQ(enabled, true) << "failed to start autosuspend";
}
+ unique_fd wakeupCountFds[2];
+ unique_fd stateFds[2];
+};
+
+class SystemSuspendTest : public ::testing::Test {
public:
virtual void SetUp() override {
::android::hardware::details::waitForHwService(ISystemSuspend::descriptor, kServiceName);
@@ -139,8 +146,9 @@ class SystemSuspendTest : public ::testing::Test {
ASSERT_NE(control, nullptr) << "failed to get the suspend control service";
controlService = interface_cast<ISuspendControlService>(control);
- wakeupCountFd = wakeupCountFds[0];
- stateFd = stateFds[0];
+ auto* environment = SystemSuspendTestEnvironment::Instance();
+ wakeupCountFd = environment->wakeupCountFds[0];
+ stateFd = environment->stateFds[0];
// SystemSuspend HAL should not have written back to wakeupCountFd or stateFd yet.
ASSERT_TRUE(isReadBlocked(wakeupCountFd));
@@ -161,14 +169,31 @@ class SystemSuspendTest : public ::testing::Test {
bool isSystemSuspendBlocked(int timeout_ms = 20) { return isReadBlocked(stateFd, timeout_ms); }
- sp<IWakeLock> acquireWakeLock(const std::string& name = "TestLock") {
- return suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
+ sp<IWakeLock> acquireWakeLock() {
+ return suspendService->acquireWakeLock(WakeLockType::PARTIAL, "TestLock");
+ }
+
+ SystemSuspendStats getDebugDump() {
+ // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+ int fds[2];
+ pipe2(fds, O_NONBLOCK);
+ native_handle_t* handle = native_handle_create(1, 0);
+ handle->data[0] = fds[1];
+
+ suspendService->debug(handle, {});
+ SystemSuspendStats stats{};
+ google::protobuf::TextFormat::ParseFromString(readFd(fds[0]), &stats);
+
+ native_handle_close(handle);
+ close(fds[0]);
+ close(fds[1]);
+
+ return stats;
}
size_t getActiveWakeLockCount() {
- std::vector<WakeLockInfo> wlStats;
- controlService->getWakeLockStats(&wlStats);
- return count_if(wlStats.begin(), wlStats.end(), [](auto entry) { return entry.isActive; });
+ const auto& wlStats = getDebugDump().wl_stats();
+ return count_if(wlStats.begin(), wlStats.end(), [](auto x) { return x.second.active(); });
}
void checkLoop(int numIter) {
@@ -182,20 +207,13 @@ class SystemSuspendTest : public ::testing::Test {
<< "SystemSuspend failed to write correct sleep state.";
}
}
+
sp<ISystemSuspend> suspendService;
sp<ISuspendControlService> controlService;
- static unique_fd wakeupCountFds[2];
- static unique_fd stateFds[2];
- static int wakeupCountFd;
- static int stateFd;
+ int stateFd;
+ int wakeupCountFd;
};
-// SystemSuspendTest test suite resources
-unique_fd SystemSuspendTest::wakeupCountFds[2];
-unique_fd SystemSuspendTest::stateFds[2];
-int SystemSuspendTest::wakeupCountFd;
-int SystemSuspendTest::stateFd;
-
// Tests that autosuspend thread can only be enabled once.
TEST_F(SystemSuspendTest, OnlyOneEnableAutosuspend) {
bool enabled = false;
@@ -274,6 +292,45 @@ TEST_F(SystemSuspendTest, CleanupOnAbort) {
ASSERT_FALSE(isSystemSuspendBlocked(200));
}
+// Test that debug dump has correct information about WakeLocks.
+TEST_F(SystemSuspendTest, DebugDumpWakeLocks) {
+ uint64_t timeNow = getEpochTimeNow();
+ {
+ sp<IWakeLock> wl = acquireWakeLock();
+ auto wlStats = getDebugDump().wl_stats();
+ ASSERT_EQ(wlStats.size(), 1);
+ ASSERT_EQ(wlStats.begin()->second.name(), "TestLock");
+ ASSERT_EQ(wlStats.begin()->second.pid(), getpid());
+ ASSERT_EQ(wlStats.begin()->second.active(), true);
+ ASSERT_GT(wlStats.begin()->second.last_updated(), timeNow);
+ // We sleep so that the wake lock stats entry get updated with a different timestamp.
+ std::this_thread::sleep_for(1s);
+ }
+ auto wlStats = getDebugDump().wl_stats();
+ ASSERT_EQ(wlStats.size(), 1);
+ ASSERT_EQ(wlStats.begin()->second.name(), "TestLock");
+ ASSERT_EQ(wlStats.begin()->second.pid(), getpid());
+ ASSERT_EQ(wlStats.begin()->second.active(), false);
+ // The updated timestamp is not deterministic. However, all SystemSuspend HAL calls run in the
+ // order of microseconds, so in practice the updated timestamp should be 1 second newer than the
+ // old one.
+ ASSERT_GT(wlStats.begin()->second.last_updated(), timeNow + 1000000);
+}
+
+// Test that the least recently used wake stats entry is evicted after a given threshold.
+TEST_F(SystemSuspendTest, LruWakeLockStatsEviction) {
+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "foo");
+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "bar");
+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "bar");
+ suspendService->acquireWakeLock(WakeLockType::PARTIAL, "baz");
+
+ auto wlStats = getDebugDump().wl_stats();
+ // Max number of stats entries was set to 1 in SystemSuspend constructor.
+ ASSERT_EQ(wlStats.size(), 1);
+ ASSERT_EQ(wlStats.begin()->second.name(), "baz");
+ ASSERT_EQ(wlStats.begin()->second.active(), false);
+}
+
// Stress test acquiring/releasing WakeLocks.
TEST_F(SystemSuspendTest, WakeLockStressTest) {
// numThreads threads will acquire/release numLocks locks each.
@@ -384,450 +441,11 @@ TEST_F(SystemSuspendTest, CallbackRegisterCallbackNoDeadlock) {
checkLoop(3);
}
-class SystemSuspendSameThreadTest : public ::testing::Test {
- public:
- sp<IWakeLock> acquireWakeLock(const std::string& name = "TestLock") {
- return suspendService->acquireWakeLock(WakeLockType::PARTIAL, name);
- }
-
- /**
- * Returns true if wake lock is found else false.
- */
- bool findWakeLockInfoByName(const std::vector<WakeLockInfo>& wlStats, const std::string& name,
- WakeLockInfo* info) {
- 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;
- }
-
- bool writeStatToFile(int statDirFd, const std::string& fileName, const std::string& stat) {
- unique_fd statFd{TEMP_FAILURE_RETRY(
- openat(statDirFd, fileName.c_str(), O_CREAT | O_CLOEXEC | O_RDWR, S_IRWXU))};
- if (statFd < 0) {
- PLOG(ERROR) << "SystemSuspend: Error opening " << fileName;
- return false;
- }
-
- if (!WriteStringToFd(stat, statFd.get())) {
- PLOG(ERROR) << "SystemSuspend: Error writing stat to " << fileName;
- return false;
- }
-
- return true;
- }
-
- bool writeStatToFile(int statDirFd, const std::string& fileName, int64_t stat) {
- return writeStatToFile(statDirFd, fileName, std::to_string(stat));
- }
-
- /**
- * Creates a kernel wakelock directory and stats files.
- * Returns true on success else false.
- */
- bool addKernelWakelock(const std::string& name, int64_t activeCount = 42,
- int64_t activeTime = 42, int64_t eventCount = 42,
- int64_t expireCount = 42, int64_t lastChange = 42, int64_t maxTime = 42,
- int64_t preventSuspendTime = 42, int64_t totalTime = 42,
- int64_t wakeupCount = 42) {
- static int id = 0;
- std::string kwlId = "wakeup" + std::to_string(id++);
-
- if ((mkdirat(kernelWakelockStatsFd, kwlId.c_str(), S_IRWXU)) < 0) {
- PLOG(ERROR) << "SystemSuspend: Error creating directory for " << kwlId;
- return false;
- }
-
- unique_fd kernelWakelockFd{TEMP_FAILURE_RETRY(
- openat(kernelWakelockStatsFd, kwlId.c_str(), O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
- if (kernelWakelockFd < 0) {
- PLOG(ERROR) << "SystemSuspend: Error opening " << kwlId;
- return false;
- }
-
- int fd = kernelWakelockFd.get();
-
- return writeStatToFile(fd, "name", name) &&
- writeStatToFile(fd, "active_count", activeCount) &&
- writeStatToFile(fd, "active_time_ms", activeTime) &&
- writeStatToFile(fd, "event_count", eventCount) &&
- writeStatToFile(fd, "expire_count", expireCount) &&
- writeStatToFile(fd, "last_change_ms", lastChange) &&
- writeStatToFile(fd, "max_time_ms", maxTime) &&
- writeStatToFile(fd, "prevent_suspend_time_ms", preventSuspendTime) &&
- writeStatToFile(fd, "total_time_ms", totalTime) &&
- writeStatToFile(fd, "wakeup_count", wakeupCount);
- }
-
- /**
- * Adds Suspend stats files to suspendStatDir.
- * Returns true on success else false.
- */
- bool addSuspendStats(int64_t success = 42, int64_t fail = 42, int64_t failedFreeze = 42,
- int64_t failedPrepare = 42, int64_t failedSuspend = 42,
- int64_t failedSuspendLate = 42, int64_t failedSuspendNoirq = 42,
- int64_t failedResume = 42, int64_t failedResumeEarly = 42,
- int64_t failedResumeNoirq = 42,
- const std::string& lastFailedDev = "fakeDev", int64_t lastFailedErrno = 42,
- const std::string& lastFailedStep = "fakeStep") {
- int fd = suspendStatsFd.get();
-
- return writeStatToFile(fd, "success", success) && writeStatToFile(fd, "fail", fail) &&
- writeStatToFile(fd, "failed_freeze", failedFreeze) &&
- writeStatToFile(fd, "failed_prepare", failedPrepare) &&
- writeStatToFile(fd, "failed_suspend", failedSuspend) &&
- writeStatToFile(fd, "failed_suspend_late", failedSuspendLate) &&
- writeStatToFile(fd, "failed_suspend_noirq", failedSuspendNoirq) &&
- writeStatToFile(fd, "failed_resume", failedResume) &&
- writeStatToFile(fd, "failed_resume_early", failedResumeEarly) &&
- writeStatToFile(fd, "failed_resume_noirq", failedResumeNoirq) &&
- writeStatToFile(fd, "last_failed_dev", lastFailedDev) &&
- writeStatToFile(fd, "last_failed_errno", lastFailedErrno) &&
- writeStatToFile(fd, "last_failed_step", lastFailedStep);
- }
-
- bool removeDirectoryEntry(const std::string& path) {
- auto callback = [](const char* child, const struct stat*, int file_type,
- struct FTW*) -> int {
- switch (file_type) {
- case FTW_D:
- case FTW_DP:
- case FTW_DNR:
- if (rmdir(child) == -1) {
- PLOG(ERROR) << "rmdir " << child;
- }
- break;
- case FTW_NS:
- default:
- if (rmdir(child) != -1) break;
- // FALLTHRU (for gcc, lint, pcc, etc; and following for clang)
- FALLTHROUGH_INTENDED;
- case FTW_F:
- case FTW_SL:
- case FTW_SLN:
- if (unlink(child) == -1) {
- PLOG(ERROR) << "unlink " << child;
- }
- break;
- }
- return 0;
- };
- return nftw(path.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0;
- }
-
- /**
- * Removes all entries from directory.
- * Returns true on success else false.
- */
- bool clearDirectory(const std::string& dirPath) {
- std::unique_ptr<DIR, decltype(&closedir)> dp(opendir(dirPath.c_str()), &closedir);
- if (!dp) {
- return false;
- }
-
- rewinddir(dp.get());
- struct dirent* de;
- while ((de = readdir(dp.get()))) {
- std::string name(de->d_name);
- if ((name == ".") || (name == "..")) {
- continue;
- }
- if (!removeDirectoryEntry(dirPath + "/" + name)) {
- PLOG(ERROR) << "SystemSuspend: Failed to remove " << name;
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Returns wakelock stats.
- */
- std::vector<WakeLockInfo> getWakelockStats() {
- std::vector<WakeLockInfo> wlStats;
- controlService->getWakeLockStats(&wlStats);
- return wlStats;
- }
-
- /**
- * Returns suspend stats.
- */
- Result<SuspendStats> getSuspendStats() {
- return reinterpret_cast<SystemSuspend*>(suspendService.get())->getSuspendStats();
- }
-
- virtual void SetUp() override {
- kernelWakelockStatsFd = unique_fd(TEMP_FAILURE_RETRY(
- open(kernelWakelockStatsDir.path, O_DIRECTORY | O_CLOEXEC | O_RDONLY)));
- if (kernelWakelockStatsFd < 0) {
- PLOG(FATAL) << "SystemSuspend: Failed to open kernel wakelock stats directory";
- }
-
- suspendStatsFd = unique_fd(
- TEMP_FAILURE_RETRY(open(suspendStatsDir.path, O_DIRECTORY | O_CLOEXEC | O_RDONLY)));
- if (suspendStatsFd < 0) {
- PLOG(FATAL) << "SystemSuspend: Failed to open suspend_stats directory";
- }
-
- // Set up same thread suspend services
- sp<SuspendControlService> suspendControl = new SuspendControlService();
- controlService = suspendControl;
- suspendService = new SystemSuspend(
- unique_fd(-1) /* wakeupCountFd */, unique_fd(-1) /* stateFd */,
- unique_fd(dup(suspendStatsFd)), 1 /* maxNativeStatsEntries */,
- unique_fd(dup(kernelWakelockStatsFd.get())), 0ms /* baseSleepTime */, suspendControl);
- }
-
- virtual void TearDown() override {
- ASSERT_TRUE(clearDirectory(kernelWakelockStatsDir.path));
- ASSERT_TRUE(clearDirectory(suspendStatsDir.path));
- }
-
- sp<ISystemSuspend> suspendService;
- sp<ISuspendControlService> controlService;
- unique_fd kernelWakelockStatsFd;
- unique_fd suspendStatsFd;
- TemporaryDir kernelWakelockStatsDir;
- TemporaryDir suspendStatsDir;
-};
-
-// Test that getWakeLockStats has correct information about Native WakeLocks.
-TEST_F(SystemSuspendSameThreadTest, GetNativeWakeLockStats) {
- std::string fakeWlName = "FakeLock";
- {
- sp<IWakeLock> fakeLock = acquireWakeLock(fakeWlName);
- std::vector<WakeLockInfo> wlStats = getWakelockStats();
- ASSERT_EQ(wlStats.size(), 1);
-
- WakeLockInfo nwlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName, &nwlInfo));
- ASSERT_EQ(nwlInfo.name, fakeWlName);
- ASSERT_EQ(nwlInfo.activeCount, 1);
- ASSERT_EQ(nwlInfo.isActive, true);
- ASSERT_FALSE(nwlInfo.isKernelWakelock);
-
- ASSERT_EQ(nwlInfo.pid, getpid());
-
- ASSERT_EQ(nwlInfo.eventCount, 0);
- ASSERT_EQ(nwlInfo.expireCount, 0);
- ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
- ASSERT_EQ(nwlInfo.wakeupCount, 0);
-
- // We sleep so that the wake lock stats entry get updated with a different timestamp.
- std::this_thread::sleep_for(1s);
- }
- std::vector<WakeLockInfo> wlStats = getWakelockStats();
- ASSERT_EQ(wlStats.size(), 1);
-
- WakeLockInfo nwlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName, &nwlInfo));
- ASSERT_EQ(nwlInfo.name, fakeWlName);
- ASSERT_EQ(nwlInfo.activeCount, 1);
- ASSERT_GE(nwlInfo.maxTime, 1000);
- ASSERT_GE(nwlInfo.totalTime, 1000);
- ASSERT_EQ(nwlInfo.isActive, false);
- ASSERT_EQ(nwlInfo.activeTime, 0); // No longer active
- ASSERT_FALSE(nwlInfo.isKernelWakelock);
-
- ASSERT_EQ(nwlInfo.pid, getpid());
-
- ASSERT_EQ(nwlInfo.eventCount, 0);
- ASSERT_EQ(nwlInfo.expireCount, 0);
- ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
- ASSERT_EQ(nwlInfo.wakeupCount, 0);
-}
-
-// Test that getWakeLockStats has correct information about Kernel WakeLocks.
-TEST_F(SystemSuspendSameThreadTest, GetKernelWakeLockStats) {
- std::string fakeKwlName1 = "fakeKwl1";
- std::string fakeKwlName2 = "fakeKwl2";
- addKernelWakelock(fakeKwlName1);
- addKernelWakelock(fakeKwlName2, 10 /* activeCount */);
-
- std::vector<WakeLockInfo> wlStats = getWakelockStats();
-
- ASSERT_EQ(wlStats.size(), 2);
-
- WakeLockInfo kwlInfo1;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName1, &kwlInfo1));
- ASSERT_EQ(kwlInfo1.name, fakeKwlName1);
- ASSERT_EQ(kwlInfo1.activeCount, 42);
- ASSERT_EQ(kwlInfo1.lastChange, 42);
- ASSERT_EQ(kwlInfo1.maxTime, 42);
- ASSERT_EQ(kwlInfo1.totalTime, 42);
- ASSERT_EQ(kwlInfo1.isActive, true);
- ASSERT_EQ(kwlInfo1.activeTime, 42);
- ASSERT_TRUE(kwlInfo1.isKernelWakelock);
-
- ASSERT_EQ(kwlInfo1.pid, -1);
-
- ASSERT_EQ(kwlInfo1.eventCount, 42);
- ASSERT_EQ(kwlInfo1.expireCount, 42);
- ASSERT_EQ(kwlInfo1.preventSuspendTime, 42);
- ASSERT_EQ(kwlInfo1.wakeupCount, 42);
-
- WakeLockInfo kwlInfo2;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName2, &kwlInfo2));
- ASSERT_EQ(kwlInfo2.name, fakeKwlName2);
- ASSERT_EQ(kwlInfo2.activeCount, 10);
- ASSERT_EQ(kwlInfo2.lastChange, 42);
- ASSERT_EQ(kwlInfo2.maxTime, 42);
- ASSERT_EQ(kwlInfo2.totalTime, 42);
- ASSERT_EQ(kwlInfo2.isActive, true);
- ASSERT_EQ(kwlInfo2.activeTime, 42);
- ASSERT_TRUE(kwlInfo2.isKernelWakelock);
-
- ASSERT_EQ(kwlInfo2.pid, -1);
-
- ASSERT_EQ(kwlInfo2.eventCount, 42);
- ASSERT_EQ(kwlInfo2.expireCount, 42);
- ASSERT_EQ(kwlInfo2.preventSuspendTime, 42);
- ASSERT_EQ(kwlInfo2.wakeupCount, 42);
-}
-
-// Test that getWakeLockStats has correct information about Native AND Kernel WakeLocks.
-TEST_F(SystemSuspendSameThreadTest, GetNativeAndKernelWakeLockStats) {
- std::string fakeNwlName = "fakeNwl";
- std::string fakeKwlName = "fakeKwl";
-
- addKernelWakelock(fakeKwlName);
-
- {
- sp<IWakeLock> fakeLock = acquireWakeLock(fakeNwlName);
- std::vector<WakeLockInfo> wlStats = getWakelockStats();
- ASSERT_EQ(wlStats.size(), 2);
-
- // Native Wakelock Stats
- WakeLockInfo nwlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeNwlName, &nwlInfo));
- ASSERT_EQ(nwlInfo.name, fakeNwlName);
- ASSERT_EQ(nwlInfo.activeCount, 1);
- ASSERT_EQ(nwlInfo.isActive, true);
- ASSERT_FALSE(nwlInfo.isKernelWakelock);
-
- ASSERT_EQ(nwlInfo.pid, getpid());
-
- ASSERT_EQ(nwlInfo.eventCount, 0);
- ASSERT_EQ(nwlInfo.expireCount, 0);
- ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
- ASSERT_EQ(nwlInfo.wakeupCount, 0);
-
- // Kernel Wakelock Stats
- WakeLockInfo kwlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName, &kwlInfo));
- ASSERT_EQ(kwlInfo.name, fakeKwlName);
- ASSERT_EQ(kwlInfo.activeCount, 42);
- ASSERT_EQ(kwlInfo.lastChange, 42);
- ASSERT_EQ(kwlInfo.maxTime, 42);
- ASSERT_EQ(kwlInfo.totalTime, 42);
- ASSERT_EQ(kwlInfo.isActive, true);
- ASSERT_EQ(kwlInfo.activeTime, 42);
- ASSERT_TRUE(kwlInfo.isKernelWakelock);
-
- ASSERT_EQ(kwlInfo.pid, -1);
-
- ASSERT_EQ(kwlInfo.eventCount, 42);
- ASSERT_EQ(kwlInfo.expireCount, 42);
- ASSERT_EQ(kwlInfo.preventSuspendTime, 42);
- ASSERT_EQ(kwlInfo.wakeupCount, 42);
-
- // We sleep so that the wake lock stats entry get updated with a different timestamp.
- std::this_thread::sleep_for(1s);
- }
- std::vector<WakeLockInfo> wlStats = getWakelockStats();
- ASSERT_EQ(wlStats.size(), 2);
-
- // Native Wakelock Stats
- WakeLockInfo nwlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeNwlName, &nwlInfo));
- ASSERT_EQ(nwlInfo.name, fakeNwlName);
- ASSERT_EQ(nwlInfo.activeCount, 1);
- ASSERT_GE(nwlInfo.maxTime, 1000);
- ASSERT_GE(nwlInfo.totalTime, 1000);
- ASSERT_EQ(nwlInfo.isActive, false);
- ASSERT_EQ(nwlInfo.activeTime, 0); // No longer active
- ASSERT_FALSE(nwlInfo.isKernelWakelock);
-
- ASSERT_EQ(nwlInfo.pid, getpid());
-
- ASSERT_EQ(nwlInfo.eventCount, 0);
- ASSERT_EQ(nwlInfo.expireCount, 0);
- ASSERT_EQ(nwlInfo.preventSuspendTime, 0);
- ASSERT_EQ(nwlInfo.wakeupCount, 0);
-
- // Kernel Wakelock Stats (No changes expected here)
- WakeLockInfo kwlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeKwlName, &kwlInfo));
- ASSERT_EQ(kwlInfo.name, fakeKwlName);
- ASSERT_EQ(kwlInfo.activeCount, 42);
- ASSERT_EQ(kwlInfo.lastChange, 42);
- ASSERT_EQ(kwlInfo.maxTime, 42);
- ASSERT_EQ(kwlInfo.totalTime, 42);
- ASSERT_EQ(kwlInfo.isActive, true);
- ASSERT_EQ(kwlInfo.activeTime, 42);
- ASSERT_TRUE(kwlInfo.isKernelWakelock);
-
- ASSERT_EQ(kwlInfo.pid, -1);
-
- ASSERT_EQ(kwlInfo.eventCount, 42);
- ASSERT_EQ(kwlInfo.expireCount, 42);
- ASSERT_EQ(kwlInfo.preventSuspendTime, 42);
- ASSERT_EQ(kwlInfo.wakeupCount, 42);
-}
-
-// Test that the least recently used native wake lock stats entry is evicted after a given
-// threshold.
-TEST_F(SystemSuspendSameThreadTest, NativeWakeLockStatsLruEviction) {
- std::string fakeWlName1 = "FakeLock1";
- std::string fakeWlName2 = "FakeLock2";
-
- acquireWakeLock(fakeWlName1);
- acquireWakeLock(fakeWlName2);
-
- std::vector<WakeLockInfo> wlStats = getWakelockStats();
-
- // Max number of native stats entries was set to 1 in SystemSuspend constructor.
- ASSERT_EQ(wlStats.size(), 1);
- ASSERT_EQ(wlStats.begin()->name, fakeWlName2);
-
- WakeLockInfo wlInfo;
- ASSERT_TRUE(findWakeLockInfoByName(wlStats, fakeWlName2, &wlInfo));
- ASSERT_FALSE(findWakeLockInfoByName(wlStats, fakeWlName1, &wlInfo)); // Evicted
-}
-
-// Test that GetSuspendStats has correct information.
-TEST_F(SystemSuspendSameThreadTest, GetSuspendStats) {
- addSuspendStats();
-
- Result<SuspendStats> res = getSuspendStats();
-
- ASSERT_TRUE(res);
-
- SuspendStats stats = res.value();
-
- ASSERT_EQ(stats.success, 42);
- ASSERT_EQ(stats.fail, 42);
- ASSERT_EQ(stats.failedFreeze, 42);
- ASSERT_EQ(stats.failedPrepare, 42);
- ASSERT_EQ(stats.failedSuspend, 42);
- ASSERT_EQ(stats.failedSuspendLate, 42);
- ASSERT_EQ(stats.failedSuspendNoirq, 42);
- ASSERT_EQ(stats.failedResume, 42);
- ASSERT_EQ(stats.failedResumeEarly, 42);
- ASSERT_EQ(stats.failedResumeNoirq, 42);
- ASSERT_EQ(stats.lastFailedDev, "fakeDev");
- ASSERT_EQ(stats.lastFailedErrno, 42);
- ASSERT_EQ(stats.lastFailedStep, "fakeStep");
-}
-
} // namespace android
int main(int argc, char** argv) {
setenv("TREBLE_TESTING_OVERRIDE", "true", true);
+ ::testing::AddGlobalTestEnvironment(android::SystemSuspendTestEnvironment::Instance());
::testing::InitGoogleMock(&argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
diff --git a/suspend/1.0/default/WakeLockEntryList.cpp b/suspend/1.0/default/WakeLockEntryList.cpp
deleted file mode 100644
index d8f6b04..0000000
--- a/suspend/1.0/default/WakeLockEntryList.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * Copyright (C) 2019 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 "WakeLockEntryList.h"
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-
-#include <iomanip>
-
-using android::base::ReadFdToString;
-
-namespace android {
-namespace system {
-namespace suspend {
-namespace V1_0 {
-
-static std::ostream& operator<<(std::ostream& out, const WakeLockInfo& entry) {
- const char* sep = " | ";
- const char* notApplicable = "---";
- bool kernelWakelock = entry.isKernelWakelock;
-
- // clang-format off
- out << sep
- << std::left << std::setw(30) << entry.name << sep
- << std::right << std::setw(6)
- << ((kernelWakelock) ? notApplicable : std::to_string(entry.pid)) << sep
- << std::left << std::setw(6) << ((kernelWakelock) ? "Kernel" : "Native") << sep
- << std::left << std::setw(8) << ((entry.isActive) ? "Active" : "Inactive") << sep
- << std::right << std::setw(12) << entry.activeCount << sep
- << std::right << std::setw(12) << std::to_string(entry.totalTime) + "ms" << sep
- << std::right << std::setw(12) << std::to_string(entry.maxTime) + "ms" << sep
- << std::right << std::setw(12)
- << ((kernelWakelock) ? std::to_string(entry.eventCount) : notApplicable) << sep
- << std::right << std::setw(12)
- << ((kernelWakelock) ? std::to_string(entry.wakeupCount) : notApplicable) << sep
- << std::right << std::setw(12)
- << ((kernelWakelock) ? std::to_string(entry.expireCount) : notApplicable) << sep
- << std::right << std::setw(20)
- << ((kernelWakelock) ? std::to_string(entry.preventSuspendTime) + "ms" : notApplicable)
- << sep
- << std::right << std::setw(16) << std::to_string(entry.lastChange) + "ms" << sep;
- // clang-format on
-
- return out;
-}
-
-std::ostream& operator<<(std::ostream& out, const WakeLockEntryList& list) {
- std::vector<WakeLockInfo> wlStats;
- list.getWakeLockStats(&wlStats);
- int width = 194;
- const char* sep = " | ";
- std::stringstream ss;
- ss << " " << std::setfill('-') << std::setw(width) << "\n";
- std::string div = ss.str();
-
- out << div;
-
- std::stringstream header;
- header << sep << std::right << std::setw(((width - 14) / 2) + 14) << "WAKELOCK STATS"
- << std::right << std::setw((width - 14) / 2) << sep << "\n";
- out << header.str();
-
- out << div;
-
- // Col names
- // clang-format off
- out << sep
- << std::left << std::setw(30) << "NAME" << sep
- << std::left << std::setw(6) << "PID" << sep
- << std::left << std::setw(6) << "TYPE" << sep
- << std::left << std::setw(8) << "STATUS" << sep
- << std::left << std::setw(12) << "ACTIVE COUNT" << sep
- << std::left << std::setw(12) << "TOTAL TIME" << sep
- << std::left << std::setw(12) << "MAX TIME" << sep
- << std::left << std::setw(12) << "EVENT COUNT" << sep
- << std::left << std::setw(12) << "WAKEUP COUNT" << sep
- << std::left << std::setw(12) << "EXPIRE COUNT" << sep
- << std::left << std::setw(20) << "PREVENT SUSPEND TIME" << sep
- << std::left << std::setw(16) << "LAST CHANGE" << sep
- << "\n";
- // clang-format on
-
- out << div;
-
- // Rows
- for (const WakeLockInfo& entry : wlStats) {
- out << entry << "\n";
- }
-
- out << div;
- return out;
-}
-
-/**
- * Returns the monotonic time in milliseconds.
- */
-TimestampType getTimeNow() {
- timespec monotime;
- clock_gettime(CLOCK_MONOTONIC, &monotime);
- return std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::nanoseconds{monotime.tv_nsec})
- .count() +
- std::chrono::duration_cast<std::chrono::milliseconds>(
- std::chrono::seconds{monotime.tv_sec})
- .count();
-}
-
-WakeLockEntryList::WakeLockEntryList(size_t capacity, unique_fd kernelWakelockStatsFd)
- : mCapacity(capacity), mKernelWakelockStatsFd(std::move(kernelWakelockStatsFd)) {}
-
-/**
- * Evicts LRU from back of list if stats is at capacity.
- */
-void WakeLockEntryList::evictIfFull() {
- if (mStats.size() == mCapacity) {
- auto evictIt = mStats.end();
- std::advance(evictIt, -1);
- auto evictKey = std::make_pair(evictIt->name, evictIt->pid);
- mLookupTable.erase(evictKey);
- mStats.erase(evictIt);
- LOG(ERROR) << "WakeLock Stats: Stats capacity met, consider adjusting capacity to "
- "avoid stats eviction.";
- }
-}
-
-/**
- * Inserts entry as MRU.
- */
-void WakeLockEntryList::insertEntry(WakeLockInfo entry) {
- auto key = std::make_pair(entry.name, entry.pid);
- mStats.emplace_front(std::move(entry));
- mLookupTable[key] = mStats.begin();
-}
-
-/**
- * Removes entry from the stats list.
- */
-void WakeLockEntryList::deleteEntry(std::list<WakeLockInfo>::iterator entry) {
- auto key = std::make_pair(entry->name, entry->pid);
- mLookupTable.erase(key);
- mStats.erase(entry);
-}
-
-/**
- * Creates and returns a native wakelock entry.
- */
-WakeLockInfo WakeLockEntryList::createNativeEntry(const std::string& name, int pid,
- TimestampType timeNow) const {
- WakeLockInfo info;
-
- info.name = name;
- // It only makes sense to create a new entry on initial activation of the lock.
- info.activeCount = 1;
- info.lastChange = timeNow;
- info.maxTime = 0;
- info.totalTime = 0;
- info.isActive = true;
- info.activeTime = 0;
- info.isKernelWakelock = false;
-
- info.pid = pid;
-
- info.eventCount = 0;
- info.expireCount = 0;
- info.preventSuspendTime = 0;
- info.wakeupCount = 0;
-
- return info;
-}
-/*
- * Creates and returns a kernel wakelock entry with data read from mKernelWakelockStatsFd
- */
-WakeLockInfo WakeLockEntryList::createKernelEntry(const std::string& kwlId) const {
- WakeLockInfo info;
-
- info.activeCount = 0;
- info.lastChange = 0;
- info.maxTime = 0;
- info.totalTime = 0;
- info.isActive = false;
- info.activeTime = 0;
- info.isKernelWakelock = true;
-
- info.pid = -1; // N/A
-
- info.eventCount = 0;
- info.expireCount = 0;
- info.preventSuspendTime = 0;
- info.wakeupCount = 0;
-
- unique_fd wakelockFd{TEMP_FAILURE_RETRY(
- openat(mKernelWakelockStatsFd, kwlId.c_str(), O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
- if (wakelockFd < 0) {
- PLOG(ERROR) << "Error opening kernel wakelock stats for: " << kwlId;
- }
-
- std::unique_ptr<DIR, decltype(&closedir)> wakelockDp(fdopendir(dup(wakelockFd.get())),
- &closedir);
- if (wakelockDp) {
- struct dirent* de;
- while ((de = readdir(wakelockDp.get()))) {
- std::string statName(de->d_name);
- if ((statName == ".") || (statName == ".." || statName == "power" ||
- statName == "subsystem" || statName == "uevent")) {
- continue;
- }
-
- unique_fd statFd{
- TEMP_FAILURE_RETRY(openat(wakelockFd, statName.c_str(), O_CLOEXEC | O_RDONLY))};
- if (statFd < 0) {
- PLOG(ERROR) << "Error opening " << statName << " for " << kwlId;
- }
-
- std::string valStr;
- if (!ReadFdToString(statFd.get(), &valStr)) {
- PLOG(ERROR) << "Error reading " << statName << " for " << kwlId;
- continue;
- }
-
- // Trim newline
- valStr.erase(std::remove(valStr.begin(), valStr.end(), '\n'), valStr.end());
-
- if (statName == "name") {
- info.name = valStr;
- continue;
- }
-
- int64_t statVal = std::stoll(valStr);
-
- if (statName == "active_count") {
- info.activeCount = statVal;
- } else if (statName == "active_time_ms") {
- info.activeTime = statVal;
- } else if (statName == "event_count") {
- info.eventCount = statVal;
- } else if (statName == "expire_count") {
- info.expireCount = statVal;
- } else if (statName == "last_change_ms") {
- info.lastChange = statVal;
- } else if (statName == "max_time_ms") {
- info.maxTime = statVal;
- } else if (statName == "prevent_suspend_time_ms") {
- info.preventSuspendTime = statVal;
- } else if (statName == "total_time_ms") {
- info.totalTime = statVal;
- } else if (statName == "wakeup_count") {
- info.wakeupCount = statVal;
- }
- }
- }
-
- // Derived stats
- info.isActive = info.activeTime > 0;
-
- return info;
-}
-
-void WakeLockEntryList::getKernelWakelockStats(std::vector<WakeLockInfo>* aidl_return) const {
- std::unique_ptr<DIR, decltype(&closedir)> dp(fdopendir(dup(mKernelWakelockStatsFd.get())),
- &closedir);
- if (dp) {
- // rewinddir, else subsequent calls will not get any kernel wakelocks.
- rewinddir(dp.get());
-
- struct dirent* de;
- while ((de = readdir(dp.get()))) {
- std::string kwlId(de->d_name);
- if ((kwlId == ".") || (kwlId == "..")) {
- continue;
- }
- WakeLockInfo entry = createKernelEntry(kwlId);
- aidl_return->emplace_back(std::move(entry));
- }
- } else {
- PLOG(ERROR)
- << "SystemSuspend: Failed to get directory pointer to kernel wakelock stats dir";
- }
-}
-
-void WakeLockEntryList::updateOnAcquire(const std::string& name, int pid, TimestampType timeNow) {
- std::lock_guard<std::mutex> lock(mStatsLock);
-
- auto key = std::make_pair(name, pid);
- auto it = mLookupTable.find(key);
- if (it == mLookupTable.end()) {
- evictIfFull();
- WakeLockInfo newEntry = createNativeEntry(name, pid, timeNow);
- insertEntry(newEntry);
- } else {
- auto staleEntry = it->second;
- WakeLockInfo updatedEntry = *staleEntry;
-
- // Update entry
- updatedEntry.isActive = true;
- updatedEntry.activeTime = 0;
- updatedEntry.activeCount++;
- updatedEntry.lastChange = timeNow;
-
- deleteEntry(staleEntry);
- insertEntry(std::move(updatedEntry));
- }
-}
-
-void WakeLockEntryList::updateOnRelease(const std::string& name, int pid, TimestampType timeNow) {
- std::lock_guard<std::mutex> lock(mStatsLock);
-
- auto key = std::make_pair(name, pid);
- auto it = mLookupTable.find(key);
- if (it == mLookupTable.end()) {
- LOG(INFO) << "WakeLock Stats: A stats entry for, \"" << name
- << "\" was not found. This is most likely due to it being evicted.";
- } else {
- auto staleEntry = it->second;
- WakeLockInfo updatedEntry = *staleEntry;
-
- // Update entry
- TimestampType timeDelta = timeNow - updatedEntry.lastChange;
- updatedEntry.isActive = false;
- updatedEntry.activeTime += timeDelta;
- updatedEntry.maxTime = std::max(updatedEntry.maxTime, updatedEntry.activeTime);
- updatedEntry.activeTime = 0; // No longer active
- updatedEntry.totalTime += timeDelta;
- updatedEntry.lastChange = timeNow;
-
- deleteEntry(staleEntry);
- insertEntry(std::move(updatedEntry));
- }
-}
-/**
- * Updates the native wakelock stats based on the current time.
- */
-void WakeLockEntryList::updateNow() {
- std::lock_guard<std::mutex> lock(mStatsLock);
-
- TimestampType timeNow = getTimeNow();
-
- for (std::list<WakeLockInfo>::iterator it = mStats.begin(); it != mStats.end(); ++it) {
- if (it->isActive) {
- TimestampType timeDelta = timeNow - it->lastChange;
- it->activeTime += timeDelta;
- it->maxTime = std::max(it->maxTime, it->activeTime);
- it->totalTime += timeDelta;
- it->lastChange = timeNow;
- }
- }
-}
-
-void WakeLockEntryList::getWakeLockStats(std::vector<WakeLockInfo>* aidl_return) const {
- std::lock_guard<std::mutex> lock(mStatsLock);
-
- for (const WakeLockInfo& entry : mStats) {
- aidl_return->emplace_back(entry);
- }
-
- getKernelWakelockStats(aidl_return);
-}
-
-} // namespace V1_0
-} // namespace suspend
-} // namespace system
-} // namespace android
diff --git a/suspend/1.0/default/WakeLockEntryList.h b/suspend/1.0/default/WakeLockEntryList.h
deleted file mode 100644
index 3b72f77..0000000
--- a/suspend/1.0/default/WakeLockEntryList.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2019 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 ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H
-#define ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H
-
-#include <android-base/unique_fd.h>
-#include <android/system/suspend/WakeLockInfo.h>
-#include <utils/Mutex.h>
-
-#include <list>
-#include <mutex>
-#include <unordered_map>
-#include <utility>
-#include <vector>
-
-namespace android {
-namespace system {
-namespace suspend {
-namespace V1_0 {
-
-using android::base::unique_fd;
-using TimestampType = int64_t;
-
-TimestampType getTimeNow();
-
-/*
- * WakeLockEntryList to collect wake lock stats.
- * This class is thread safe.
- */
-class WakeLockEntryList {
- public:
- WakeLockEntryList(size_t capacity, unique_fd kernelWakelockStatsFd);
- void updateOnAcquire(const std::string& name, int pid, TimestampType timeNow);
- void updateOnRelease(const std::string& name, int pid, TimestampType timeNow);
- // updateNow() should be called before getWakeLockStats() to ensure stats are
- // updated wrt the current time.
- void updateNow();
- void getWakeLockStats(std::vector<WakeLockInfo>* aidl_return) const;
- friend std::ostream& operator<<(std::ostream& out, const WakeLockEntryList& list);
-
- private:
- void evictIfFull() REQUIRES(mStatsLock);
- void insertEntry(WakeLockInfo entry) REQUIRES(mStatsLock);
- void deleteEntry(std::list<WakeLockInfo>::iterator entry) REQUIRES(mStatsLock);
- WakeLockInfo createNativeEntry(const std::string& name, int pid, TimestampType timeNow) const;
- WakeLockInfo createKernelEntry(const std::string& name) const;
- void getKernelWakelockStats(std::vector<WakeLockInfo>* aidl_return) const;
-
- // Hash for WakeLockEntry key (pair<std::string, int>)
- struct LockHash {
- std::size_t operator()(const std::pair<std::string, int>& key) const {
- return std::hash<std::string>()(key.first) ^ std::hash<int>()(key.second);
- }
- };
-
- size_t mCapacity;
- unique_fd mKernelWakelockStatsFd;
-
- mutable std::mutex mStatsLock;
-
- // std::list and std::unordered map are used to support both inserting a stat
- // and eviction of the LRU stat in O(1) time. The LRU stat is maintained at
- // the back of the list.
- std::list<WakeLockInfo> mStats GUARDED_BY(mStatsLock);
- std::unordered_map<std::pair<std::string, int>, std::list<WakeLockInfo>::iterator, LockHash>
- mLookupTable GUARDED_BY(mStatsLock);
-};
-
-} // namespace V1_0
-} // namespace suspend
-} // namespace system
-} // namespace android
-
-#endif // ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H
diff --git a/suspend/1.0/default/android.system.suspend@1.0-service.rc b/suspend/1.0/default/android.system.suspend@1.0-service.rc
index 965ca16..c5d3869 100644
--- a/suspend/1.0/default/android.system.suspend@1.0-service.rc
+++ b/suspend/1.0/default/android.system.suspend@1.0-service.rc
@@ -1,5 +1,5 @@
service system_suspend /system/bin/hw/android.system.suspend@1.0-service
- class early_hal
+ class hal
user system
group system wakelock
capabilities BLOCK_SUSPEND
diff --git a/suspend/1.0/default/main.cpp b/suspend/1.0/default/main.cpp
index ab1c9d0..7f2dead 100644
--- a/suspend/1.0/default/main.cpp
+++ b/suspend/1.0/default/main.cpp
@@ -14,21 +14,23 @@
* limitations under the License.
*/
+#include "SuspendControlService.h"
+#include "SystemSuspend.h"
+
#include <android-base/logging.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/native_handle.h>
-#include <fcntl.h>
#include <hidl/HidlTransportSupport.h>
#include <hwbinder/ProcessState.h>
+
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
-#include <unistd.h>
-#include "SuspendControlService.h"
-#include "SystemSuspend.h"
+#include <fcntl.h>
+#include <unistd.h>
using android::sp;
using android::status_t;
@@ -41,9 +43,6 @@ using android::system::suspend::V1_0::SuspendControlService;
using android::system::suspend::V1_0::SystemSuspend;
using namespace std::chrono_literals;
-static constexpr size_t kNativeWakeLockStatsCapacity = 1000;
-static constexpr char kSysClassWakeup[] = "/sys/class/wakeup";
-static constexpr char kSysPowerSuspendStats[] = "/sys/power/suspend_stats";
static constexpr char kSysPowerWakeupCount[] = "/sys/power/wakeup_count";
static constexpr char kSysPowerState[] = "/sys/power/state";
@@ -56,16 +55,6 @@ int main() {
if (stateFd < 0) {
PLOG(ERROR) << "error opening " << kSysPowerState;
}
- unique_fd kernelWakelockStatsFd{
- TEMP_FAILURE_RETRY(open(kSysClassWakeup, O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
- if (kernelWakelockStatsFd < 0) {
- PLOG(ERROR) << "SystemSuspend: Error opening " << kSysClassWakeup;
- }
- unique_fd suspendStatsFd{
- TEMP_FAILURE_RETRY(open(kSysPowerSuspendStats, O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
- if (suspendStatsFd < 0) {
- PLOG(ERROR) << "SystemSuspend: Error opening " << kSysPowerSuspendStats;
- }
// If either /sys/power/wakeup_count or /sys/power/state fail to open, we construct
// SystemSuspend with blocking fds. This way this process will keep running, handle wake lock
@@ -91,9 +80,8 @@ int main() {
ps->startThreadPool();
sp<SystemSuspend> suspend =
- new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd), std::move(suspendStatsFd),
- kNativeWakeLockStatsCapacity, std::move(kernelWakelockStatsFd),
- 100ms /* baseSleepTime */, suspendControl, true /* mUseSuspendCounter*/);
+ new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd), 100 /* maxStatsEntries */,
+ 100ms /* baseSleepTime */, suspendControl, false /* mUseSuspendCounter*/);
status_t status = suspend->registerAsService();
if (android::OK != status) {
LOG(FATAL) << "Unable to register system-suspend service: " << status;
diff --git a/suspend/aidl/Android.bp b/suspend/aidl/Android.bp
index f2978c3..2917bfc 100644
--- a/suspend/aidl/Android.bp
+++ b/suspend/aidl/Android.bp
@@ -4,11 +4,6 @@ aidl_interface {
srcs: [
"android/system/suspend/ISuspendControlService.aidl",
"android/system/suspend/ISuspendCallback.aidl",
- "android/system/suspend/WakeLockInfo.aidl",
],
- backend: {
- java: {
- sdk_version: "28",
- },
- },
}
+
diff --git a/suspend/aidl/android/system/suspend/ISuspendControlService.aidl b/suspend/aidl/android/system/suspend/ISuspendControlService.aidl
index b9ac74c..c50a882 100644
--- a/suspend/aidl/android/system/suspend/ISuspendControlService.aidl
+++ b/suspend/aidl/android/system/suspend/ISuspendControlService.aidl
@@ -17,7 +17,6 @@
package android.system.suspend;
import android.system.suspend.ISuspendCallback;
-import android.system.suspend.WakeLockInfo;
/**
* Interface exposed by the suspend hal that allows framework to toggle the suspend loop and
@@ -46,9 +45,4 @@ interface ISuspendControlService
* Suspends the system even if there are wakelocks being held.
*/
boolean forceSuspend();
-
- /**
- * Returns a list of wake lock stats.
- */
- WakeLockInfo[] getWakeLockStats();
}
diff --git a/suspend/aidl/android/system/suspend/WakeLockInfo.aidl b/suspend/aidl/android/system/suspend/WakeLockInfo.aidl
deleted file mode 100644
index 12c6a66..0000000
--- a/suspend/aidl/android/system/suspend/WakeLockInfo.aidl
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-package android.system.suspend;
-
-
-/**
- * Parcelable WakelockInfo - Representation of wake lock stats.
- *
- * Wakelocks obtained via SystemSuspend are hereafter referred to as
- * native wake locks.
- *
- * @name: Name of wake lock (Not guaranteed to be unique).
- * @activeCount: Number of times the wake lock was activated.
- * @lastChange: Monotonic time (in ms) when the wake lock was last touched.
- * @maxTime: Maximum time (in ms) this wake lock has been continuously active.
- * @totalTime: Total time (in ms) this wake lock has been active.
- * @isActive: Status of wake lock.
- * @activeTime: Time since wake lock was activated, 0 if wake lock is not active.
- * @isKernelWakelock: True if kernel wake lock, false if native wake lock.
- *
- * The stats below are specific to NATIVE wake locks and hold no valid
- * data in the context of kernel wake locks.
- *
- * @pid: Pid of process that acquired native wake lock.
- *
- * The stats below are specific to KERNEL wake locks and hold no valid
- * data in the context of native wake locks.
- *
- * @eventCount: Number of signaled wakeup events.
- * @expireCount: Number times the wakeup source's timeout expired.
- * @preventSuspendTime: Total time this wake lock has been preventing autosuspend.
- * @wakeupCount: Number of times the wakeup source might abort suspend.
- */
-parcelable WakeLockInfo {
- @utf8InCpp String name;
- long activeCount;
- long lastChange;
- long maxTime;
- long totalTime;
- boolean isActive;
- long activeTime;
- boolean isKernelWakelock;
-
- // ---- Specific to Native Wake locks ---- //
- int pid;
-
- // ---- Specific to Kernel Wake locks ---- //
- long eventCount;
- long expireCount;
- long preventSuspendTime;
- long wakeupCount;
-}
diff --git a/wifi/keystore/1.0/Android.bp b/wifi/keystore/1.0/Android.bp
index 6b12292..1afcdc2 100644
--- a/wifi/keystore/1.0/Android.bp
+++ b/wifi/keystore/1.0/Android.bp
@@ -14,3 +14,4 @@ hidl_interface {
],
gen_java: true,
}
+
diff --git a/wifi/keystore/1.0/default/Android.bp b/wifi/keystore/1.0/default/Android.bp
index d5339ef..e7d1d35 100644
--- a/wifi/keystore/1.0/default/Android.bp
+++ b/wifi/keystore/1.0/default/Android.bp
@@ -1,4 +1,4 @@
-cc_library_static {
+cc_library_shared {
name: "libwifikeystorehal",
cppflags: [
"-Wall",
@@ -12,6 +12,7 @@ cc_library_static {
"libbinder",
"libcutils",
"libhidlbase",
+ "libhidltransport",
"libkeystore_aidl",
"libkeystore_binder",
"libkeystore_parcelables",
diff --git a/wifi/keystore/1.0/vts/functional/Android.bp b/wifi/keystore/1.0/vts/functional/Android.bp
index b0d398c..fa7464d 100644
--- a/wifi/keystore/1.0/vts/functional/Android.bp
+++ b/wifi/keystore/1.0/vts/functional/Android.bp
@@ -24,6 +24,7 @@ cc_test {
"liblog",
"libcutils",
"libhidlbase",
+ "libhidltransport",
"libnativehelper",
"libutils",
"libkeystore_binder",
@@ -32,6 +33,7 @@ cc_test {
"libkeystore_parcelables",
"libkeymaster4support",
"libbinderthreadstate",
+ "libhwbinder",
],
static_libs: [
"VtsHalHidlTargetTestBase",
diff --git a/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp b/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp
index 12096b4..13a07f8 100644
--- a/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp
+++ b/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp
@@ -254,24 +254,21 @@ TEST_F(WifiKeystoreHalTest, Sign_empty_data) {
GTEST_SKIP() << "Device not running a debuggable build, cannot make test keys";
}
- bool callbackInvoked = false;
+ IKeystore::KeystoreStatusCode statusCode;
- auto callback = [&callbackInvoked](IKeystore::KeystoreStatusCode /*status*/,
- const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
- // The result is ignored; this callback is a no-op.
- callbackInvoked = true;
+ auto callback = [&statusCode](IKeystore::KeystoreStatusCode status,
+ const ::android::hardware::hidl_vec<uint8_t>& /*value*/) {
+ statusCode = status;
return;
};
bool result = generateKey(kTestKeyName, KeyPurpose::SIGNING, AID_WIFI);
EXPECT_EQ(result, true);
- // The data to sign is empty. The return code is not important, and the attempt could be
- // interpreted as valid or an error case. The goal is to determine that the callback
- // was invokved.
+ // The data to sign is empty, and a failure is expected
::android::hardware::hidl_vec<uint8_t> dataToSign;
keystore->sign(kTestKeyName, dataToSign, callback);
- EXPECT_EQ(true, callbackInvoked);
+ EXPECT_EQ(IKeystore::KeystoreStatusCode::ERROR_UNKNOWN, statusCode);
}
TEST_F(WifiKeystoreHalTest, Sign_wrong_key_purpose) {