1 /*
2  * Copyright 2018 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_SYSTEM_SUSPEND_V1_0_H
18 #define ANDROID_SYSTEM_SYSTEM_SUSPEND_V1_0_H
19 
20 #include <android-base/result.h>
21 #include <android-base/unique_fd.h>
22 #include <android/system/suspend/1.0/ISystemSuspend.h>
23 #include <android/system/suspend/internal/SuspendInfo.h>
24 #include <hidl/HidlTransportSupport.h>
25 
26 #include <atomic>
27 #include <condition_variable>
28 #include <mutex>
29 #include <string>
30 
31 #include "SuspendControlService.h"
32 #include "WakeLockEntryList.h"
33 #include "WakeupList.h"
34 
35 namespace android {
36 namespace system {
37 namespace suspend {
38 namespace V1_0 {
39 
40 using ::android::base::Result;
41 using ::android::base::unique_fd;
42 using ::android::hardware::hidl_string;
43 using ::android::hardware::interfacesEqual;
44 using ::android::hardware::Return;
45 using ::android::system::suspend::internal::SuspendInfo;
46 
47 using namespace std::chrono_literals;
48 
49 class SystemSuspend;
50 
51 struct SuspendStats {
52     int success = 0;
53     int fail = 0;
54     int failedFreeze = 0;
55     int failedPrepare = 0;
56     int failedSuspend = 0;
57     int failedSuspendLate = 0;
58     int failedSuspendNoirq = 0;
59     int failedResume = 0;
60     int failedResumeEarly = 0;
61     int failedResumeNoirq = 0;
62     std::string lastFailedDev;
63     int lastFailedErrno = 0;
64     std::string lastFailedStep;
65 };
66 
67 struct SleepTimeConfig {
68     std::chrono::milliseconds baseSleepTime;
69     std::chrono::milliseconds maxSleepTime;
70     double sleepTimeScaleFactor;
71     uint32_t backoffThreshold;
72     std::chrono::milliseconds shortSuspendThreshold;
73     bool failedSuspendBackoffEnabled;
74     bool shortSuspendBackoffEnabled;
75 };
76 
77 std::string readFd(int fd);
78 
79 class WakeLock : public IWakeLock {
80    public:
81     WakeLock(SystemSuspend* systemSuspend, const std::string& name, int pid);
82     ~WakeLock();
83 
84     Return<void> release();
85 
86    private:
87     inline void releaseOnce();
88     std::once_flag mReleased;
89 
90     SystemSuspend* mSystemSuspend;
91     std::string mName;
92     int mPid;
93 };
94 
95 class SystemSuspend : public ISystemSuspend {
96    public:
97     SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, unique_fd suspendStatsFd,
98                   size_t maxStatsEntries, unique_fd kernelWakelockStatsFd,
99                   unique_fd wakeupReasonsFd, unique_fd suspendTimeFd,
100                   const SleepTimeConfig& sleepTimeConfig,
101                   const sp<SuspendControlService>& controlService,
102                   const sp<SuspendControlServiceInternal>& controlServiceInternal,
103                   bool useSuspendCounter = true);
104     Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
105     void incSuspendCounter(const std::string& name);
106     void decSuspendCounter(const std::string& name);
107     bool enableAutosuspend();
108     bool forceSuspend();
109 
110     const WakeupList& getWakeupList() const;
111     const WakeLockEntryList& getStatsList() const;
112     void updateWakeLockStatOnRelease(const std::string& name, int pid, TimestampType timeNow);
113     void updateStatsNow();
114     Result<SuspendStats> getSuspendStats();
115     void getSuspendInfo(SuspendInfo* info);
116     std::chrono::milliseconds getSleepTime() const;
117 
118    private:
119     void initAutosuspend();
120 
121     std::mutex mCounterLock;
122     std::condition_variable mCounterCondVar;
123     uint32_t mSuspendCounter;
124     unique_fd mWakeupCountFd;
125     unique_fd mStateFd;
126 
127     unique_fd mSuspendStatsFd;
128     unique_fd mSuspendTimeFd;
129 
130     std::mutex mSuspendInfoLock;
131     SuspendInfo mSuspendInfo;
132 
133     const SleepTimeConfig kSleepTimeConfig;
134 
135     // Amount of thread sleep time between consecutive iterations of the suspend loop
136     std::chrono::milliseconds mSleepTime;
137     int32_t mNumConsecutiveBadSuspends;
138 
139     // Updates thread sleep time and suspend stats depending on the result of suspend attempt
140     void updateSleepTime(bool success, const struct SuspendTime& suspendTime);
141 
142     sp<SuspendControlService> mControlService;
143     sp<SuspendControlServiceInternal> mControlServiceInternal;
144 
145     WakeLockEntryList mStatsList;
146     WakeupList mWakeupList;
147 
148     // If true, use mSuspendCounter to keep track of native wake locks. Otherwise, rely on
149     // /sys/power/wake_lock interface to block suspend.
150     // TODO(b/128923994): remove dependency on /sys/power/wake_lock interface.
151     bool mUseSuspendCounter;
152     unique_fd mWakeLockFd;
153     unique_fd mWakeUnlockFd;
154     unique_fd mWakeupReasonsFd;
155 
156     std::atomic_flag mAutosuspendEnabled = ATOMIC_FLAG_INIT;
157 };
158 
159 }  // namespace V1_0
160 }  // namespace suspend
161 }  // namespace system
162 }  // namespace android
163 
164 #endif  // ANDROID_SYSTEM_SYSTEM_SUSPEND_V1_0_H
165