1 /*
2  * Copyright (c) 2021, 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 #define LOG_TAG "carpowerpolicyd"
18 
19 #include "SilentModeHandler.h"
20 
21 #include "CarPowerPolicyServer.h"
22 
23 #include <android-base/file.h>
24 #include <android-base/properties.h>
25 #include <android-base/stringprintf.h>
26 #include <android-base/strings.h>
27 
28 #include <sys/epoll.h>
29 #include <sys/stat.h>
30 #include <unistd.h>
31 
32 #include <filesystem>
33 
34 namespace android {
35 namespace frameworks {
36 namespace automotive {
37 namespace powerpolicy {
38 
39 using ::android::Mutex;
40 using ::android::automotive::SysfsMonitor;
41 using ::android::base::Error;
42 using ::android::base::GetProperty;
43 using ::android::base::ReadFileToString;
44 using ::android::base::Result;
45 using ::android::base::SetProperty;
46 using ::android::base::StringPrintf;
47 using ::android::base::Trim;
48 using ::android::base::unique_fd;
49 using ::android::base::WriteStringToFd;
50 using ::ndk::ScopedAStatus;
51 
52 namespace {
53 
54 constexpr const char kPropertySystemBootReason[] = "sys.boot.reason";
55 constexpr const char kHwStateFilename[] = "pm_silentmode_hw_state";
56 constexpr const char kKernelStateFilename[] = "pm_silentmode_kernel_state";
57 // To prevent boot animation from being started.
58 constexpr const char kPropertyNoBootAnimation[] = "debug.sf.nobootanimation";
59 // To stop boot animation while it is being played.
60 constexpr const char kPropertyBootAnimationExit[] = "service.bootanim.exit";
61 constexpr const char* kSysfsDirForSilentMode[] = {"/sys/kernel/silent_boot", "/sys/power"};
62 // Silent Mode types. Must be identical to definitions in SilentModeHandler.java.
63 constexpr const char kSilentModeStringForcedSilent[] = "forced-silent";
64 constexpr const char kSilentModeStringForcedNonSilent[] = "forced-non-silent";
65 constexpr const char kSilentModeStringNonForced[] = "non-forced-silent-mode";
66 constexpr int32_t kSilentModeTypeForcedSilent = 1;
67 constexpr int32_t kSilentModeTypeForcedNonSilent = 2;
68 constexpr int32_t kSilentModeTypeNonForced = 3;
69 
70 const std::unordered_map<std::string, int32_t> kSilentModeToType =
71         {{kSilentModeStringForcedSilent, kSilentModeTypeForcedSilent},
72          {kSilentModeStringForcedNonSilent, kSilentModeTypeForcedNonSilent},
73          {kSilentModeStringNonForced, kSilentModeTypeNonForced}};
74 
fileExists(const char * filename)75 bool fileExists(const char* filename) {
76     struct stat buffer;
77     return stat(filename, &buffer) == 0;
78 }
79 
80 // We search for the folder where sysfs files for Silent Mode are located in the following order:
81 //   1. /sys/kernel/silent_boot
82 //   2. /sys/power (only for backward compatibility)
searchForSysfsDir()83 std::string searchForSysfsDir() {
84     std::error_code ec;
85     for (const char* dir : kSysfsDirForSilentMode) {
86         if (std::filesystem::is_directory(dir, ec)) {
87             return std::string(dir) + "/";
88         }
89     }
90     return std::string(kSysfsDirForSilentMode[0]) + "/";
91 }
92 
93 }  // namespace
94 
SilentModeHandler(ISilentModeChangeHandler * handler)95 SilentModeHandler::SilentModeHandler(ISilentModeChangeHandler* handler) :
96       mSilentModeByHwState(false),
97       mSilentModeChangeHandler(handler),
98       mSysfsMonitor(sp<SysfsMonitor>::make()) {
99     mBootReason = GetProperty(kPropertySystemBootReason, "");
100 }
101 
init()102 void SilentModeHandler::init() {
103     std::string sysfsDir = searchForSysfsDir();
104     mSilentModeHwStateFilename = sysfsDir + kHwStateFilename;
105     mKernelSilentModeFilename = sysfsDir + kKernelStateFilename;
106     bool forcedMode;
107     {
108         Mutex::Autolock lock(mMutex);
109         mForcedMode = false;
110         if (mBootReason == kBootReasonForcedSilent) {
111             mForcedMode = true;
112             mSilentModeByHwState = true;
113         } else if (mBootReason == kBootReasonForcedNonSilent) {
114             mForcedMode = true;
115             mSilentModeByHwState = false;
116         }
117         forcedMode = mForcedMode;
118     }
119     if (forcedMode) {
120         handleSilentModeChange(mSilentModeByHwState);
121         mSilentModeChangeHandler->notifySilentModeChange(mSilentModeByHwState);
122         ALOGI("Now in forced mode: monitoring %s is disabled", mSilentModeHwStateFilename.c_str());
123     } else {
124         startMonitoringSilentModeHwState();
125     }
126 }
127 
release()128 void SilentModeHandler::release() {
129     stopMonitoringSilentModeHwState();
130 }
131 
isSilentMode()132 bool SilentModeHandler::isSilentMode() {
133     Mutex::Autolock lock(mMutex);
134     return mSilentModeByHwState;
135 }
136 
stopMonitoringSilentModeHwState()137 void SilentModeHandler::stopMonitoringSilentModeHwState() {
138     if (mIsMonitoring.exchange(false)) {
139         if (auto ret = mSysfsMonitor->unregisterFd(mFdSilentModeHwState.get()); !ret.ok()) {
140             ALOGW("Unregistering %s from SysfsMonitor failed", mSilentModeHwStateFilename.c_str());
141         }
142     }
143     mFdSilentModeHwState.reset();
144     mSysfsMonitor->release();
145 }
146 
setSilentMode(const std::string & silentMode)147 ScopedAStatus SilentModeHandler::setSilentMode(const std::string& silentMode) {
148     if (kSilentModeToType.count(silentMode) == 0) {
149         return ScopedAStatus::
150                 fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
151                                              StringPrintf("Unsupported Silent Mode(%s)",
152                                                           silentMode.c_str())
153                                                      .c_str());
154     }
155     int32_t silentModeType = kSilentModeToType.at(silentMode);
156     switch (silentModeType) {
157         case kSilentModeTypeForcedSilent:
158             switchToForcedMode(true);
159             break;
160         case kSilentModeTypeForcedNonSilent:
161             switchToForcedMode(false);
162             break;
163         case kSilentModeTypeNonForced:
164             switchToNonForcedMode();
165             break;
166     }
167     return ScopedAStatus::ok();
168 }
169 
dump(int fd,const Vector<String16> &)170 Result<void> SilentModeHandler::dump(int fd, const Vector<String16>& /*args*/) {
171     const char* indent = "  ";
172     WriteStringToFd(StringPrintf("%sHW state filename: %s\n", indent,
173                                  mSilentModeHwStateFilename.c_str()),
174                     fd);
175     WriteStringToFd(StringPrintf("%sKernel state filename: %s\n", indent,
176                                  mKernelSilentModeFilename.c_str()),
177                     fd);
178     WriteStringToFd(StringPrintf("%sMonitoring HW state: %s\n", indent,
179                                  mIsMonitoring ? "true" : "false"),
180                     fd);
181     WriteStringToFd(StringPrintf("%sForced silent mode: %s\n", indent,
182                                  mForcedMode ? "true" : "false"),
183                     fd);
184     if (mIsMonitoring) {
185         Mutex::Autolock lock(mMutex);
186         WriteStringToFd(StringPrintf("%sSilent mode by HW state: %s\n", indent,
187                                      mSilentModeByHwState ? "silent" : "non-silent"),
188                         fd);
189     }
190     return {};
191 }
192 
startMonitoringSilentModeHwState()193 void SilentModeHandler::startMonitoringSilentModeHwState() {
194     if (mIsMonitoring) {
195         ALOGW("Silent Mode monitoring is already started");
196         return;
197     }
198     const char* filename = mSilentModeHwStateFilename.c_str();
199     if (!fileExists(filename)) {
200         ALOGW("Failed to start monitoring Silent Mode HW state: %s doesn't exist", filename);
201         return;
202     }
203     if (mFdSilentModeHwState == -1) {
204         if (mFdSilentModeHwState.reset(open(filename, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
205             mFdSilentModeHwState == -1) {
206             ALOGW("Failed to open %s for monitoring: errno = %d", filename, errno);
207             return;
208         }
209     }
210     auto ret = mSysfsMonitor->init([this](const std::vector<int32_t>& fileDescriptors) {
211         // Only one sysfs file is registered.
212         if (mFdSilentModeHwState != fileDescriptors[0]) {
213             return;
214         }
215         handleSilentModeHwStateChange();
216     });
217     if (!ret.ok()) {
218         ALOGW("Failed to initialize SysfsMonitor: %s", ret.error().message().c_str());
219         return;
220     }
221     if (auto ret = mSysfsMonitor->registerFd(mFdSilentModeHwState.get()); !ret.ok()) {
222         ALOGW("Failed to register %s to SysfsMonitor: %s", filename, ret.error().message().c_str());
223         return;
224     }
225     if (mSysfsMonitor->observe(); !ret.ok()) {
226         ALOGI("Failed to observe %s", filename);
227         return;
228     }
229     mIsMonitoring = true;
230     ALOGI("Started monitoring Silent Mode HW state");
231 
232     // Read the current silent mode HW state.
233     handleSilentModeHwStateChange();
234 }
235 
handleSilentModeHwStateChange()236 void SilentModeHandler::handleSilentModeHwStateChange() {
237     if (!mIsMonitoring) {
238         return;
239     }
240     std::string buf;
241     if (!ReadFileToString(mSilentModeHwStateFilename.c_str(), &buf)) {
242         ALOGW("Failed to read %s", mSilentModeHwStateFilename.c_str());
243         return;
244     }
245     bool newSilentMode;
246     bool oldSilentMode;
247     {
248         Mutex::Autolock lock(mMutex);
249         oldSilentMode = std::exchange(mSilentModeByHwState, Trim(buf) == kValueSilentMode);
250         newSilentMode = mSilentModeByHwState;
251     }
252     if (newSilentMode != oldSilentMode) {
253         ALOGI("%s is set to %s", mSilentModeHwStateFilename.c_str(),
254               newSilentMode ? "silent" : "non-silent");
255         handleSilentModeChange(newSilentMode);
256         mSilentModeChangeHandler->notifySilentModeChange(newSilentMode);
257     }
258 }
259 
handleSilentModeChange(bool silent)260 void SilentModeHandler::handleSilentModeChange(bool silent) {
261     if (auto ret = updateKernelSilentMode(silent); !ret.ok()) {
262         ALOGW("Failed to update kernel silent mode: %s", ret.error().message().c_str());
263     }
264     if (auto ret = enableBootAnimation(!silent); !ret.ok()) {
265         ALOGW("Failed to %s boot animation: %s", mSilentModeByHwState ? "disabling" : "enabling",
266               ret.error().message().c_str());
267     }
268 }
269 
enableBootAnimation(bool enabled)270 Result<void> SilentModeHandler::enableBootAnimation(bool enabled) {
271     const std::string value = enabled ? "0" : "1";
272     if (!SetProperty(kPropertyNoBootAnimation, value)) {
273         return Error() << "Failed to set " << kPropertyNoBootAnimation << " property to " << value;
274     }
275     if (!enabled) {
276         if (!SetProperty(kPropertyBootAnimationExit, value)) {
277             return Error() << "Failed to set " << kPropertyBootAnimationExit << " property to "
278                            << value;
279         }
280     }
281     return {};
282 }
283 
switchToForcedMode(bool silent)284 void SilentModeHandler::switchToForcedMode(bool silent) {
285     bool updated = false;
286     {
287         Mutex::Autolock lock(mMutex);
288         if (!mForcedMode) {
289             stopMonitoringSilentModeHwState();
290             mForcedMode = true;
291         }
292         if (mSilentModeByHwState != silent) {
293             mSilentModeByHwState = silent;
294             updated = true;
295         }
296     }
297     if (updated) {
298         updateKernelSilentMode(silent);
299         mSilentModeChangeHandler->notifySilentModeChange(silent);
300     }
301     ALOGI("Now in forced %s mode: monitoring %s is disabled", silent ? "silent" : "non-silent",
302           mSilentModeHwStateFilename.c_str());
303 }
304 
switchToNonForcedMode()305 void SilentModeHandler::switchToNonForcedMode() {
306     bool updated = false;
307     {
308         Mutex::Autolock lock(mMutex);
309         if (mForcedMode) {
310             ALOGI("Now in non forced mode: monitoring %s is started",
311                   mSilentModeHwStateFilename.c_str());
312             mForcedMode = false;
313             updated = true;
314         }
315     }
316     if (updated) {
317         startMonitoringSilentModeHwState();
318     }
319 }
320 
updateKernelSilentMode(bool silent)321 Result<void> SilentModeHandler::updateKernelSilentMode(bool silent) {
322     int fd = open(mKernelSilentModeFilename.c_str(), O_WRONLY | O_NONBLOCK);
323     if (fd < 0) {
324         return Error() << "Failed to open " << mKernelSilentModeFilename;
325     }
326     Result<void> status = {};
327     if (const auto& value = silent ? kValueSilentMode : kValueNonSilentMode;
328         !WriteStringToFd(value, fd)) {
329         status = Error() << "Failed to write " << value << " to fd " << fd;
330     }
331     close(fd);
332     return status;
333 }
334 
335 }  // namespace powerpolicy
336 }  // namespace automotive
337 }  // namespace frameworks
338 }  // namespace android
339