/* * 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 #include #include #include #include #include #include #include using ::android::system::suspend::internal::WakeLockInfo; namespace android { namespace system { namespace suspend { namespace V1_0 { using android::base::unique_fd; using TimestampType = int64_t; /* * 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); void updateOnRelease(const std::string& name, int pid); // updateNow() should be called before getWakeLockStats() to ensure stats are // updated wrt the current time. void updateNow(); void getWakeLockStats(int wakeLockInfoFieldBitMask, std::vector* aidl_return) const; friend std::ostream& operator<<(std::ostream& out, const WakeLockEntryList& list); private: void evictIfFull() REQUIRES(mLock); void insertEntry(WakeLockInfo entry) REQUIRES(mLock); void deleteEntry(std::list::iterator entry) REQUIRES(mLock); WakeLockInfo createNativeEntry(const std::string& name, int pid, TimestampType timeNow) const; WakeLockInfo createKernelEntry(const std::string& name) 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* aidl_return) const; // Hash for WakeLockEntry key (pair) struct LockHash { std::size_t operator()(const std::pair& key) const { return std::hash()(key.first) ^ std::hash()(key.second); } }; mutable std::mutex mLock; size_t mCapacity; unique_fd mKernelWakelockStatsFd; mutable std::unordered_map 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 mStats GUARDED_BY(mLock); std::unordered_map, std::list::iterator, LockHash> mLookupTable GUARDED_BY(mLock); }; } // namespace V1_0 } // namespace suspend } // namespace system } // namespace android #endif // ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H