Merge "Speed up kernel wakelock polling" into main
diff --git a/suspend/1.0/default/Android.bp b/suspend/1.0/default/Android.bp
index d203698..6652b6d 100644
--- a/suspend/1.0/default/Android.bp
+++ b/suspend/1.0/default/Android.bp
@@ -19,6 +19,9 @@
cc_defaults {
name: "system_suspend_defaults",
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ ],
shared_libs: [
"libbase",
"libbinder",
@@ -27,6 +30,10 @@
"libhidlbase",
"liblog",
"libutils",
+ "server_configurable_flags",
+ ],
+ static_libs: [
+ "suspend_service_flags_c_lib",
],
cflags: [
"-Wall",
@@ -206,3 +213,15 @@
"fuzzers/SuspendServiceInternalFuzzer.cpp",
],
}
+
+aconfig_declarations {
+ name: "suspend_service_flags",
+ package: "suspend_service.flags",
+ container: "system",
+ srcs: ["flags.aconfig"],
+}
+
+cc_aconfig_library {
+ name: "suspend_service_flags_c_lib",
+ aconfig_declarations: "suspend_service_flags",
+}
diff --git a/suspend/1.0/default/SuspendControlService.cpp b/suspend/1.0/default/SuspendControlService.cpp
index 43f17db..3e88faf 100644
--- a/suspend/1.0/default/SuspendControlService.cpp
+++ b/suspend/1.0/default/SuspendControlService.cpp
@@ -183,7 +183,22 @@
}
suspendService->updateStatsNow();
- suspendService->getStatsList().getWakeLockStats(_aidl_return);
+ suspendService->getStatsList().getWakeLockStats(
+ BnSuspendControlServiceInternal::WAKE_LOCK_INFO_ALL_FIELDS, _aidl_return);
+
+ return binder::Status::ok();
+}
+
+binder::Status SuspendControlServiceInternal::getWakeLockStatsFiltered(
+ int wakeLockInfoFieldBitMask, 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(wakeLockInfoFieldBitMask, _aidl_return);
return binder::Status::ok();
}
diff --git a/suspend/1.0/default/SuspendControlService.h b/suspend/1.0/default/SuspendControlService.h
index 7d7e0ae..b6e34ff 100644
--- a/suspend/1.0/default/SuspendControlService.h
+++ b/suspend/1.0/default/SuspendControlService.h
@@ -75,6 +75,8 @@
binder::Status forceSuspend(bool* _aidl_return) override;
binder::Status getSuspendStats(SuspendInfo* _aidl_return) override;
binder::Status getWakeLockStats(std::vector<WakeLockInfo>* _aidl_return) override;
+ binder::Status getWakeLockStatsFiltered(int wakeLockInfoFieldBitMask,
+ std::vector<WakeLockInfo>* _aidl_return) override;
binder::Status getWakeupStats(std::vector<WakeupInfo>* _aidl_return) override;
void setSuspendService(const wp<SystemSuspend>& suspend);
diff --git a/suspend/1.0/default/SystemSuspend.cpp b/suspend/1.0/default/SystemSuspend.cpp
index 9493e85..760aea8 100644
--- a/suspend/1.0/default/SystemSuspend.cpp
+++ b/suspend/1.0/default/SystemSuspend.cpp
@@ -28,6 +28,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/binder_manager.h>
+#include <android/system/suspend/internal/ISuspendControlServiceInternal.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -50,6 +51,8 @@
using ::android::base::WriteStringToFd;
using ::std::string;
+using ISCSI = ::android::system::suspend::internal::ISuspendControlServiceInternal;
+
namespace android {
namespace system {
namespace suspend {
@@ -425,7 +428,8 @@
std::stringstream klStats;
klStats << "Kernel wakesource stats: ";
std::vector<WakeLockInfo> wlStats;
- mStatsList.getWakeLockStats(&wlStats);
+ mStatsList.getWakeLockStats(
+ ISCSI::WAKE_LOCK_INFO_ACTIVE_COUNT | ISCSI::WAKE_LOCK_INFO_TOTAL_TIME, &wlStats);
for (const WakeLockInfo& wake : wlStats) {
if ((wake.isKernelWakelock) && (wake.activeCount > 0)) {
diff --git a/suspend/1.0/default/SystemSuspendUnitTest.cpp b/suspend/1.0/default/SystemSuspendUnitTest.cpp
index 03288ab..f6b6db3 100644
--- a/suspend/1.0/default/SystemSuspendUnitTest.cpp
+++ b/suspend/1.0/default/SystemSuspendUnitTest.cpp
@@ -30,6 +30,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <hidl/HidlTransportSupport.h>
+#include <suspend_service_flags.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -228,7 +229,8 @@
size_t getActiveWakeLockCount() {
std::vector<WakeLockInfo> wlStats;
- controlServiceInternal->getWakeLockStats(&wlStats);
+ controlServiceInternal->getWakeLockStatsFiltered(
+ ISuspendControlServiceInternal::WAKE_LOCK_INFO_ACTIVE_COUNT, &wlStats);
return count_if(wlStats.begin(), wlStats.end(), [](auto entry) { return entry.isActive; });
}
@@ -1199,9 +1201,10 @@
/**
* Returns wakelock stats.
*/
- std::vector<WakeLockInfo> getWakelockStats() {
+ std::vector<WakeLockInfo> getWakelockStats(
+ int32_t selectBitmap = ISuspendControlServiceInternal::WAKE_LOCK_INFO_ALL_FIELDS) {
std::vector<WakeLockInfo> wlStats;
- controlServiceInternal->getWakeLockStats(&wlStats);
+ controlServiceInternal->getWakeLockStatsFiltered(selectBitmap, &wlStats);
return wlStats;
}
@@ -1265,6 +1268,24 @@
};
};
+class mock_flag_provider_interface : public suspend_service::flags::flag_provider_interface {
+ public:
+ MOCK_METHOD(bool, fast_kernel_wakelock_reporting, (), (override));
+};
+
+class ParameterizedSystemSuspendSameThreadTest : public SystemSuspendSameThreadTest,
+ public ::testing::WithParamInterface<bool> {
+ protected:
+ void SetUp() override {
+ auto mock_flag_provider = std::make_unique<mock_flag_provider_interface>();
+ ON_CALL(*mock_flag_provider, fast_kernel_wakelock_reporting())
+ .WillByDefault(::testing::Return(GetParam()));
+ suspend_service::flags::provider_ = std::move(mock_flag_provider);
+
+ SystemSuspendSameThreadTest::SetUp();
+ }
+};
+
// Test that getWakeLockStats has correct information about Native WakeLocks.
TEST_F(SystemSuspendSameThreadTest, GetNativeWakeLockStats) {
std::string fakeWlName = "FakeLock";
@@ -1311,8 +1332,11 @@
ASSERT_EQ(nwlInfo.wakeupCount, 0);
}
+INSTANTIATE_TEST_SUITE_P(ParameterizedSystemSuspendSameThreadTest,
+ ParameterizedSystemSuspendSameThreadTest, ::testing::Bool());
+
// Test that getWakeLockStats has correct information about Kernel WakeLocks.
-TEST_F(SystemSuspendSameThreadTest, GetKernelWakeLockStats) {
+TEST_P(ParameterizedSystemSuspendSameThreadTest, GetKernelWakeLockStats) {
std::string fakeKwlName1 = "fakeKwl1";
std::string fakeKwlName2 = "fakeKwl2";
addKernelWakelock(fakeKwlName1);
@@ -1360,7 +1384,7 @@
}
// Test that getWakeLockStats has correct information about Native AND Kernel WakeLocks.
-TEST_F(SystemSuspendSameThreadTest, GetNativeAndKernelWakeLockStats) {
+TEST_P(ParameterizedSystemSuspendSameThreadTest, GetNativeAndKernelWakeLockStats) {
std::string fakeNwlName = "fakeNwl";
std::string fakeKwlName = "fakeKwl";
@@ -1825,6 +1849,42 @@
ASSERT_EQ(wakeups[2].count, 2);
}
+struct WakeLockInfoField {
+ int32_t bit = 0;
+ std::function<int(WakeLockInfo)> getter;
+ int64_t expectedValue;
+};
+
+// Test that selected fields are properly set.
+TEST_P(ParameterizedSystemSuspendSameThreadTest, GetKernelWakeLockStatsFiltered) {
+ using ISCSI = ISuspendControlServiceInternal;
+ static const WakeLockInfoField FIELDS[] = {
+ {ISCSI::WAKE_LOCK_INFO_ACTIVE_COUNT, [](WakeLockInfo wl) { return wl.activeCount; }, 1},
+ {ISCSI::WAKE_LOCK_INFO_LAST_CHANGE, [](WakeLockInfo wl) { return wl.lastChange; }, 2},
+ {ISCSI::WAKE_LOCK_INFO_MAX_TIME, [](WakeLockInfo wl) { return wl.maxTime; }, 3},
+ {ISCSI::WAKE_LOCK_INFO_TOTAL_TIME, [](WakeLockInfo wl) { return wl.totalTime; }, 4},
+ {ISCSI::WAKE_LOCK_INFO_ACTIVE_TIME, [](WakeLockInfo wl) { return wl.activeTime; }, 5},
+ {ISCSI::WAKE_LOCK_INFO_EVENT_COUNT, [](WakeLockInfo wl) { return wl.eventCount; }, 6},
+ {ISCSI::WAKE_LOCK_INFO_EXPIRE_COUNT, [](WakeLockInfo wl) { return wl.expireCount; }, 7},
+ {ISCSI::WAKE_LOCK_INFO_PREVENT_SUSPEND_TIME,
+ [](WakeLockInfo wl) { return wl.preventSuspendTime; }, 8},
+ {ISCSI::WAKE_LOCK_INFO_WAKEUP_COUNT, [](WakeLockInfo wl) { return wl.wakeupCount; }, 9},
+ };
+
+ std::string fakeKwlName1 = "fakeKwl1";
+ addKernelWakelock(fakeKwlName1, /* activeCount = */ 1, /* activeTime = */ 5,
+ /* eventCount = */ 6,
+ /* expireCount = */ 7, /* lastChange = */ 2, /* maxTime = */ 3,
+ /* preventSuspendTime = */ 8, /* totalTime = */ 4, /* wakeupCount = */ 9);
+ for (auto field : FIELDS) {
+ std::vector<WakeLockInfo> infos = getWakelockStats(field.bit);
+ WakeLockInfo wli;
+ ASSERT_TRUE(findWakeLockInfoByName(infos, fakeKwlName1, &wli));
+ ASSERT_EQ(field.getter(wli), field.expectedValue)
+ << "Bit mask " << field.bit << " had unexpected value";
+ }
+}
+
} // namespace android
int main(int argc, char** argv) {
diff --git a/suspend/1.0/default/WakeLockEntryList.cpp b/suspend/1.0/default/WakeLockEntryList.cpp
index 5a43501..f726586 100644
--- a/suspend/1.0/default/WakeLockEntryList.cpp
+++ b/suspend/1.0/default/WakeLockEntryList.cpp
@@ -20,6 +20,8 @@
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
+#include <android/system/suspend/internal/ISuspendControlServiceInternal.h>
+#include <suspend_service_flags.h>
#include <iomanip>
@@ -27,12 +29,37 @@
using android::base::ReadFdToString;
using android::base::Readlink;
using android::base::StringPrintf;
+using suspend_service::flags::fast_kernel_wakelock_reporting;
+
+using ISCSI = ::android::system::suspend::internal::ISuspendControlServiceInternal;
namespace android {
namespace system {
namespace suspend {
namespace V1_0 {
+namespace {
+
+struct BitAndFilename {
+ int32_t bit;
+ std::string filename;
+};
+
+const BitAndFilename FIELDS[] = {
+ {-1, "name"},
+ {ISCSI::WAKE_LOCK_INFO_ACTIVE_COUNT, "active_count"},
+ {ISCSI::WAKE_LOCK_INFO_LAST_CHANGE, "last_change_ms"},
+ {ISCSI::WAKE_LOCK_INFO_MAX_TIME, "max_time_ms"},
+ {ISCSI::WAKE_LOCK_INFO_TOTAL_TIME, "total_time_ms"},
+ {ISCSI::WAKE_LOCK_INFO_ACTIVE_TIME, "active_time_ms"},
+ {ISCSI::WAKE_LOCK_INFO_EVENT_COUNT, "event_count"},
+ {ISCSI::WAKE_LOCK_INFO_EXPIRE_COUNT, "expire_count"},
+ {ISCSI::WAKE_LOCK_INFO_PREVENT_SUSPEND_TIME, "prevent_suspend_time_ms"},
+ {ISCSI::WAKE_LOCK_INFO_WAKEUP_COUNT, "wakeup_count"},
+};
+
+} // namespace
+
static std::ostream& operator<<(std::ostream& out, const WakeLockInfo& entry) {
const char* sep = " | ";
const char* notApplicable = "---";
@@ -65,7 +92,7 @@
std::ostream& operator<<(std::ostream& out, const WakeLockEntryList& list) {
std::vector<WakeLockInfo> wlStats;
- list.getWakeLockStats(&wlStats);
+ list.getWakeLockStats(ISCSI::WAKE_LOCK_INFO_ALL_FIELDS, &wlStats);
int width = 194;
const char* sep = " | ";
std::stringstream ss;
@@ -324,20 +351,146 @@
return info;
}
-void WakeLockEntryList::getKernelWakelockStats(std::vector<WakeLockInfo>* aidl_return) const {
+/*
+ * Creates and returns a kernel wakelock entry with data read from mKernelWakelockStatsFd.
+ * Has been micro-optimized to reduce CPU time and wall time.
+ */
+WakeLockInfo WakeLockEntryList::createKernelEntry(ScratchSpace* ss, int wakeLockInfoFieldBitMask,
+ 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;
+
+ for (const auto& field : FIELDS) {
+ const bool isNameField = field.bit == -1;
+ if (!isNameField && (wakeLockInfoFieldBitMask & field.bit) == 0) {
+ continue;
+ }
+
+ ss->statName = kwlId + "/" + field.filename;
+ int statFd = -1;
+
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ // Check if we have a valid cached file descriptor.
+ auto it = mFdCache.find(ss->statName);
+ if (it != mFdCache.end() && it->second >= 0) {
+ auto result = lseek(it->second, 0, SEEK_SET);
+ if (result < 0) {
+ PLOG(ERROR) << "Could not seek to start of FD for " << ss->statName;
+ mFdCache.erase(it);
+ PLOG(ERROR) << "Closed the FD.";
+ } else {
+ statFd = it->second;
+ }
+ }
+
+ if (statFd == -1) {
+ unique_fd tmpFd(TEMP_FAILURE_RETRY(
+ openat(mKernelWakelockStatsFd, ss->statName.c_str(), O_CLOEXEC | O_RDONLY)));
+ if (tmpFd < 0) {
+ PLOG(ERROR) << "Error opening " << ss->statName << " for " << kwlId;
+ continue;
+ }
+ statFd = tmpFd;
+ mFdCache.insert(it, {ss->statName, std::move(tmpFd)});
+ }
+ } // mLock is released here
+
+ ss->valStr.clear();
+ ssize_t n;
+ while ((n = TEMP_FAILURE_RETRY(read(statFd, &ss->readBuff[0], sizeof(ss->readBuff)))) > 0) {
+ ss->valStr.append(ss->readBuff, n);
+ }
+ if (n < 0) {
+ PLOG(ERROR) << "Error reading " << ss->statName;
+ {
+ std::lock_guard<std::mutex> lock(mLock);
+ mFdCache.erase(ss->statName);
+ PLOG(ERROR) << "Closed the FD.";
+ }
+ continue;
+ }
+
+ // Trim newline
+ ss->valStr.erase(std::remove(ss->valStr.begin(), ss->valStr.end(), '\n'), ss->valStr.end());
+
+ if (isNameField) {
+ info.name = ss->valStr;
+ continue;
+ }
+
+ int64_t statVal;
+ if (!ParseInt(ss->valStr, &statVal)) {
+ std::string path;
+ if (Readlink(StringPrintf("/proc/self/fd/%d", statFd), &path)) {
+ LOG(ERROR) << "Unexpected format for wakelock stat value (" << ss->valStr
+ << ") from file: " << path;
+ } else {
+ LOG(ERROR) << "Unexpected format for wakelock stat value (" << ss->valStr << ")";
+ }
+ continue;
+ }
+
+ if (field.filename == "active_count") {
+ info.activeCount = statVal;
+ } else if (field.filename == "active_time_ms") {
+ info.activeTime = statVal;
+ } else if (field.filename == "event_count") {
+ info.eventCount = statVal;
+ } else if (field.filename == "expire_count") {
+ info.expireCount = statVal;
+ } else if (field.filename == "last_change_ms") {
+ info.lastChange = statVal;
+ } else if (field.filename == "max_time_ms") {
+ info.maxTime = statVal;
+ } else if (field.filename == "prevent_suspend_time_ms") {
+ info.preventSuspendTime = statVal;
+ } else if (field.filename == "total_time_ms") {
+ info.totalTime = statVal;
+ } else if (field.filename == "wakeup_count") {
+ info.wakeupCount = statVal;
+ }
+ }
+
+ // Derived stats
+ info.isActive = info.activeTime > 0;
+
+ return info;
+}
+
+void WakeLockEntryList::getKernelWakelockStats(int wakeLockInfoFieldBitMask,
+ 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());
+ ScratchSpace ss;
struct dirent* de;
while ((de = readdir(dp.get()))) {
std::string kwlId(de->d_name);
if ((kwlId == ".") || (kwlId == "..")) {
continue;
}
- WakeLockInfo entry = createKernelEntry(kwlId);
+ WakeLockInfo entry = fast_kernel_wakelock_reporting()
+ ? createKernelEntry(&ss, wakeLockInfoFieldBitMask, kwlId)
+ : createKernelEntry(kwlId);
+
aidl_return->emplace_back(std::move(entry));
}
}
@@ -346,7 +499,7 @@
void WakeLockEntryList::updateOnAcquire(const std::string& name, int pid) {
TimestampType timeNow = getTimeNow();
- std::lock_guard<std::mutex> lock(mStatsLock);
+ std::lock_guard<std::mutex> lock(mLock);
auto key = std::make_pair(name, pid);
auto it = mLookupTable.find(key);
@@ -372,7 +525,7 @@
void WakeLockEntryList::updateOnRelease(const std::string& name, int pid) {
TimestampType timeNow = getTimeNow();
- std::lock_guard<std::mutex> lock(mStatsLock);
+ std::lock_guard<std::mutex> lock(mLock);
auto key = std::make_pair(name, pid);
auto it = mLookupTable.find(key);
@@ -406,7 +559,7 @@
* Updates the native wakelock stats based on the current time.
*/
void WakeLockEntryList::updateNow() {
- std::lock_guard<std::mutex> lock(mStatsLock);
+ std::lock_guard<std::mutex> lock(mLock);
TimestampType timeNow = getTimeNow();
@@ -421,15 +574,16 @@
}
}
-void WakeLockEntryList::getWakeLockStats(std::vector<WakeLockInfo>* aidl_return) const {
+void WakeLockEntryList::getWakeLockStats(int wakeLockInfoFieldBitMask,
+ std::vector<WakeLockInfo>* aidl_return) const {
// Under no circumstances should the lock be held while getting kernel wakelock stats
{
- std::lock_guard<std::mutex> lock(mStatsLock);
+ std::lock_guard<std::mutex> lock(mLock);
for (const WakeLockInfo& entry : mStats) {
aidl_return->emplace_back(entry);
}
}
- getKernelWakelockStats(aidl_return);
+ getKernelWakelockStats(wakeLockInfoFieldBitMask, aidl_return);
}
} // namespace V1_0
diff --git a/suspend/1.0/default/WakeLockEntryList.h b/suspend/1.0/default/WakeLockEntryList.h
index 1ebc411..d81727a 100644
--- a/suspend/1.0/default/WakeLockEntryList.h
+++ b/suspend/1.0/default/WakeLockEntryList.h
@@ -49,16 +49,32 @@
// 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;
+ void getWakeLockStats(int wakeLockInfoFieldBitMask,
+ 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);
+ void evictIfFull() REQUIRES(mLock);
+ void insertEntry(WakeLockInfo entry) REQUIRES(mLock);
+ void deleteEntry(std::list<WakeLockInfo>::iterator entry) REQUIRES(mLock);
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;
+
+ // Used by createKernelEntry to reduce heap churn on successive calls.
+ struct ScratchSpace {
+ static constexpr const int BUFF_SIZE = 1024;
+ char readBuff[BUFF_SIZE];
+ std::string statName, valStr;
+ ScratchSpace() {
+ valStr.reserve(BUFF_SIZE);
+ statName.reserve(BUFF_SIZE);
+ }
+ };
+ WakeLockInfo createKernelEntry(ScratchSpace* ss, int wakeLockInfoFieldBitMask,
+ const std::string& name) const;
+
+ void getKernelWakelockStats(int wakeLockInfoFieldBitMask,
+ std::vector<WakeLockInfo>* aidl_return) const;
// Hash for WakeLockEntry key (pair<std::string, int>)
struct LockHash {
@@ -67,17 +83,18 @@
}
};
+ mutable std::mutex mLock;
+
size_t mCapacity;
unique_fd mKernelWakelockStatsFd;
-
- mutable std::mutex mStatsLock;
+ mutable std::unordered_map<std::string, unique_fd> mFdCache GUARDED_BY(mLock);
// 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::list<WakeLockInfo> mStats GUARDED_BY(mLock);
std::unordered_map<std::pair<std::string, int>, std::list<WakeLockInfo>::iterator, LockHash>
- mLookupTable GUARDED_BY(mStatsLock);
+ mLookupTable GUARDED_BY(mLock);
};
} // namespace V1_0
diff --git a/suspend/1.0/default/flags.aconfig b/suspend/1.0/default/flags.aconfig
new file mode 100644
index 0000000..c943950
--- /dev/null
+++ b/suspend/1.0/default/flags.aconfig
@@ -0,0 +1,9 @@
+package: "suspend_service.flags"
+container: "system"
+
+flag {
+ name: "fast_kernel_wakelock_reporting"
+ namespace: "android_kernel"
+ description: "Controls using new codepath to speed up polling of /sys/class/wakeup for kernel wakelocks."
+ bug: "364368163"
+}
\ No newline at end of file
diff --git a/suspend/aidl/android/system/suspend/internal/ISuspendControlServiceInternal.aidl b/suspend/aidl/android/system/suspend/internal/ISuspendControlServiceInternal.aidl
index 8e0a9a2..065d486 100644
--- a/suspend/aidl/android/system/suspend/internal/ISuspendControlServiceInternal.aidl
+++ b/suspend/aidl/android/system/suspend/internal/ISuspendControlServiceInternal.aidl
@@ -46,6 +46,12 @@
WakeLockInfo[] getWakeLockStats();
/**
+ * Returns a list of wake lock stats. Fields not selected with the
+ * bit mask are in an undefined state (see WAKE_LOCK_INFO_* below).
+ */
+ WakeLockInfo[] getWakeLockStatsFiltered(int wakeLockInfoFieldBitMask);
+
+ /**
* Returns a list of wakeup stats.
*/
WakeupInfo[] getWakeupStats();
@@ -54,4 +60,27 @@
* Returns stats related to suspend.
*/
SuspendInfo getSuspendStats();
+
+ /**
+ * Used to select fields from WakeLockInfo that getWakeLockStats should return.
+ * This is in addition to the name of the wake lock, which is always returned.
+ */
+ const int WAKE_LOCK_INFO_ACTIVE_COUNT = 1 << 0;
+ const int WAKE_LOCK_INFO_LAST_CHANGE = 1 << 1;
+ const int WAKE_LOCK_INFO_MAX_TIME = 1 << 2;
+ const int WAKE_LOCK_INFO_TOTAL_TIME = 1 << 3;
+ const int WAKE_LOCK_INFO_IS_ACTIVE = 1 << 4;
+ const int WAKE_LOCK_INFO_ACTIVE_TIME = 1 << 5;
+ const int WAKE_LOCK_INFO_IS_KERNEL_WAKELOCK = 1 << 6;
+
+ // Specific to Native wake locks.
+ const int WAKE_LOCK_INFO_PID = 1 << 7;
+
+ // Specific to Kernel wake locks.
+ const int WAKE_LOCK_INFO_EVENT_COUNT = 1 << 8;
+ const int WAKE_LOCK_INFO_EXPIRE_COUNT = 1 << 9;
+ const int WAKE_LOCK_INFO_PREVENT_SUSPEND_TIME = 1 << 10;
+ const int WAKE_LOCK_INFO_WAKEUP_COUNT = 1 << 11;
+
+ const int WAKE_LOCK_INFO_ALL_FIELDS = (1 << 12) - 1;
}