1 /*
2 * Copyright 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 #include <SuspendProperties.sysprop.h>
18 #include <android-base/logging.h>
19 #include <android/binder_manager.h>
20 #include <android/hidl/manager/1.2/IServiceManager.h>
21 #include <binder/IPCThreadState.h>
22 #include <binder/IServiceManager.h>
23 #include <binder/ProcessState.h>
24 #include <cutils/native_handle.h>
25 #include <fcntl.h>
26 #include <hidl/HidlTransportSupport.h>
27 #include <hwbinder/ProcessState.h>
28 #include <sys/socket.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32
33 #include "SuspendControlService.h"
34 #include "SystemSuspend.h"
35 #include "SystemSuspendAidl.h"
36 #include "SystemSuspendHidl.h"
37
38 using aidl::android::system::suspend::SystemSuspendAidl;
39 using android::sp;
40 using android::status_t;
41 using android::String16;
42 using android::base::Socketpair;
43 using android::base::unique_fd;
44 using android::hardware::configureRpcThreadpool;
45 using android::hardware::joinRpcThreadpool;
46 using android::system::suspend::V1_0::ISystemSuspend;
47 using android::system::suspend::V1_0::SleepTimeConfig;
48 using android::system::suspend::V1_0::SuspendControlService;
49 using android::system::suspend::V1_0::SuspendControlServiceInternal;
50 using android::system::suspend::V1_0::SystemSuspend;
51 using android::system::suspend::V1_0::SystemSuspendHidl;
52 using namespace std::chrono_literals;
53 using namespace ::android::sysprop;
54
55 static constexpr size_t kStatsCapacity = 1000;
56 static constexpr char kSysClassWakeup[] = "/sys/class/wakeup";
57 static constexpr char kSysPowerSuspendStats[] = "/sys/power/suspend_stats";
58 static constexpr char kSysPowerWakeupCount[] = "/sys/power/wakeup_count";
59 static constexpr char kSysPowerState[] = "/sys/power/state";
60 // TODO(b/120445600): Use upstream mechanism for wakeup reasons once available
61 static constexpr char kSysKernelWakeupReasons[] = "/sys/kernel/wakeup_reasons/last_resume_reason";
62 static constexpr char kSysKernelSuspendTime[] = "/sys/kernel/wakeup_reasons/last_suspend_time";
63
64 static constexpr uint32_t kDefaultMaxSleepTimeMillis = 60000;
65 static constexpr uint32_t kDefaultBaseSleepTimeMillis = 100;
66 static constexpr double kDefaultSleepTimeScaleFactor = 2.0;
67 static constexpr uint32_t kDefaultBackoffThresholdCount = 0;
68 static constexpr uint32_t kDefaultShortSuspendThresholdMillis = 0;
69 static constexpr bool kDefaultFailedSuspendBackoffEnabled = true;
70 static constexpr bool kDefaultShortSuspendBackoffEnabled = false;
71
main()72 int main() {
73 unique_fd wakeupCountFd{TEMP_FAILURE_RETRY(open(kSysPowerWakeupCount, O_CLOEXEC | O_RDWR))};
74 if (wakeupCountFd < 0) {
75 PLOG(ERROR) << "error opening " << kSysPowerWakeupCount;
76 }
77 unique_fd stateFd{TEMP_FAILURE_RETRY(open(kSysPowerState, O_CLOEXEC | O_RDWR))};
78 if (stateFd < 0) {
79 PLOG(ERROR) << "error opening " << kSysPowerState;
80 }
81 unique_fd kernelWakelockStatsFd{
82 TEMP_FAILURE_RETRY(open(kSysClassWakeup, O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
83 if (kernelWakelockStatsFd < 0) {
84 PLOG(ERROR) << "SystemSuspend: Error opening " << kSysClassWakeup;
85 }
86 unique_fd suspendStatsFd{
87 TEMP_FAILURE_RETRY(open(kSysPowerSuspendStats, O_DIRECTORY | O_CLOEXEC | O_RDONLY))};
88 if (suspendStatsFd < 0) {
89 PLOG(ERROR) << "SystemSuspend: Error opening " << kSysPowerSuspendStats;
90 }
91 unique_fd wakeupReasonsFd{
92 TEMP_FAILURE_RETRY(open(kSysKernelWakeupReasons, O_CLOEXEC | O_RDONLY))};
93 if (wakeupReasonsFd < 0) {
94 PLOG(ERROR) << "SystemSuspend: Error opening " << kSysKernelWakeupReasons;
95 }
96 unique_fd suspendTimeFd{TEMP_FAILURE_RETRY(open(kSysKernelSuspendTime, O_CLOEXEC | O_RDONLY))};
97 if (suspendTimeFd < 0) {
98 PLOG(ERROR) << "SystemSuspend: Error opening " << kSysKernelSuspendTime;
99 }
100
101 // If either /sys/power/wakeup_count or /sys/power/state fail to open, we construct
102 // SystemSuspend with blocking fds. This way this process will keep running, handle wake lock
103 // requests, collect stats, but won't suspend the device. We want this behavior on devices
104 // (hosts) where system suspend should not be handles by Android platform e.g. ARC++, Android
105 // virtual devices.
106 if (wakeupCountFd < 0 || stateFd < 0) {
107 // This will block all reads/writes to these fds from the suspend thread.
108 Socketpair(SOCK_STREAM, &wakeupCountFd, &stateFd);
109 }
110
111 SleepTimeConfig sleepTimeConfig = {
112 .baseSleepTime = std::chrono::milliseconds(
113 SuspendProperties::base_sleep_time_millis().value_or(kDefaultBaseSleepTimeMillis)),
114 .maxSleepTime = std::chrono::milliseconds(
115 SuspendProperties::max_sleep_time_millis().value_or(kDefaultMaxSleepTimeMillis)),
116 .sleepTimeScaleFactor =
117 SuspendProperties::sleep_time_scale_factor().value_or(kDefaultSleepTimeScaleFactor),
118 .backoffThreshold =
119 SuspendProperties::backoff_threshold_count().value_or(kDefaultBackoffThresholdCount),
120 .shortSuspendThreshold =
121 std::chrono::milliseconds(SuspendProperties::short_suspend_threshold_millis().value_or(
122 kDefaultShortSuspendThresholdMillis)),
123 .failedSuspendBackoffEnabled = SuspendProperties::failed_suspend_backoff_enabled().value_or(
124 kDefaultFailedSuspendBackoffEnabled),
125 .shortSuspendBackoffEnabled = SuspendProperties::short_suspend_backoff_enabled().value_or(
126 kDefaultShortSuspendBackoffEnabled),
127 };
128
129 // Create non-HW binder threadpool for SuspendControlService.
130 android::ProcessState::self()->startThreadPool();
131
132 sp<SuspendControlService> suspendControl = new SuspendControlService();
133 auto controlStatus =
134 android::defaultServiceManager()->addService(String16("suspend_control"), suspendControl);
135 if (controlStatus != android::OK) {
136 LOG(FATAL) << "Unable to register suspend_control service: " << controlStatus;
137 }
138
139 sp<SuspendControlServiceInternal> suspendControlInternal = new SuspendControlServiceInternal();
140 controlStatus = android::defaultServiceManager()->addService(
141 String16("suspend_control_internal"), suspendControlInternal);
142 if (controlStatus != android::OK) {
143 LOG(FATAL) << "Unable to register suspend_control_internal service: " << controlStatus;
144 }
145
146 sp<SystemSuspend> suspend = new SystemSuspend(
147 std::move(wakeupCountFd), std::move(stateFd), std::move(suspendStatsFd), kStatsCapacity,
148 std::move(kernelWakelockStatsFd), std::move(wakeupReasonsFd), std::move(suspendTimeFd),
149 sleepTimeConfig, suspendControl, suspendControlInternal, true /* mUseSuspendCounter*/);
150
151 std::shared_ptr<SystemSuspendAidl> suspendAidl =
152 ndk::SharedRefBase::make<SystemSuspendAidl>(suspend.get());
153 const std::string suspendAidlInstance =
154 std::string() + SystemSuspendAidl::descriptor + "/default";
155 auto aidlStatus =
156 AServiceManager_addService(suspendAidl->asBinder().get(), suspendAidlInstance.c_str());
157 CHECK_EQ(aidlStatus, STATUS_OK)
158 << "Unable to register system-suspend AIDL service: " << aidlStatus;
159
160 if (android::hidl::manager::V1_2::IServiceManager::Transport::HWBINDER ==
161 android::hardware::defaultServiceManager1_2()->getTransport(SystemSuspendHidl::descriptor,
162 "default")) {
163 configureRpcThreadpool(1, false /* callerWillJoin */);
164 sp<SystemSuspendHidl> suspendHidl = new SystemSuspendHidl(suspend.get());
165 status_t hidlStatus = suspendHidl->registerAsService();
166 CHECK_EQ(hidlStatus, android::OK)
167 << "Unable to register system-suspend HIDL hal" << hidlStatus;
168 }
169 // join the libbinder threadpool
170 android::IPCThreadState::self()->joinThreadPool(true /* isMain */);
171 std::abort(); /* unreachable */
172 }
173