1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "power_interface_impl.h"
17
18 #include "errors.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_remote_service.h"
21 #include "hdf_sbuf.h"
22 #include "pubdef.h"
23 #include "running_lock_impl.h"
24 #include "securec.h"
25 #include "unique_fd.h"
26 #include "power_hdf_log.h"
27 #include "v1_2/power_types.h"
28 #include <atomic>
29 #include <chrono>
30 #include <condition_variable>
31 #include <cstdlib>
32 #include <file_ex.h>
33 #include <hdf_base.h>
34 #include <iproxy_broker.h>
35 #include <iremote_object.h>
36 #include <mutex>
37 #include <sys/eventfd.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <thread>
41 #include <unistd.h>
42
43 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
44 #include "power_config.h"
45 #endif
46
47 namespace OHOS {
48 namespace HDI {
49 namespace Power {
50 namespace V1_2 {
51 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
52 static constexpr const int32_t FORCE_SLEEP_MAX_COUNT = 100;
53
54 static constexpr const char * const SUSPEND_STATE = "mem";
55 static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state";
56 static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock";
57 static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock";
58 static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count";
59 #ifdef FASTER_RETRY_OF_SLEEP
60 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(100); // 100ms for phone and tablet
61 #else
62 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(1000); // 1000ms
63 #endif
64 static constexpr std::chrono::milliseconds MAX_WAIT_TIME(1000 * 60); // 1min
65 static constexpr int32_t WAIT_TIME_FACTOR = 2;
66 static std::chrono::milliseconds waitTime_(DEFAULT_WAIT_TIME);
67 static std::chrono::milliseconds forceThreadWaitTime_(100); // 100ms
68 static std::mutex g_mutex;
69 static std::mutex g_suspendMutex;
70 static std::mutex g_forceSuspendMutex;
71 static std::mutex g_autoSuspendThreadCreatedMutex;
72 static std::mutex g_forceSuspendThreadCreatedMutex;
73 static std::mutex g_controlSuspendThreadMutex;
74
75 static std::condition_variable g_suspendCv;
76 static std::condition_variable g_forceSuspendCv;
77 static std::unique_ptr<std::thread> g_daemon;
78 static std::unique_ptr<std::thread> g_forceDaemon;
79
80 static std::atomic_bool g_suspendRetry {false};
81 static std::atomic_bool g_forceSuspendRetry {false};
82 static std::atomic_bool g_autoSuspendThreadCreated {false};
83 static std::atomic_bool g_forceSuspendThreadCreated {false};
84
85 static sptr<IPowerHdiCallback> g_callback;
86 static UniqueFd wakeupCountFd;
87 static PowerHdfState g_powerState {PowerHdfState::AWAKE};
88 static void AutoSuspendLoop();
89 static void ForceSuspendLoop();
90 static int32_t DoSuspend();
91 static void LoadStringFd(int32_t fd, std::string &content);
92 static std::string ReadWakeCount();
93 static bool WriteWakeCount(const std::string &count);
94 static void NotifyCallback(int code);
95 namespace {
96 sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
97 bool g_isHdiStart = false;
98 } // namespace
99
PowerInterfaceImplGetInstance(void)100 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
101 {
102 using OHOS::HDI::Power::V1_2::PowerInterfaceImpl;
103 PowerInterfaceImpl *service = new (std::nothrow) PowerInterfaceImpl();
104 if (service == nullptr) {
105 return nullptr;
106 }
107
108 if (service->Init() != HDF_SUCCESS) {
109 delete service;
110 return nullptr;
111 }
112 return service;
113 }
114
Init()115 int32_t PowerInterfaceImpl::Init()
116 {
117 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
118 auto& powerConfig = PowerConfig::GetInstance();
119 powerConfig.ParseConfig();
120 #endif
121 return HDF_SUCCESS;
122 }
123
RegisterCallback(const sptr<IPowerHdiCallback> & ipowerHdiCallback)124 int32_t PowerInterfaceImpl::RegisterCallback(const sptr<IPowerHdiCallback> &ipowerHdiCallback)
125 {
126 std::lock_guard<std::mutex> lock(g_mutex);
127 if (!g_isHdiStart) {
128 g_callback = ipowerHdiCallback;
129 if (g_callback == nullptr) {
130 UnRegister();
131 return HDF_SUCCESS;
132 }
133 g_deathRecipient = new PowerDeathRecipient(this);
134 if (g_deathRecipient == nullptr) {
135 return HDF_FAILURE;
136 }
137 AddPowerDeathRecipient(g_callback);
138 g_isHdiStart = true;
139 }
140
141 return HDF_SUCCESS;
142 }
143
UnRegister()144 int32_t PowerInterfaceImpl::UnRegister()
145 {
146 HDF_LOGI("UnRegister");
147 RemovePowerDeathRecipient(g_callback);
148 g_callback = nullptr;
149 g_isHdiStart = false;
150 return HDF_SUCCESS;
151 }
152
RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> & iPowerRunningLockCallback)153 int32_t PowerInterfaceImpl::RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback>
154 &iPowerRunningLockCallback)
155 {
156 if (iPowerRunningLockCallback != nullptr) {
157 UnRegisterRunningLockCallback();
158 }
159 RunningLockImpl::RegisterRunningLockCallback(iPowerRunningLockCallback);
160 return HDF_SUCCESS;
161 }
162
UnRegisterRunningLockCallback()163 int32_t PowerInterfaceImpl::UnRegisterRunningLockCallback()
164 {
165 RunningLockImpl::UnRegisterRunningLockCallback();
166 return HDF_SUCCESS;
167 }
168
AutoSuspendLoop()169 void AutoSuspendLoop()
170 {
171 auto suspendLock = std::unique_lock(g_suspendMutex);
172 while (true) {
173 std::this_thread::sleep_for(waitTime_);
174
175 const std::string wakeupCount = ReadWakeCount();
176 if (wakeupCount.empty()) {
177 continue;
178 }
179 if (!g_suspendRetry) {
180 g_suspendCv.wait(suspendLock);
181 }
182 if (!WriteWakeCount(wakeupCount)) {
183 continue;
184 }
185 if (g_forceSuspendRetry) {
186 continue;
187 }
188 NotifyCallback(CMD_ON_SUSPEND);
189 g_powerState = PowerHdfState::SLEEP;
190 DoSuspend();
191 g_powerState = PowerHdfState::AWAKE;
192 NotifyCallback(CMD_ON_WAKEUP);
193 }
194 }
195
ForceSuspendLoop()196 void ForceSuspendLoop()
197 {
198 auto suspendLock = std::unique_lock(g_forceSuspendMutex);
199 while (true) {
200 if (!g_forceSuspendRetry) {
201 g_forceSuspendCv.wait(suspendLock);
202 }
203
204 NotifyCallback(CMD_ON_SUSPEND);
205 g_powerState = PowerHdfState::SLEEP;
206 DoSuspend();
207 g_powerState = PowerHdfState::AWAKE;
208 NotifyCallback(CMD_ON_WAKEUP);
209 /*
210 * Sleep for 10s when wake up form non-configuration source,
211 * and just sleep until g_forceSuspendRetry is false when wake up
212 * form configuration source in order to reduce response time of
213 * next force suspend.
214 */
215 int count = 1;
216 while (count <= FORCE_SLEEP_MAX_COUNT) {
217 if (!g_forceSuspendRetry) {
218 HDF_LOGI("do not need to sleep.");
219 break;
220 }
221 std::this_thread::sleep_for(forceThreadWaitTime_);
222 count++;
223 }
224 }
225 }
226
DoSuspend()227 int32_t DoSuspend()
228 {
229 std::lock_guard<std::mutex> lock(g_mutex);
230 UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
231 if (suspendStateFd < 0) {
232 return HDF_FAILURE;
233 }
234 bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
235 if (!ret) {
236 HDF_LOGE("DoSuspend fail");
237 waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
238 return HDF_FAILURE;
239 }
240 waitTime_ = DEFAULT_WAIT_TIME;
241 return HDF_SUCCESS;
242 }
243
CreateAutoSuspendThread()244 void PowerInterfaceImpl::CreateAutoSuspendThread()
245 {
246 std::lock_guard<std::mutex> lock(g_autoSuspendThreadCreatedMutex);
247 if (g_autoSuspendThreadCreated) {
248 return;
249 }
250
251 HDF_LOGI("create auto sleep thread");
252 g_daemon = std::make_unique<std::thread>(&AutoSuspendLoop);
253 g_daemon->detach();
254 g_autoSuspendThreadCreated = true;
255 }
256
CreateForceSuspendThread()257 void PowerInterfaceImpl::CreateForceSuspendThread()
258 {
259 std::lock_guard<std::mutex> lock(g_forceSuspendThreadCreatedMutex);
260 if (g_forceSuspendThreadCreated) {
261 return;
262 }
263
264 HDF_LOGI("create force sleep thread");
265 g_forceDaemon = std::make_unique<std::thread>(&ForceSuspendLoop);
266 g_forceDaemon->detach();
267 g_forceSuspendThreadCreated = true;
268 }
269
NotifyCallback(int code)270 void NotifyCallback(int code)
271 {
272 if (g_callback == nullptr) {
273 return;
274 }
275 switch (code) {
276 case CMD_ON_SUSPEND:
277 g_callback->OnSuspend();
278 break;
279 case CMD_ON_WAKEUP:
280 g_callback->OnWakeup();
281 break;
282 default:
283 break;
284 }
285 }
286
StopSuspend()287 int32_t PowerInterfaceImpl::StopSuspend()
288 {
289 HDF_LOGI("stop suspend");
290 std::lock_guard<std::mutex> lock(g_controlSuspendThreadMutex);
291 g_suspendRetry = false;
292 g_forceSuspendRetry = false;
293 g_powerState = PowerHdfState::AWAKE;
294 return HDF_SUCCESS;
295 }
296
StartSuspend()297 int32_t PowerInterfaceImpl::StartSuspend()
298 {
299 HDF_LOGI("start suspend");
300 {
301 std::lock_guard<std::mutex> lock(g_controlSuspendThreadMutex);
302 g_powerState = PowerHdfState::INACTIVE;
303 g_suspendRetry = true;
304 g_suspendCv.notify_one();
305 }
306 CreateAutoSuspendThread();
307 return HDF_SUCCESS;
308 }
309
ForceSuspend()310 int32_t PowerInterfaceImpl::ForceSuspend()
311 {
312 HDF_LOGI("force suspend");
313 {
314 std::lock_guard<std::mutex> lock(g_controlSuspendThreadMutex);
315 g_forceSuspendRetry = true;
316 g_forceSuspendCv.notify_one();
317 }
318 CreateForceSuspendThread();
319 return HDF_SUCCESS;
320 }
321
Hibernate()322 int32_t PowerInterfaceImpl::Hibernate()
323 {
324 HDF_LOGI("hibernate begin.");
325 return HDF_SUCCESS;
326 }
327
SuspendBlock(const std::string & name)328 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
329 {
330 std::lock_guard<std::mutex> lock(g_mutex);
331 if (name.empty()) {
332 return HDF_ERR_INVALID_PARAM;
333 }
334 UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
335 bool ret = SaveStringToFd(fd, name);
336 if (!ret) {
337 return HDF_FAILURE;
338 }
339 return HDF_SUCCESS;
340 }
341
SuspendUnblock(const std::string & name)342 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
343 {
344 std::lock_guard<std::mutex> lock(g_mutex);
345 if (name.empty()) {
346 return HDF_ERR_INVALID_PARAM;
347 }
348 UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
349 bool ret = SaveStringToFd(fd, name);
350 if (!ret) {
351 return HDF_FAILURE;
352 }
353 return HDF_SUCCESS;
354 }
355
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)356 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
357 {
358 HDF_LOGI("AddPowerDeathRecipient");
359 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
360 bool result = remote->AddDeathRecipient(g_deathRecipient);
361 if (!result) {
362 HDF_LOGI("AddPowerDeathRecipient fail");
363 return HDF_FAILURE;
364 }
365 return HDF_SUCCESS;
366 }
367
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)368 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
369 {
370 HDF_LOGI("RemovePowerDeathRecipient");
371 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
372 bool result = remote->RemoveDeathRecipient(g_deathRecipient);
373 if (!result) {
374 HDF_LOGI("RemovePowerDeathRecipient fail");
375 return HDF_FAILURE;
376 }
377 return HDF_SUCCESS;
378 }
379
OnRemoteDied(const wptr<IRemoteObject> & object)380 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
381 {
382 HDF_LOGI("PowerDeathRecipient OnRemoteDied");
383 powerInterfaceImpl_->UnRegister();
384 RunningLockImpl::Clean();
385 }
386
LoadStringFd(int32_t fd,std::string & content)387 void LoadStringFd(int32_t fd, std::string &content)
388 {
389 if (fd <= 0) {
390 HDF_LOGW("invalid fd: %{public}d", fd);
391 return;
392 }
393
394 const int32_t fileLength = lseek(fd, 0, SEEK_END);
395 if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
396 HDF_LOGW("invalid file length(%{public}d)!", fileLength);
397 return;
398 }
399 int32_t loc = lseek(fd, 0, SEEK_SET);
400 if (loc == -1) {
401 HDF_LOGE("lseek file to begin failed!");
402 return;
403 }
404 content.resize(fileLength);
405 const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
406 if (len <= 0) {
407 HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
408 content.clear();
409 }
410 }
411
ReadWakeCount()412 std::string ReadWakeCount()
413 {
414 if (wakeupCountFd < 0) {
415 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
416 }
417 std::string wakeupCount;
418 LoadStringFd(wakeupCountFd, wakeupCount);
419
420 return wakeupCount;
421 }
422
WriteWakeCount(const std::string & count)423 bool WriteWakeCount(const std::string &count)
424 {
425 if (wakeupCountFd < 0) {
426 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
427 }
428 bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
429 return ret;
430 }
431
LoadSystemInfo(const std::string & path,std::string & info)432 static void LoadSystemInfo(const std::string &path, std::string &info)
433 {
434 UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
435 std::string str;
436 if (fd >= 0) {
437 bool ret = LoadStringFromFd(fd, str);
438 if (!ret) {
439 str = "# Failed to read";
440 }
441 } else {
442 str = "# Failed to open";
443 }
444 info.append(path);
445 info.append(": " + str + "\n");
446 }
447
PowerDump(std::string & info)448 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
449 {
450 std::string dumpInfo("");
451 LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
452 LoadSystemInfo(LOCK_PATH, dumpInfo);
453 LoadSystemInfo(UNLOCK_PATH, dumpInfo);
454 info = dumpInfo;
455
456 return HDF_SUCCESS;
457 }
458
HoldRunningLock(const RunningLockInfo & info)459 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
460 {
461 return RunningLockImpl::Hold(info, g_powerState);
462 }
463
UnholdRunningLock(const RunningLockInfo & info)464 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
465 {
466 return RunningLockImpl::Unhold(info);
467 }
468
HoldRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)469 int32_t PowerInterfaceImpl::HoldRunningLockExt(const RunningLockInfo &info,
470 uint64_t lockid, const std::string &bundleName)
471 {
472 return RunningLockImpl::HoldLock(info, g_powerState, lockid, bundleName);
473 }
474
UnholdRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)475 int32_t PowerInterfaceImpl::UnholdRunningLockExt(const RunningLockInfo &info,
476 uint64_t lockid, const std::string &bundleName)
477 {
478 return RunningLockImpl::UnholdLock(info, lockid, bundleName);
479 }
480
GetWakeupReason(std::string & reason)481 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
482 {
483 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
484 auto& powerConfig = PowerConfig::GetInstance();
485 std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap= powerConfig.GetPowerSceneConfigMap();
486 std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find("wakeuo_cause");
487 if (it == sceneConfigMap.end()) {
488 HDF_LOGW("wakeuo_cause getPath does not exist");
489 return HDF_FAILURE;
490 }
491 std::string getPath = (it->second).getPath;
492 HDF_LOGI("getPath = %{public}s", getPath.c_str());
493
494 UniqueFd wakeupCauseFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
495 if (wakeupCauseFd < 0) {
496 return HDF_FAILURE;
497 }
498 LoadStringFd(wakeupCauseFd, reason);
499 return HDF_SUCCESS;
500 #else
501 HDF_LOGW("wakrup cause path not config");
502 return HDF_FAILURE;
503 #endif
504 }
505 } // namespace V1_2
506 } // namespace Power
507 } // namespace HDI
508 } // namespace OHOS
509