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 "power_xcollie.h"
28 #include "v1_2/power_types.h"
29 #include <atomic>
30 #include <chrono>
31 #include <condition_variable>
32 #include <cstdlib>
33 #include <file_ex.h>
34 #include <hdf_base.h>
35 #include <iproxy_broker.h>
36 #include <iremote_object.h>
37 #include <mutex>
38 #include <sys/eventfd.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <thread>
42 #include <unistd.h>
43
44 #include "power_config.h"
45 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
46 #include "hibernate.h"
47 #endif
48
49 namespace OHOS {
50 namespace HDI {
51 namespace Power {
52 namespace V1_2 {
53 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
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 #elif defined(SLOWER_RETRY_OF_SLEEP)
62 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(500); // 500ms for PC
63 #else
64 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(1000); // 1000ms
65 #endif
66 #ifdef FASTER_RETRY_OF_SLEEP
67 static constexpr std::chrono::milliseconds MAX_WAIT_TIME(5763); // 5763ms for phone and tablet
68 #else
69 static constexpr std::chrono::milliseconds MAX_WAIT_TIME(1000 * 60); // 1min
70 #endif
71 static constexpr int32_t WAIT_TIME_FACTOR = 2;
72 static std::chrono::milliseconds waitTime_(DEFAULT_WAIT_TIME);
73 static std::mutex g_mutex;
74 static std::mutex g_suspendMutex;
75 static std::condition_variable g_suspendCv;
76 static std::unique_ptr<std::thread> g_daemon;
77 static std::atomic_bool g_suspending;
78 static std::atomic_bool g_suspendRetry;
79 static sptr<IPowerHdiCallback> g_callback;
80 static UniqueFd wakeupCountFd;
81 static PowerHdfState g_powerState {PowerHdfState::AWAKE};
82 static void AutoSuspendLoop();
83 static int32_t DoSuspend();
84 static void LoadStringFd(int32_t fd, std::string &content);
85 static std::string ReadWakeCount();
86 static bool WriteWakeCount(const std::string &count);
87 static void NotifyCallback(int code);
88 namespace {
89 sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
90 bool g_isHdiStart = false;
91 } // namespace
92
PowerInterfaceImplGetInstance(void)93 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
94 {
95 using OHOS::HDI::Power::V1_2::PowerInterfaceImpl;
96 PowerInterfaceImpl *service = new (std::nothrow) PowerInterfaceImpl();
97 if (service == nullptr) {
98 return nullptr;
99 }
100
101 if (service->Init() != HDF_SUCCESS) {
102 delete service;
103 return nullptr;
104 }
105 return service;
106 }
107
Init()108 int32_t PowerInterfaceImpl::Init()
109 {
110 auto& powerConfig = PowerConfig::GetInstance();
111 powerConfig.ParseConfig();
112 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
113 Hibernate::GetInstance().Init();
114 #endif
115 return HDF_SUCCESS;
116 }
117
RegisterCallback(const sptr<IPowerHdiCallback> & ipowerHdiCallback)118 int32_t PowerInterfaceImpl::RegisterCallback(const sptr<IPowerHdiCallback> &ipowerHdiCallback)
119 {
120 std::lock_guard<std::mutex> lock(g_mutex);
121 if (!g_isHdiStart) {
122 g_callback = ipowerHdiCallback;
123 if (g_callback == nullptr) {
124 UnRegister();
125 return HDF_SUCCESS;
126 }
127 g_deathRecipient = new PowerDeathRecipient(this);
128 if (g_deathRecipient == nullptr) {
129 return HDF_FAILURE;
130 }
131 AddPowerDeathRecipient(g_callback);
132 g_isHdiStart = true;
133 }
134
135 return HDF_SUCCESS;
136 }
137
UnRegister()138 int32_t PowerInterfaceImpl::UnRegister()
139 {
140 HDF_LOGI("UnRegister");
141 RemovePowerDeathRecipient(g_callback);
142 g_callback = nullptr;
143 g_isHdiStart = false;
144 return HDF_SUCCESS;
145 }
146
RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> & iPowerRunningLockCallback)147 int32_t PowerInterfaceImpl::RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback>
148 &iPowerRunningLockCallback)
149 {
150 if (iPowerRunningLockCallback != nullptr) {
151 UnRegisterRunningLockCallback();
152 }
153 RunningLockImpl::RegisterRunningLockCallback(iPowerRunningLockCallback);
154 return HDF_SUCCESS;
155 }
156
UnRegisterRunningLockCallback()157 int32_t PowerInterfaceImpl::UnRegisterRunningLockCallback()
158 {
159 RunningLockImpl::UnRegisterRunningLockCallback();
160 return HDF_SUCCESS;
161 }
162
StartSuspend()163 int32_t PowerInterfaceImpl::StartSuspend()
164 {
165 std::lock_guard<std::mutex> lock(g_mutex);
166 HDF_LOGI("staS3");
167 g_suspendRetry = true;
168 if (g_suspending) {
169 g_powerState = PowerHdfState::INACTIVE;
170 g_suspendCv.notify_one();
171 return HDF_SUCCESS;
172 }
173 g_suspending = true;
174 g_daemon = std::make_unique<std::thread>(&AutoSuspendLoop);
175 g_daemon->detach();
176 return HDF_SUCCESS;
177 }
178
AutoSuspendLoop()179 void AutoSuspendLoop()
180 {
181 auto suspendLock = std::unique_lock(g_suspendMutex);
182 #ifdef DRIVERS_PERIPHERAL_POWER_HOST_SCHED_PRIORITY
183 struct sched_param param = { 0 };
184 param.sched_priority = 1; // thread priority:51
185 int32_t schRet = sched_setscheduler(0, SCHED_FIFO, ¶m);
186 if (schRet != 0) {
187 HDF_LOGI("power_host set SCHED_FIFO, schRet: %{public}d error: %{public}s", schRet, strerror(errno));
188 }
189 #endif
190 while (true) {
191 std::this_thread::sleep_for(waitTime_);
192 const std::string wakeupCount = ReadWakeCount();
193 if (wakeupCount.empty()) {
194 continue;
195 }
196 if (!g_suspendRetry) {
197 g_suspendCv.wait(suspendLock);
198 }
199 if (!WriteWakeCount(wakeupCount)) {
200 continue;
201 }
202
203 NotifyCallback(CMD_ON_SUSPEND);
204 g_powerState = PowerHdfState::SLEEP;
205 DoSuspend();
206 g_powerState = PowerHdfState::AWAKE;
207 NotifyCallback(CMD_ON_WAKEUP);
208 }
209 g_suspending = false;
210 g_suspendRetry = false;
211 }
212
213 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
214 static constexpr const int32_t MAX_RETRY_COUNT = 5;
215 static int32_t g_ulsr_loop = 0;
216 static std::string g_suspendTag;
SetSuspendTag(const std::string & tag)217 int32_t PowerInterfaceImpl::SetSuspendTag(const std::string &tag)
218 {
219 HDF_LOGI("Set suspend tag: %{public}s", tag.c_str());
220 g_suspendTag = tag;
221 g_ulsr_loop = 0;
222 return HDF_SUCCESS;
223 }
224
DoSuspendWithTag()225 int32_t DoSuspendWithTag()
226 {
227 UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
228 if (suspendStateFd < 0) {
229 return HDF_FAILURE;
230 }
231
232 g_ulsr_loop++;
233 bool ret = SaveStringToFd(suspendStateFd, g_suspendTag);
234 if (!ret) {
235 waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
236 HDF_LOGE("SaveStringToFd fail, tag:%{public}s loop:%{public}d", g_suspendTag.c_str(), g_ulsr_loop);
237 if (g_ulsr_loop >= MAX_RETRY_COUNT) {
238 HDF_LOGE("DoSuspendWithTag fail: %{public}s", g_suspendTag.c_str());
239 g_suspendTag.clear();
240 waitTime_ = DEFAULT_WAIT_TIME;
241 return HDF_FAILURE;
242 }
243 return HDF_SUCCESS;
244 }
245 HDF_LOGI("Do Suspend %{public}d: echo %{public}s > /sys/power/state", g_ulsr_loop, g_suspendTag.c_str());
246 g_suspendTag.clear();
247 waitTime_ = DEFAULT_WAIT_TIME;
248 return HDF_SUCCESS;
249 }
250 #else
SetSuspendTag(const std::string & tag)251 int32_t PowerInterfaceImpl::SetSuspendTag(const std::string &tag)
252 {
253 return HDF_SUCCESS;
254 }
255 #endif
256
DoSuspend()257 int32_t DoSuspend()
258 {
259 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
260 if (!g_suspendTag.empty()) {
261 return DoSuspendWithTag();
262 }
263 #endif
264
265 UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
266 if (suspendStateFd < 0) {
267 HDF_LOGE("DoSuspend open suspendStateFd fail, error: %{public}s", strerror(errno));
268 return HDF_FAILURE;
269 }
270 HDF_LOGD("DoSuspend SaveStringToFd");
271 bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
272 if (!ret) {
273 HDF_LOGE("S3 FA");
274 waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
275 return HDF_FAILURE;
276 }
277 waitTime_ = DEFAULT_WAIT_TIME;
278 return HDF_SUCCESS;
279 }
280
NotifyCallback(int code)281 void NotifyCallback(int code)
282 {
283 if (g_callback == nullptr) {
284 return;
285 }
286 switch (code) {
287 case CMD_ON_SUSPEND:
288 g_callback->OnSuspend();
289 break;
290 case CMD_ON_WAKEUP:
291 g_callback->OnWakeup();
292 break;
293 default:
294 break;
295 }
296 }
297
StopSuspend()298 int32_t PowerInterfaceImpl::StopSuspend()
299 {
300 HDF_LOGI("stpS3");
301 g_suspendRetry = false;
302 g_powerState = PowerHdfState::AWAKE;
303 return HDF_SUCCESS;
304 }
305
ForceSuspend()306 int32_t PowerInterfaceImpl::ForceSuspend()
307 {
308 //force suspend changed into active suspend
309 HDF_LOGI("active suspend");
310 StartSuspend();
311 return HDF_SUCCESS;
312 }
313
Hibernate()314 int32_t PowerInterfaceImpl::Hibernate()
315 {
316 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
317 HDF_LOGI("hibernate begin.");
318 return Hibernate::GetInstance().DoHibernate();
319 #else
320 HDF_LOGI("hdf hibernate interface not supported.");
321 return HDF_FAILURE;
322 #endif
323 }
324
SuspendBlock(const std::string & name)325 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
326 {
327 std::lock_guard<std::mutex> lock(g_mutex);
328 if (name.empty()) {
329 return HDF_ERR_INVALID_PARAM;
330 }
331 UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
332 bool ret = SaveStringToFd(fd, name);
333 if (!ret) {
334 return HDF_FAILURE;
335 }
336 return HDF_SUCCESS;
337 }
338
SuspendUnblock(const std::string & name)339 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
340 {
341 std::lock_guard<std::mutex> lock(g_mutex);
342 if (name.empty()) {
343 return HDF_ERR_INVALID_PARAM;
344 }
345 UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
346 bool ret = SaveStringToFd(fd, name);
347 if (!ret) {
348 return HDF_FAILURE;
349 }
350 return HDF_SUCCESS;
351 }
352
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)353 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
354 {
355 HDF_LOGI("AddPowerDeathRecipient");
356 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
357 bool result = remote->AddDeathRecipient(g_deathRecipient);
358 if (!result) {
359 HDF_LOGI("AddPowerDeathRecipient fail");
360 return HDF_FAILURE;
361 }
362 return HDF_SUCCESS;
363 }
364
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)365 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
366 {
367 HDF_LOGI("RemovePowerDeathRecipient");
368 const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
369 bool result = remote->RemoveDeathRecipient(g_deathRecipient);
370 if (!result) {
371 HDF_LOGI("RemovePowerDeathRecipient fail");
372 return HDF_FAILURE;
373 }
374 return HDF_SUCCESS;
375 }
376
OnRemoteDied(const wptr<IRemoteObject> & object)377 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
378 {
379 HDF_LOGI("PowerDeathRecipient OnRemoteDied");
380 powerInterfaceImpl_->UnRegister();
381 RunningLockImpl::Clean();
382 }
383
LoadStringFd(int32_t fd,std::string & content)384 void LoadStringFd(int32_t fd, std::string &content)
385 {
386 if (fd <= 0) {
387 HDF_LOGW("invalid fd: %{public}d", fd);
388 return;
389 }
390
391 const int32_t fileLength = lseek(fd, 0, SEEK_END);
392 if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
393 HDF_LOGW("invalid file length(%{public}d)!", fileLength);
394 return;
395 }
396 int32_t loc = lseek(fd, 0, SEEK_SET);
397 if (loc == -1) {
398 HDF_LOGE("lseek file to begin failed!");
399 return;
400 }
401 content.resize(fileLength);
402 const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
403 if (len <= 0) {
404 HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
405 content.clear();
406 }
407 }
408
ReadWakeCount()409 std::string ReadWakeCount()
410 {
411 if (wakeupCountFd < 0) {
412 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
413 }
414 std::string wakeupCount;
415 LoadStringFd(wakeupCountFd, wakeupCount);
416
417 return wakeupCount;
418 }
419
WriteWakeCount(const std::string & count)420 bool WriteWakeCount(const std::string &count)
421 {
422 if (wakeupCountFd < 0) {
423 wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
424 }
425 bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
426 return ret;
427 }
428
LoadSystemInfo(const std::string & path,std::string & info)429 static void LoadSystemInfo(const std::string &path, std::string &info)
430 {
431 UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
432 std::string str;
433 if (fd >= 0) {
434 bool ret = LoadStringFromFd(fd, str);
435 if (!ret) {
436 str = "# Failed to read";
437 }
438 } else {
439 str = "# Failed to open";
440 }
441 info.append(path);
442 info.append(": " + str + "\n");
443 }
444
PowerDump(std::string & info)445 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
446 {
447 std::string dumpInfo("");
448 LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
449 LoadSystemInfo(LOCK_PATH, dumpInfo);
450 LoadSystemInfo(UNLOCK_PATH, dumpInfo);
451 info = dumpInfo;
452
453 return HDF_SUCCESS;
454 }
455
HoldRunningLock(const RunningLockInfo & info)456 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
457 {
458 Power::PowerXCollie powerXcollie("Power_HoldRunningLock");
459 return RunningLockImpl::Hold(info, g_powerState);
460 }
461
UnholdRunningLock(const RunningLockInfo & info)462 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
463 {
464 Power::PowerXCollie powerXcollie("Power_UnholdRunningLock");
465 return RunningLockImpl::Unhold(info);
466 }
467
HoldRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)468 int32_t PowerInterfaceImpl::HoldRunningLockExt(const RunningLockInfo &info,
469 uint64_t lockid, const std::string &bundleName)
470 {
471 // Background runningLock active
472 HDF_LOGI("BL active,T=%{public}d", info.type);
473 Power::PowerXCollie powerXcollie("Power_HoldRunningLockExt");
474 return RunningLockImpl::HoldLock(info, g_powerState, lockid, bundleName);
475 }
476
UnholdRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)477 int32_t PowerInterfaceImpl::UnholdRunningLockExt(const RunningLockInfo &info,
478 uint64_t lockid, const std::string &bundleName)
479 {
480 // Background runningLock inactive
481 HDF_LOGI("BL inactive,T=%{public}d", info.type);
482 Power::PowerXCollie powerXcollie("Power_UnholdRunningLockExt");
483 return RunningLockImpl::UnholdLock(info, lockid, bundleName);
484 }
485
GetWakeupReason(std::string & reason)486 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
487 {
488 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
489 return GetPowerConfig("wakeuo_cause", reason);
490 #else
491 HDF_LOGW("wakrup cause path not config");
492 return HDF_FAILURE;
493 #endif
494 }
495
SetPowerConfig(const std::string & sceneName,const std::string & value)496 int32_t PowerInterfaceImpl::SetPowerConfig(const std::string &sceneName, const std::string &value)
497 {
498 auto& powerConfig = PowerConfig::GetInstance();
499 std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap = powerConfig.GetPowerSceneConfigMap();
500 if (sceneConfigMap.empty()) {
501 HDF_LOGE("SetPowerConfig sceneConfigMap is empty");
502 return HDF_ERR_NOT_SUPPORT;
503 }
504
505 std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find(sceneName);
506 if (it == sceneConfigMap.end()) {
507 HDF_LOGE("SetPowerConfig sceneName: %{public}s does not exist", sceneName.c_str());
508 return HDF_FAILURE;
509 }
510 std::string setPath = (it->second).setPath;
511 HDF_LOGI("SetPowerConfig setPath = %{public}s", setPath.c_str());
512
513 UniqueFd setValueFd = UniqueFd(TEMP_FAILURE_RETRY(open(setPath.c_str(), O_RDWR | O_CLOEXEC)));
514 if (setValueFd < 0) {
515 HDF_LOGE("SetPowerConfig open failed");
516 return HDF_FAILURE;
517 }
518 bool ret = SaveStringToFd(setValueFd, value);
519 if (!ret) {
520 HDF_LOGE("SetPowerConfig SaveStringToFd failed");
521 return HDF_FAILURE;
522 }
523 return HDF_SUCCESS;
524 }
525
GetPowerConfig(const std::string & sceneName,std::string & value)526 int32_t PowerInterfaceImpl::GetPowerConfig(const std::string &sceneName, std::string &value)
527 {
528 auto& powerConfig = PowerConfig::GetInstance();
529 std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap = powerConfig.GetPowerSceneConfigMap();
530 if (sceneConfigMap.empty()) {
531 HDF_LOGE("GetPowerConfig sceneConfigMap is empty");
532 return HDF_ERR_NOT_SUPPORT;
533 }
534
535 std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find(sceneName);
536 if (it == sceneConfigMap.end()) {
537 HDF_LOGE("GetPowerConfig sceneName: %{public}s does not exist", sceneName.c_str());
538 return HDF_FAILURE;
539 }
540 std::string getPath = (it->second).getPath;
541 HDF_LOGI("GetPowerConfig getPath = %{public}s", getPath.c_str());
542
543 UniqueFd getValueFd = UniqueFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
544 if (getValueFd < 0) {
545 HDF_LOGE("GetPowerConfig open failed");
546 return HDF_FAILURE;
547 }
548 LoadStringFd(getValueFd, value);
549 return HDF_SUCCESS;
550 }
551 } // namespace V1_2
552 } // namespace Power
553 } // namespace HDI
554 } // namespace OHOS
555