• 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_1/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_1 {
51 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
52 static constexpr const char * const SUSPEND_STATE = "mem";
53 static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state";
54 static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock";
55 static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock";
56 static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count";
57 static std::chrono::milliseconds waitTime_(1000); // {1000ms};
58 static std::mutex g_mutex;
59 static std::mutex g_suspendMutex;
60 static std::mutex g_forceMutex;
61 static std::condition_variable g_suspendCv;
62 static std::unique_ptr<std::thread> g_daemon;
63 static std::atomic_bool g_suspending;
64 static std::atomic_bool g_suspendRetry;
65 static std::atomic_bool g_forceSuspendStart;
66 static sptr<IPowerHdiCallback> g_callback;
67 static UniqueFd wakeupCountFd;
68 static PowerHdfState g_powerState {PowerHdfState::AWAKE};
69 static void AutoSuspendLoop();
70 static int32_t DoSuspend();
71 static void LoadStringFd(int32_t fd, std::string &content);
72 static std::string ReadWakeCount();
73 static bool WriteWakeCount(const std::string &count);
74 static void NotifyCallback(int code);
75 namespace {
76 sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
77 bool g_isHdiStart = false;
78 } // namespace
79 
PowerInterfaceImplGetInstance(void)80 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
81 {
82     using OHOS::HDI::Power::V1_1::PowerInterfaceImpl;
83     PowerInterfaceImpl *service = new (std::nothrow) PowerInterfaceImpl();
84     if (service == nullptr) {
85         return nullptr;
86     }
87 
88     if (service->Init() != HDF_SUCCESS) {
89         delete service;
90         return nullptr;
91     }
92     return service;
93 }
94 
Init()95 int32_t PowerInterfaceImpl::Init()
96 {
97 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
98     auto& powerConfig = PowerConfig::GetInstance();
99     powerConfig.ParseConfig();
100 #endif
101     return HDF_SUCCESS;
102 }
103 
RegisterCallback(const sptr<IPowerHdiCallback> & ipowerHdiCallback)104 int32_t PowerInterfaceImpl::RegisterCallback(const sptr<IPowerHdiCallback> &ipowerHdiCallback)
105 {
106     std::lock_guard<std::mutex> lock(g_mutex);
107     if (!g_isHdiStart) {
108         g_callback = ipowerHdiCallback;
109         if (g_callback == nullptr) {
110             UnRegister();
111             return HDF_SUCCESS;
112         }
113         g_deathRecipient = new PowerDeathRecipient(this);
114         if (g_deathRecipient == nullptr) {
115             return HDF_FAILURE;
116         }
117         AddPowerDeathRecipient(g_callback);
118         g_isHdiStart = true;
119     }
120 
121     return HDF_SUCCESS;
122 }
123 
UnRegister()124 int32_t PowerInterfaceImpl::UnRegister()
125 {
126     HDF_LOGI("UnRegister");
127     RemovePowerDeathRecipient(g_callback);
128     g_callback = nullptr;
129     g_isHdiStart = false;
130     return HDF_SUCCESS;
131 }
132 
StartSuspend()133 int32_t PowerInterfaceImpl::StartSuspend()
134 {
135     HDF_LOGI("start suspend");
136     std::lock_guard<std::mutex> lock(g_mutex);
137     g_suspendRetry = true;
138     if (g_suspending) {
139         g_powerState = PowerHdfState::INACTIVE;
140         g_suspendCv.notify_one();
141         return HDF_SUCCESS;
142     }
143     g_suspending = true;
144     g_daemon = std::make_unique<std::thread>(&AutoSuspendLoop);
145     g_daemon->detach();
146     return HDF_SUCCESS;
147 }
148 
AutoSuspendLoop()149 void AutoSuspendLoop()
150 {
151     auto suspendLock = std::unique_lock(g_suspendMutex);
152     while (true) {
153         std::this_thread::sleep_for(waitTime_);
154 
155         const std::string wakeupCount = ReadWakeCount();
156         if (wakeupCount.empty()) {
157             continue;
158         }
159         if (!g_suspendRetry) {
160             g_suspendCv.wait(suspendLock);
161         }
162         if (!WriteWakeCount(wakeupCount)) {
163             continue;
164         }
165 
166         NotifyCallback(CMD_ON_SUSPEND);
167         g_powerState = PowerHdfState::SLEEP;
168         DoSuspend();
169         g_powerState = PowerHdfState::AWAKE;
170         NotifyCallback(CMD_ON_WAKEUP);
171     }
172     g_suspending = false;
173     g_suspendRetry = false;
174 }
175 
DoSuspend()176 int32_t DoSuspend()
177 {
178     std::lock_guard<std::mutex> lock(g_mutex);
179     UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
180     if (suspendStateFd < 0) {
181         return HDF_FAILURE;
182     }
183     bool ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
184     if (!ret) {
185         HDF_LOGE("DoSuspend fail");
186         return HDF_FAILURE;
187     }
188     return HDF_SUCCESS;
189 }
190 
NotifyCallback(int code)191 void NotifyCallback(int code)
192 {
193     if (g_callback == nullptr) {
194         return;
195     }
196     switch (code) {
197         case CMD_ON_SUSPEND:
198             g_callback->OnSuspend();
199             break;
200         case CMD_ON_WAKEUP:
201             g_callback->OnWakeup();
202             break;
203         default:
204             break;
205     }
206 }
207 
StopSuspend()208 int32_t PowerInterfaceImpl::StopSuspend()
209 {
210     HDF_LOGI("stop suspend");
211     std::lock_guard<std::mutex> lock(g_forceMutex);
212     g_forceSuspendStart = false;
213     g_suspendRetry = false;
214     g_powerState = PowerHdfState::AWAKE;
215     return HDF_SUCCESS;
216 }
217 
ForceSuspend()218 int32_t PowerInterfaceImpl::ForceSuspend()
219 {
220     HDF_LOGI("force suspend");
221     {
222         std::lock_guard<std::mutex> lock(g_forceMutex);
223         g_forceSuspendStart = true;
224         g_suspendRetry = false;
225     }
226 
227     NotifyCallback(CMD_ON_SUSPEND);
228     g_powerState = PowerHdfState::SLEEP;
229     DoSuspend();
230     g_powerState = PowerHdfState::AWAKE;
231     NotifyCallback(CMD_ON_WAKEUP);
232 
233     std::lock_guard<std::mutex> lock(g_forceMutex);
234     if (g_forceSuspendStart) {
235         StartSuspend();
236     }
237     return HDF_SUCCESS;
238 }
239 
SuspendBlock(const std::string & name)240 int32_t PowerInterfaceImpl::SuspendBlock(const std::string &name)
241 {
242     std::lock_guard<std::mutex> lock(g_mutex);
243     if (name.empty()) {
244         return HDF_ERR_INVALID_PARAM;
245     }
246     UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
247     bool ret = SaveStringToFd(fd, name);
248     if (!ret) {
249         return HDF_FAILURE;
250     }
251     return HDF_SUCCESS;
252 }
253 
SuspendUnblock(const std::string & name)254 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string &name)
255 {
256     std::lock_guard<std::mutex> lock(g_mutex);
257     if (name.empty()) {
258         return HDF_ERR_INVALID_PARAM;
259     }
260     UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
261     bool ret = SaveStringToFd(fd, name);
262     if (!ret) {
263         return HDF_FAILURE;
264     }
265     return HDF_SUCCESS;
266 }
267 
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)268 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
269 {
270     HDF_LOGI("AddPowerDeathRecipient");
271     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
272     bool result = remote->AddDeathRecipient(g_deathRecipient);
273     if (!result) {
274         HDF_LOGI("AddPowerDeathRecipient fail");
275         return HDF_FAILURE;
276     }
277     return HDF_SUCCESS;
278 }
279 
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)280 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
281 {
282     HDF_LOGI("RemovePowerDeathRecipient");
283     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
284     bool result = remote->RemoveDeathRecipient(g_deathRecipient);
285     if (!result) {
286         HDF_LOGI("RemovePowerDeathRecipient fail");
287         return HDF_FAILURE;
288     }
289     return HDF_SUCCESS;
290 }
291 
OnRemoteDied(const wptr<IRemoteObject> & object)292 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
293 {
294     HDF_LOGI("PowerDeathRecipient OnRemoteDied");
295     powerInterfaceImpl_->UnRegister();
296     RunningLockImpl::Clean();
297 }
298 
LoadStringFd(int32_t fd,std::string & content)299 void LoadStringFd(int32_t fd, std::string &content)
300 {
301     if (fd <= 0) {
302         HDF_LOGW("invalid fd: %{public}d", fd);
303         return;
304     }
305 
306     const int32_t fileLength = lseek(fd, 0, SEEK_END);
307     if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
308         HDF_LOGW("invalid file length(%{public}d)!", fileLength);
309         return;
310     }
311     int32_t loc = lseek(fd, 0, SEEK_SET);
312     if (loc == -1) {
313         HDF_LOGE("lseek file to begin failed!");
314         return;
315     }
316     content.resize(fileLength);
317     const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
318     if (len <= 0) {
319         HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d", len, fileLength);
320         content.clear();
321     }
322 }
323 
ReadWakeCount()324 std::string ReadWakeCount()
325 {
326     if (wakeupCountFd < 0) {
327         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
328     }
329     std::string wakeupCount;
330     LoadStringFd(wakeupCountFd, wakeupCount);
331 
332     return wakeupCount;
333 }
334 
WriteWakeCount(const std::string & count)335 bool WriteWakeCount(const std::string &count)
336 {
337     if (wakeupCountFd < 0) {
338         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
339     }
340     bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
341     return ret;
342 }
343 
LoadSystemInfo(const std::string & path,std::string & info)344 static void LoadSystemInfo(const std::string &path, std::string &info)
345 {
346     UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
347     std::string str;
348     if (fd >= 0) {
349         bool ret = LoadStringFromFd(fd, str);
350         if (!ret) {
351             str = "# Failed to read";
352         }
353     } else {
354         str = "# Failed to open";
355     }
356     info.append(path);
357     info.append(": " + str + "\n");
358 }
359 
PowerDump(std::string & info)360 int32_t PowerInterfaceImpl::PowerDump(std::string &info)
361 {
362     std::string dumpInfo("");
363     LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
364     LoadSystemInfo(LOCK_PATH, dumpInfo);
365     LoadSystemInfo(UNLOCK_PATH, dumpInfo);
366     info = dumpInfo;
367 
368     return HDF_SUCCESS;
369 }
370 
HoldRunningLock(const RunningLockInfo & info)371 int32_t PowerInterfaceImpl::HoldRunningLock(const RunningLockInfo &info)
372 {
373     return RunningLockImpl::Hold(info, g_powerState);
374 }
375 
UnholdRunningLock(const RunningLockInfo & info)376 int32_t PowerInterfaceImpl::UnholdRunningLock(const RunningLockInfo &info)
377 {
378     return RunningLockImpl::Unhold(info);
379 }
380 
GetWakeupReason(std::string & reason)381 int32_t PowerInterfaceImpl::GetWakeupReason(std::string &reason)
382 {
383 #ifdef DRIVER_PERIPHERAL_POWER_WAKEUP_CAUSE_PATH
384     auto& powerConfig = PowerConfig::GetInstance();
385     std::map<std::string, PowerConfig::PowerSceneConfig> sceneConfigMap= powerConfig.GetPowerSceneConfigMap();
386     std::map<std::string, PowerConfig::PowerSceneConfig>::iterator it = sceneConfigMap.find("wakeuo_cause");
387     if (it == sceneConfigMap.end()) {
388         HDF_LOGW("wakeuo_cause getPath does not exist");
389         return HDF_FAILURE;
390     }
391     std::string getPath = (it->second).getPath;
392     HDF_LOGI("getPath = %{public}s", getPath.c_str());
393 
394     UniqueFd wakeupCauseFd(TEMP_FAILURE_RETRY(open(getPath.c_str(), O_RDONLY | O_CLOEXEC)));
395     if (wakeupCauseFd < 0) {
396         return HDF_FAILURE;
397     }
398     LoadStringFd(wakeupCauseFd, reason);
399     return HDF_SUCCESS;
400 #else
401     HDF_LOGW("wakrup cause path not config");
402     return HDF_FAILURE;
403 #endif
404 }
405 } // namespace V1_1
406 } // namespace Power
407 } // namespace HDI
408 } // namespace OHOS
409