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