diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2020-04-28 20:26:52 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2020-04-28 20:26:52 +0000 |
commit | c0a29a703e72ece2c1ab87c3e1ee1587476da040 (patch) | |
tree | 76082fe06c0f187f38e2689e34556459018579f6 | |
parent | 265fe2e6fa12e521f41248be088595758bf4b78b (diff) | |
parent | 2987e6b9e5e5ea02124c67e880aaeb942a3e4c17 (diff) | |
download | interfaces-android12-mainline-tzdata-release.tar.gz |
Snap for 6439596 from 2987e6b9e5e5ea02124c67e880aaeb942a3e4c17 to qt-aml-tzdata-releaseq_tzdata_aml_297100400q_tzdata_aml_297100300q_tzdata_aml_297100000q_tzdata_aml_296200000q_tzdata_aml_295600118q_tzdata_aml_295600110q_tzdata_aml_295500002q_tzdata_aml_295500001q_tzdata_aml_294400310android-mainline-12.0.0_r54android-mainline-12.0.0_r111android-mainline-10.0.0_r13android-mainline-10.0.0_r12android-mainline-10.0.0_r11q_tzdata_aml_297100000android12-mainline-tzdata-releaseandroid10-mainline-tzdata-releaseandroid10-android13-mainline-tzdata-release
Change-Id: If409c0581ca1761d11a8d92aa7aacc25ea5d65c5
23 files changed, 273 insertions, 1298 deletions
@@ -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) { |