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     HDF_LOGI("start suspend");
166     std::lock_guard<std::mutex> lock(g_mutex);
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     std::lock_guard<std::mutex> lock(g_mutex);
245 
246 #ifdef DRIVER_PERIPHERAL_POWER_SUSPEND_WITH_TAG
247     if (!g_suspendTag.empty()) {
248         return DoSuspendWithTag();
249     }
250 #endif
251 
252     UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
253     if (suspendStateFd < 0) {
254         return HDF_FAILURE;
255     }
256     bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
257     if (!ret) {
258         HDF_LOGE("DoSuspend fail");
259         waitTime_ = std::min(waitTime_ * WAIT_TIME_FACTOR, MAX_WAIT_TIME);
260         return HDF_FAILURE;
261     }
262     waitTime_ = DEFAULT_WAIT_TIME;
263     return HDF_SUCCESS;
264 }
265 
NotifyCallback(int code)266 void NotifyCallback(int code)
267 {
268     if (g_callback == nullptr) {
269         return;
270     }
271     switch (code) {
272         case CMD_ON_SUSPEND:
273             g_callback->OnSuspend();
274             break;
275         case CMD_ON_WAKEUP:
276             g_callback->OnWakeup();
277             break;
278         default:
279             break;
280     }
281 }
282 
StopSuspend()283 int32_t PowerInterfaceImpl::StopSuspend()
284 {
285     HDF_LOGI("stop suspend");
286     g_suspendRetry = false;
287     g_powerState = PowerHdfState::AWAKE;
288     return HDF_SUCCESS;
289 }
290 
ForceSuspend()291 int32_t PowerInterfaceImpl::ForceSuspend()
292 {
293     //force suspend changed into active suspend
294     HDF_LOGI("active suspend");
295     StartSuspend();
296     return HDF_SUCCESS;
297 }
298 
Hibernate()299 int32_t PowerInterfaceImpl::Hibernate()
300 {
301 #ifdef DRIVERS_PERIPHERAL_POWER_ENABLE_S4
302     HDF_LOGI("hibernate begin.");
303     return Hibernate::GetInstance().DoHibernate();
304 #else
305     HDF_LOGI("hdf hibernate interface not supported.");
306     return HDF_FAILURE;
307 #endif
308 }
309 
SuspendBlock(const std::string & name)310 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
311 {
312     std::lock_guard<std::mutex> lock(g_mutex);
313     if (name.empty()) {
314         return HDF_ERR_INVALID_PARAM;
315     }
316     UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
317     bool ret = SaveStringToFd(fd, name);
318     if (!ret) {
319         return HDF_FAILURE;
320     }
321     return HDF_SUCCESS;
322 }
323 
SuspendUnblock(const std::string & name)324 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
325 {
326     std::lock_guard<std::mutex> lock(g_mutex);
327     if (name.empty()) {
328         return HDF_ERR_INVALID_PARAM;
329     }
330     UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
331     bool ret = SaveStringToFd(fd, name);
332     if (!ret) {
333         return HDF_FAILURE;
334     }
335     return HDF_SUCCESS;
336 }
337 
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)338 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
339 {
340     HDF_LOGI("AddPowerDeathRecipient");
341     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
342     bool result = remote->AddDeathRecipient(g_deathRecipient);
343     if (!result) {
344         HDF_LOGI("AddPowerDeathRecipient fail");
345         return HDF_FAILURE;
346     }
347     return HDF_SUCCESS;
348 }
349 
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)350 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
351 {
352     HDF_LOGI("RemovePowerDeathRecipient");
353     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
354     bool result = remote->RemoveDeathRecipient(g_deathRecipient);
355     if (!result) {
356         HDF_LOGI("RemovePowerDeathRecipient fail");
357         return HDF_FAILURE;
358     }
359     return HDF_SUCCESS;
360 }
361 
OnRemoteDied(const wptr<IRemoteObject> & object)362 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
363 {
364     HDF_LOGI("PowerDeathRecipient OnRemoteDied");
365     powerInterfaceImpl_->UnRegister();
366     RunningLockImpl::Clean();
367 }
368 
LoadStringFd(int32_t fd,std::string & content)369 void LoadStringFd(int32_t fd, std::string &content)
370 {
371     if (fd <= 0) {
372         HDF_LOGW("invalid fd: %{public}d", fd);
373         return;
374     }
375 
376     const int32_t fileLength = lseek(fd, 0, SEEK_END);
377     if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
378         HDF_LOGW("invalid file length(%{public}d)!", fileLength);
379         return;
380     }
381     int32_t loc = lseek(fd, 0, SEEK_SET);
382     if (loc == -1) {
383         HDF_LOGE("lseek file to begin failed!");
384         return;
385     }
386     content.resize(fileLength);
387     const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
388     if (len <= 0) {
389         HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
390         content.clear();
391     }
392 }
393 
ReadWakeCount()394 std::string ReadWakeCount()
395 {
396     if (wakeupCountFd < 0) {
397         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
398     }
399     std::string wakeupCount;
400     LoadStringFd(wakeupCountFd, wakeupCount);
401 
402     return wakeupCount;
403 }
404 
WriteWakeCount(const std::string & count)405 bool WriteWakeCount(const std::string &count)
406 {
407     if (wakeupCountFd < 0) {
408         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
409     }
410     bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
411     return ret;
412 }
413 
LoadSystemInfo(const std::string & path,std::string & info)414 static void LoadSystemInfo(const std::string &path, std::string &info)
415 {
416     UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
417     std::string str;
418     if (fd >= 0) {
419         bool ret = LoadStringFromFd(fd, str);
420         if (!ret) {
421             str = "# Failed to read";
422         }
423     } else {
424         str = "# Failed to open";
425     }
426     info.append(path);
427     info.append(": " + str + "\n");
428 }
429 
PowerDump(std::string & info)430 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
431 {
432     std::string dumpInfo("");
433     LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
434     LoadSystemInfo(LOCK_PATH, dumpInfo);
435     LoadSystemInfo(UNLOCK_PATH, dumpInfo);
436     info = dumpInfo;
437 
438     return HDF_SUCCESS;
439 }
440 
HoldRunningLock(const RunningLockInfo & info)441 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
442 {
443     return RunningLockImpl::Hold(info, g_powerState);
444 }
445 
UnholdRunningLock(const RunningLockInfo & info)446 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
447 {
448     return RunningLockImpl::Unhold(info);
449 }
450 
HoldRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)451 int32_t PowerInterfaceImpl::HoldRunningLockExt(const RunningLockInfo &info,
452     uint64_t lockid, const std::string &bundleName)
453 {
454     HDF_LOGI("Background runningLock active, type=%{public}d name=%{public}s", info.type, info.name.c_str());
455     return RunningLockImpl::HoldLock(info, g_powerState, lockid, bundleName);
456 }
457 
UnholdRunningLockExt(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)458 int32_t PowerInterfaceImpl::UnholdRunningLockExt(const RunningLockInfo &info,
459     uint64_t lockid, const std::string &bundleName)
460 {
461     HDF_LOGI("Background runningLock inactive, type=%{public}d name=%{public}s", info.type, info.name.c_str());
462     return RunningLockImpl::UnholdLock(info, lockid, bundleName);
463 }
464 
GetWakeupReason(std::string & reason)465 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
466 {
467 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
468     auto& powerConfig = PowerConfig::GetInstance();
469     std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap= powerConfig.GetPowerSceneConfigMap();
470     std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find("wakeuo_cause");
471     if (it == sceneConfigMap.end()) {
472         HDF_LOGW("wakeuo_cause getPath does not exist");
473         return HDF_FAILURE;
474     }
475     std::string getPath = (it->second).getPath;
476     HDF_LOGI("getPath = %{public}s", getPath.c_str());
477 
478     UniqueFd wakeupCauseFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
479     if (wakeupCauseFd < 0) {
480         return HDF_FAILURE;
481     }
482     LoadStringFd(wakeupCauseFd, reason);
483     return HDF_SUCCESS;
484 #else
485     HDF_LOGW("wakrup cause path not config");
486     return HDF_FAILURE;
487 #endif
488 }
489 } // namespace V1_2
490 } // namespace Power
491 } // namespace HDI
492 } // namespace OHOS
493