• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param);
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