• 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 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
47 #include "hibernate.h"
48 #endif
49 
50 namespace OHOS {
51 namespace HDI {
52 namespace Power {
53 namespace V1_2 {
54 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
55 static constexpr const char * const SUSPEND_STATE = "mem";
56 static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state";
57 static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock";
58 static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock";
59 static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count";
60 #ifdef FASTER_RETRY_OF_SLEEP
61 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(100); // 100ms for phone and tablet
62 #elif defined(SLOWER_RETRY_OF_SLEEP)
63 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(2000); // 2000ms for PC
64 #else
65 static constexpr std::chrono::milliseconds DEFAULT_WAIT_TIME(1000); // 1000ms
66 #endif
67 static constexpr std::chrono::milliseconds MAX_WAIT_TIME(1000 * 60); // 1min
68 static constexpr int32_t WAIT_TIME_FACTOR = 2;
69 static std::chrono::milliseconds waitTime_(DEFAULT_WAIT_TIME);
70 static std::mutex g_mutex;
71 static std::mutex g_suspendMutex;
72 static std::condition_variable g_suspendCv;
73 static std::unique_ptr<std::thread> g_daemon;
74 static std::atomic_bool g_suspending;
75 static std::atomic_bool g_suspendRetry;
76 static sptr<IPowerHdiCallback> g_callback;
77 static UniqueFd wakeupCountFd;
78 static PowerHdfState g_powerState {PowerHdfState::AWAKE};
79 static void AutoSuspendLoop();
80 static int32_t DoSuspend();
81 static void LoadStringFd(int32_t fd, std::string &content);
82 static std::string ReadWakeCount();
83 static bool WriteWakeCount(const std::string &count);
84 static void NotifyCallback(int code);
85 namespace {
86 sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
87 bool g_isHdiStart = false;
88 } // namespace
89 
PowerInterfaceImplGetInstance(void)90 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
91 {
92     using OHOS::HDI::Power::V1_2::PowerInterfaceImpl;
93     PowerInterfaceImpl *service = new (std::nothrow) PowerInterfaceImpl();
94     if (service == nullptr) {
95         return nullptr;
96     }
97 
98     if (service->Init() != HDF_SUCCESS) {
99         delete service;
100         return nullptr;
101     }
102     return service;
103 }
104 
Init()105 int32_t PowerInterfaceImpl::Init()
106 {
107 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
108     auto& powerConfig = PowerConfig::GetInstance();
109     powerConfig.ParseConfig();
110 #endif
111 
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("start suspend");
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     while (true) {
183         std::this_thread::sleep_for(waitTime_);
184 
185         const std::string wakeupCount = ReadWakeCount();
186         if (wakeupCount.empty()) {
187             continue;
188         }
189         if (!g_suspendRetry) {
190             g_suspendCv.wait(suspendLock);
191         }
192         if (!WriteWakeCount(wakeupCount)) {
193             continue;
194         }
195 
196         NotifyCallback(CMD_ON_SUSPEND);
197         g_powerState = PowerHdfState::SLEEP;
198         DoSuspend();
199         g_powerState = PowerHdfState::AWAKE;
200         NotifyCallback(CMD_ON_WAKEUP);
201     }
202     g_suspending = false;
203     g_suspendRetry = false;
204 }
205 
206 static std::string g_suspendTag;
SetSuspendTag(const std::string & tag)207 int32_t PowerInterfaceImpl::SetSuspendTag(const std::string &tag)
208 {
209     HDF_LOGI("Set suspend tag: %{public}s", tag.c_str());
210     g_suspendTag = tag;
211     return HDF_SUCCESS;
212 }
213 
214 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
215 static constexpr const int32_t MAX_RETRY_COUNT = 5;
DoSuspendWithTag()216 int32_t DoSuspendWithTag()
217 {
218     UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
219     if (suspendStateFd < 0) {
220         return HDF_FAILURE;
221     }
222 
223     int loop;
224     for (loop = 0; loop < MAX_RETRY_COUNT; loop++) {
225         bool ret = SaveStringToFd(suspendStateFd, g_suspendTag);
226         if (ret) {
227             break;
228         }
229         HDF_LOGE("SaveStringToFd fail, tag:%{public}s loop:%{public}d", g_suspendTag.c_str(), loop);
230     }
231     HDF_LOGI("Do suspend %{public}d: echo %{public}s > /sys/power/state", loop, g_suspendTag.c_str());
232     if (loop == MAX_RETRY_COUNT) {
233         HDF_LOGE("DoSuspendWithTag fail: %s", g_suspendTag.c_str());
234         g_suspendTag.clear();
235         return HDF_FAILURE;
236     }
237     g_suspendTag.clear();
238     return HDF_SUCCESS;
239 }
240 #endif
241 
DoSuspend()242 int32_t DoSuspend()
243 {
244 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
245     if (!g_suspendTag.empty()) {
246         return DoSuspendWithTag();
247     }
248 #endif
249 
250     UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
251     if (suspendStateFd < 0) {
252         return HDF_FAILURE;
253     }
254     bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
255     if (!ret) {
256         HDF_LOGE("DoSuspend fail");
257         waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
258         return HDF_FAILURE;
259     }
260     waitTime_ = DEFAULT_WAIT_TIME;
261     return HDF_SUCCESS;
262 }
263 
NotifyCallback(int code)264 void NotifyCallback(int code)
265 {
266     if (g_callback == nullptr) {
267         return;
268     }
269     switch (code) {
270         case CMD_ON_SUSPEND:
271             g_callback->OnSuspend();
272             break;
273         case CMD_ON_WAKEUP:
274             g_callback->OnWakeup();
275             break;
276         default:
277             break;
278     }
279 }
280 
StopSuspend()281 int32_t PowerInterfaceImpl::StopSuspend()
282 {
283     HDF_LOGI("stop suspend");
284     g_suspendRetry = false;
285     g_powerState = PowerHdfState::AWAKE;
286     return HDF_SUCCESS;
287 }
288 
ForceSuspend()289 int32_t PowerInterfaceImpl::ForceSuspend()
290 {
291     //force suspend changed into active suspend
292     HDF_LOGI("active suspend");
293     StartSuspend();
294     return HDF_SUCCESS;
295 }
296 
Hibernate()297 int32_t PowerInterfaceImpl::Hibernate()
298 {
299 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
300     HDF_LOGI("hibernate begin.");
301     return Hibernate::GetInstance().DoHibernate();
302 #else
303     HDF_LOGI("hdf hibernate interface not supported.");
304     return HDF_FAILURE;
305 #endif
306 }
307 
SuspendBlock(const std::string & name)308 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
309 {
310     std::lock_guard<std::mutex> lock(g_mutex);
311     if (name.empty()) {
312         return HDF_ERR_INVALID_PARAM;
313     }
314     UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
315     bool ret = SaveStringToFd(fd, name);
316     if (!ret) {
317         return HDF_FAILURE;
318     }
319     return HDF_SUCCESS;
320 }
321 
SuspendUnblock(const std::string & name)322 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
323 {
324     std::lock_guard<std::mutex> lock(g_mutex);
325     if (name.empty()) {
326         return HDF_ERR_INVALID_PARAM;
327     }
328     UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
329     bool ret = SaveStringToFd(fd, name);
330     if (!ret) {
331         return HDF_FAILURE;
332     }
333     return HDF_SUCCESS;
334 }
335 
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)336 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
337 {
338     HDF_LOGI("AddPowerDeathRecipient");
339     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
340     bool result = remote->AddDeathRecipient(g_deathRecipient);
341     if (!result) {
342         HDF_LOGI("AddPowerDeathRecipient fail");
343         return HDF_FAILURE;
344     }
345     return HDF_SUCCESS;
346 }
347 
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)348 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
349 {
350     HDF_LOGI("RemovePowerDeathRecipient");
351     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
352     bool result = remote->RemoveDeathRecipient(g_deathRecipient);
353     if (!result) {
354         HDF_LOGI("RemovePowerDeathRecipient fail");
355         return HDF_FAILURE;
356     }
357     return HDF_SUCCESS;
358 }
359 
OnRemoteDied(const wptr<IRemoteObject> & object)360 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
361 {
362     HDF_LOGI("PowerDeathRecipient OnRemoteDied");
363     powerInterfaceImpl_->UnRegister();
364     RunningLockImpl::Clean();
365 }
366 
LoadStringFd(int32_t fd,std::string & content)367 void LoadStringFd(int32_t fd, std::string &content)
368 {
369     if (fd <= 0) {
370         HDF_LOGW("invalid fd: %{public}d", fd);
371         return;
372     }
373 
374     const int32_t fileLength = lseek(fd, 0, SEEK_END);
375     if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
376         HDF_LOGW("invalid file length(%{public}d)!", fileLength);
377         return;
378     }
379     int32_t loc = lseek(fd, 0, SEEK_SET);
380     if (loc == -1) {
381         HDF_LOGE("lseek file to begin failed!");
382         return;
383     }
384     content.resize(fileLength);
385     const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
386     if (len <= 0) {
387         HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
388         content.clear();
389     }
390 }
391 
ReadWakeCount()392 std::string ReadWakeCount()
393 {
394     if (wakeupCountFd < 0) {
395         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
396     }
397     std::string wakeupCount;
398     LoadStringFd(wakeupCountFd, wakeupCount);
399 
400     return wakeupCount;
401 }
402 
WriteWakeCount(const std::string & count)403 bool WriteWakeCount(const std::string &count)
404 {
405     if (wakeupCountFd < 0) {
406         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
407     }
408     bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
409     return ret;
410 }
411 
LoadSystemInfo(const std::string & path,std::string & info)412 static void LoadSystemInfo(const std::string &path, std::string &info)
413 {
414     UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
415     std::string str;
416     if (fd >= 0) {
417         bool ret = LoadStringFromFd(fd, str);
418         if (!ret) {
419             str = "# Failed to read";
420         }
421     } else {
422         str = "# Failed to open";
423     }
424     info.append(path);
425     info.append(": " + str + "\n");
426 }
427 
PowerDump(std::string & info)428 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
429 {
430     std::string dumpInfo("");
431     LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
432     LoadSystemInfo(LOCK_PATH, dumpInfo);
433     LoadSystemInfo(UNLOCK_PATH, dumpInfo);
434     info = dumpInfo;
435 
436     return HDF_SUCCESS;
437 }
438 
HoldRunningLock(const RunningLockInfo & info)439 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
440 {
441     return RunningLockImpl::Hold(info, g_powerState);
442 }
443 
UnholdRunningLock(const RunningLockInfo & info)444 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
445 {
446     return RunningLockImpl::Unhold(info);
447 }
448 
HoldRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)449 int32_t PowerInterfaceImpl::HoldRunningLockExt(const RunningLockInfo &info,
450     uint64_t lockid, const std::string &bundleName)
451 {
452     HDF_LOGI("Background runningLock active, type=%{public}d name=%{public}s", info.type, info.name.c_str());
453     return RunningLockImpl::HoldLock(info, g_powerState, lockid, bundleName);
454 }
455 
UnholdRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)456 int32_t PowerInterfaceImpl::UnholdRunningLockExt(const RunningLockInfo &info,
457     uint64_t lockid, const std::string &bundleName)
458 {
459     HDF_LOGI("Background runningLock inactive, type=%{public}d name=%{public}s", info.type, info.name.c_str());
460     return RunningLockImpl::UnholdLock(info, lockid, bundleName);
461 }
462 
GetWakeupReason(std::string & reason)463 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
464 {
465 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
466     auto& powerConfig = PowerConfig::GetInstance();
467     std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap= powerConfig.GetPowerSceneConfigMap();
468     std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find("wakeuo_cause");
469     if (it == sceneConfigMap.end()) {
470         HDF_LOGW("wakeuo_cause getPath does not exist");
471         return HDF_FAILURE;
472     }
473     std::string getPath = (it->second).getPath;
474     HDF_LOGI("getPath = %{public}s", getPath.c_str());
475 
476     UniqueFd wakeupCauseFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
477     if (wakeupCauseFd < 0) {
478         return HDF_FAILURE;
479     }
480     LoadStringFd(wakeupCauseFd, reason);
481     return HDF_SUCCESS;
482 #else
483     HDF_LOGW("wakrup cause path not config");
484     return HDF_FAILURE;
485 #endif
486 }
487 } // namespace V1_2
488 } // namespace Power
489 } // namespace HDI
490 } // namespace OHOS
491