• 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 "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