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 <hidl/HidlTransportSupport.h>
24 
25 #include <condition_variable>
26 #include <mutex>
27 #include <string>
28 
29 #include "SuspendControlService.h"
30 #include "WakeLockEntryList.h"
31 
32 namespace android {
33 namespace system {
34 namespace suspend {
35 namespace V1_0 {
36 
37 using ::android::base::Result;
38 using ::android::base::unique_fd;
39 using ::android::hardware::hidl_string;
40 using ::android::hardware::interfacesEqual;
41 using ::android::hardware::Return;
42 
43 using namespace std::chrono_literals;
44 
45 class SystemSuspend;
46 
47 struct SuspendStats {
48     int success = 0;
49     int fail = 0;
50     int failedFreeze = 0;
51     int failedPrepare = 0;
52     int failedSuspend = 0;
53     int failedSuspendLate = 0;
54     int failedSuspendNoirq = 0;
55     int failedResume = 0;
56     int failedResumeEarly = 0;
57     int failedResumeNoirq = 0;
58     std::string lastFailedDev;
59     int lastFailedErrno = 0;
60     std::string lastFailedStep;
61 };
62 
63 std::string readFd(int fd);
64 
65 class WakeLock : public IWakeLock {
66    public:
67     WakeLock(SystemSuspend* systemSuspend, const std::string& name, int pid);
68     ~WakeLock();
69 
70     Return<void> release();
71 
72    private:
73     inline void releaseOnce();
74     std::once_flag mReleased;
75 
76     SystemSuspend* mSystemSuspend;
77     std::string mName;
78     int mPid;
79 };
80 
81 class SystemSuspend : public ISystemSuspend {
82    public:
83     SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, unique_fd suspendStatsFd,
84                   size_t maxNativeStatsEntries, unique_fd kernelWakelockStatsFd,
85                   std::chrono::milliseconds baseSleepTime,
86                   const sp<SuspendControlService>& controlService, bool useSuspendCounter = true);
87     Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
88     void incSuspendCounter(const std::string& name);
89     void decSuspendCounter(const std::string& name);
90     bool enableAutosuspend();
91     bool forceSuspend();
92 
93     const WakeLockEntryList& getStatsList() const;
94     void updateWakeLockStatOnRelease(const std::string& name, int pid, TimestampType timeNow);
95     void updateStatsNow();
96     Result<SuspendStats> getSuspendStats();
97 
98    private:
99     void initAutosuspend();
100 
101     std::mutex mCounterLock;
102     std::condition_variable mCounterCondVar;
103     uint32_t mSuspendCounter;
104     unique_fd mWakeupCountFd;
105     unique_fd mStateFd;
106 
107     unique_fd mSuspendStatsFd;
108 
109     // Amount of sleep time between consecutive iterations of the suspend loop.
110     std::chrono::milliseconds mBaseSleepTime;
111     std::chrono::milliseconds mSleepTime;
112     // Updates sleep time depending on the result of suspend attempt.
113     void updateSleepTime(bool success);
114 
115     sp<SuspendControlService> mControlService;
116 
117     WakeLockEntryList mStatsList;
118 
119     // If true, use mSuspendCounter to keep track of native wake locks. Otherwise, rely on
120     // /sys/power/wake_lock interface to block suspend.
121     // TODO(b/128923994): remove dependency on /sys/power/wake_lock interface.
122     bool mUseSuspendCounter;
123     unique_fd mWakeLockFd;
124     unique_fd mWakeUnlockFd;
125 };
126 
127 }  // namespace V1_0
128 }  // namespace suspend
129 }  // namespace system
130 }  // namespace android
131 
132 #endif  // ANDROID_SYSTEM_SYSTEM_SUSPEND_V1_0_H
133