1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H
18 #define ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H
19 
20 #include <android-base/unique_fd.h>
21 #include <android/system/suspend/internal/WakeLockInfo.h>
22 #include <utils/Mutex.h>
23 
24 #include <list>
25 #include <mutex>
26 #include <unordered_map>
27 #include <utility>
28 #include <vector>
29 
30 using ::android::system::suspend::internal::WakeLockInfo;
31 
32 namespace android {
33 namespace system {
34 namespace suspend {
35 namespace V1_0 {
36 
37 using android::base::unique_fd;
38 using TimestampType = int64_t;
39 
40 /*
41  * WakeLockEntryList to collect wake lock stats.
42  * This class is thread safe.
43  */
44 class WakeLockEntryList {
45    public:
46     WakeLockEntryList(size_t capacity, unique_fd kernelWakelockStatsFd);
47     void updateOnAcquire(const std::string& name, int pid);
48     void updateOnRelease(const std::string& name, int pid);
49     // updateNow() should be called before getWakeLockStats() to ensure stats are
50     // updated wrt the current time.
51     void updateNow();
52     void getWakeLockStats(int wakeLockInfoFieldBitMask,
53                           std::vector<WakeLockInfo>* aidl_return) const;
54     friend std::ostream& operator<<(std::ostream& out, const WakeLockEntryList& list);
55 
56    private:
57     void evictIfFull() REQUIRES(mLock);
58     void insertEntry(WakeLockInfo entry) REQUIRES(mLock);
59     void deleteEntry(std::list<WakeLockInfo>::iterator entry) REQUIRES(mLock);
60     WakeLockInfo createNativeEntry(const std::string& name, int pid, TimestampType timeNow) const;
61     WakeLockInfo createKernelEntry(const std::string& name) const;
62 
63     // Used by createKernelEntry to reduce heap churn on successive calls.
64     struct ScratchSpace {
65         static constexpr const int BUFF_SIZE = 1024;
66         char readBuff[BUFF_SIZE];
67         std::string statName, valStr;
ScratchSpaceScratchSpace68         ScratchSpace() {
69             valStr.reserve(BUFF_SIZE);
70             statName.reserve(BUFF_SIZE);
71         }
72     };
73     WakeLockInfo createKernelEntry(ScratchSpace* ss, int wakeLockInfoFieldBitMask,
74                                    const std::string& name) const;
75 
76     void getKernelWakelockStats(int wakeLockInfoFieldBitMask,
77                                 std::vector<WakeLockInfo>* aidl_return) const;
78 
79     // Hash for WakeLockEntry key (pair<std::string, int>)
80     struct LockHash {
operatorLockHash81         std::size_t operator()(const std::pair<std::string, int>& key) const {
82             return std::hash<std::string>()(key.first) ^ std::hash<int>()(key.second);
83         }
84     };
85 
86     mutable std::mutex mLock;
87 
88     size_t mCapacity;
89     unique_fd mKernelWakelockStatsFd;
90     mutable std::unordered_map<std::string, unique_fd> mFdCache GUARDED_BY(mLock);
91 
92     // std::list and std::unordered map are used to support both inserting a stat
93     // and eviction of the LRU stat in O(1) time. The LRU stat is maintained at
94     // the back of the list.
95     std::list<WakeLockInfo> mStats GUARDED_BY(mLock);
96     std::unordered_map<std::pair<std::string, int>, std::list<WakeLockInfo>::iterator, LockHash>
97         mLookupTable GUARDED_BY(mLock);
98 };
99 
100 }  // namespace V1_0
101 }  // namespace suspend
102 }  // namespace system
103 }  // namespace android
104 
105 #endif  // ANDROID_SYSTEM_SUSPEND_WAKE_LOCK_ENTRY_LIST_H
106