• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 <atomic>
19 #include <hdf_base.h>
20 #include <file_ex.h>
21 #include <iremote_object.h>
22 #include <iproxy_broker.h>
23 #include <sys/eventfd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <chrono>
28 #include <condition_variable>
29 #include <mutex>
30 #include <cstdlib>
31 #include <thread>
32 #include "errors.h"
33 #include "hdf_sbuf.h"
34 #include "pubdef.h"
35 #include "securec.h"
36 #include "utils/hdf_log.h"
37 #include "hdf_device_desc.h"
38 #include "hdf_remote_service.h"
39 #include "unique_fd.h"
40 
41 namespace OHOS {
42 namespace HDI {
43 namespace Power {
44 namespace V1_0 {
45 static constexpr const int32_t MAX_FILE_LENGTH = 32 * 1024 * 1024;
46 static constexpr const char * const SUSPEND_STATE = "mem";
47 static constexpr const char * const SUSPEND_STATE_PATH = "/sys/power/state";
48 static constexpr const char * const LOCK_PATH = "/sys/power/wake_lock";
49 static constexpr const char * const UNLOCK_PATH = "/sys/power/wake_unlock";
50 static constexpr const char * const WAKEUP_COUNT_PATH = "/sys/power/wakeup_count";
51 static std::chrono::milliseconds waitTime_(100); // {100ms};
52 static std::mutex g_mutex;
53 static std::mutex g_suspendMutex;
54 static std::condition_variable g_suspendCv;
55 static std::unique_ptr<std::thread> g_daemon;
56 static std::atomic_bool g_suspending;
57 static std::atomic_bool g_suspendRetry;
58 static sptr<IPowerHdiCallback> g_callback;
59 static UniqueFd wakeupCountFd;
60 static void AutoSuspendLoop();
61 static int32_t DoSuspend();
62 static void LoadStringFd(int32_t fd, std::string& content);
63 static std::string ReadWakeCount();
64 static bool WriteWakeCount(const std::string& count);
65 static void NotifyCallback(int code);
66 namespace {
67     sptr<PowerInterfaceImpl::PowerDeathRecipient> g_deathRecipient = nullptr;
68     bool g_isHdiStart = false;
69 }
70 
PowerInterfaceImplGetInstance(void)71 extern "C" IPowerInterface *PowerInterfaceImplGetInstance(void)
72 {
73     return new (std::nothrow) PowerInterfaceImpl();
74 }
75 
RegisterCallback(const sptr<IPowerHdiCallback> & ipowerHdiCallback)76 int32_t PowerInterfaceImpl::RegisterCallback(const sptr<IPowerHdiCallback>& ipowerHdiCallback)
77 {
78     std::lock_guard<std::mutex> lock(g_mutex);
79     if (!g_isHdiStart) {
80         g_callback = ipowerHdiCallback;
81         if (g_callback == nullptr) {
82             UnRegister();
83             return HDF_SUCCESS;
84         }
85         g_deathRecipient = new PowerDeathRecipient(this);
86         if (g_deathRecipient == nullptr) {
87             return HDF_FAILURE;
88         }
89         AddPowerDeathRecipient(g_callback);
90         g_isHdiStart = true;
91     }
92     return HDF_SUCCESS;
93 }
94 
UnRegister()95 int32_t PowerInterfaceImpl::UnRegister()
96 {
97     HDF_LOGI("UnRegister");
98     RemovePowerDeathRecipient(g_callback);
99     g_callback = nullptr;
100     return HDF_SUCCESS;
101 }
102 
StartSuspend()103 int32_t PowerInterfaceImpl::StartSuspend()
104 {
105     std::lock_guard<std::mutex> lock(g_mutex);
106     g_suspendRetry = true;
107     if (g_suspending) {
108         g_suspendCv.notify_one();
109         return HDF_SUCCESS;
110     }
111     g_suspending = true;
112     g_daemon = std::make_unique<std::thread>(&AutoSuspendLoop);
113     g_daemon->detach();
114     return HDF_SUCCESS;
115 }
116 
AutoSuspendLoop()117 void AutoSuspendLoop()
118 {
119     auto suspendLock = std::unique_lock(g_suspendMutex);
120     while (true) {
121         std::this_thread::sleep_for(waitTime_);
122 
123         const std::string wakeupCount = ReadWakeCount();
124         if (wakeupCount.empty()) {
125             continue;
126         }
127         if (!g_suspendRetry) {
128             g_suspendCv.wait(suspendLock);
129         }
130         if (!WriteWakeCount(wakeupCount)) {
131             continue;
132         }
133 
134         NotifyCallback(CMD_ON_SUSPEND);
135         DoSuspend();
136         NotifyCallback(CMD_ON_WAKEUP);
137     }
138     g_suspending = false;
139     g_suspendRetry = false;
140 }
141 
DoSuspend()142 int32_t DoSuspend()
143 {
144     std::lock_guard<std::mutex> lock(g_mutex);
145     UniqueFd suspendStateFd(TEMP_FAILURE_RETRY(open(SUSPEND_STATE_PATH, O_RDWR | O_CLOEXEC)));
146     if (suspendStateFd < 0) {
147         return HDF_FAILURE;
148     }
149     bool ret = false;
150     do {
151         ret = SaveStringToFd(suspendStateFd, SUSPEND_STATE);
152     } while (!ret && (errno == EINTR || errno == EBUSY));
153 
154     if (!ret) {
155         return HDF_FAILURE;
156     }
157     return HDF_SUCCESS;
158 }
159 
NotifyCallback(int code)160 void NotifyCallback(int code)
161 {
162     if (g_callback == nullptr) {
163         return;
164     }
165     switch (code) {
166         case CMD_ON_SUSPEND:
167             g_callback->OnSuspend();
168             break;
169         case CMD_ON_WAKEUP:
170             g_callback->OnWakeup();
171             break;
172     }
173 }
174 
StopSuspend()175 int32_t PowerInterfaceImpl::StopSuspend()
176 {
177     g_suspendRetry = false;
178 
179     return HDF_SUCCESS;
180 }
181 
ForceSuspend()182 int32_t PowerInterfaceImpl::ForceSuspend()
183 {
184     g_suspendRetry = false;
185 
186     NotifyCallback(CMD_ON_SUSPEND);
187     DoSuspend();
188     NotifyCallback(CMD_ON_WAKEUP);
189     return HDF_SUCCESS;
190 }
191 
SuspendBlock(const std::string & name)192 int32_t PowerInterfaceImpl::SuspendBlock(const std::string& name)
193 {
194     std::lock_guard<std::mutex> lock(g_mutex);
195     if (name.empty()) {
196         return HDF_ERR_INVALID_PARAM;
197     }
198     UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
199     bool ret = SaveStringToFd(fd, name);
200     if (!ret) {
201         return HDF_FAILURE;
202     }
203     return HDF_SUCCESS;
204 }
205 
SuspendUnblock(const std::string & name)206 int32_t PowerInterfaceImpl::SuspendUnblock(const std::string& name)
207 {
208     std::lock_guard<std::mutex> lock(g_mutex);
209     if (name.empty()) {
210         return HDF_ERR_INVALID_PARAM;
211     }
212     UniqueFd fd(TEMP_FAILURE_RETRY(open(UNLOCK_PATH, O_RDWR | O_CLOEXEC)));
213     bool ret = SaveStringToFd(fd, name);
214     if (!ret) {
215         return HDF_FAILURE;
216     }
217     return HDF_SUCCESS;
218 }
219 
AddPowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)220 int32_t PowerInterfaceImpl::AddPowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
221 {
222     HDF_LOGI("AddPowerDeathRecipient");
223     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
224     bool result = remote->AddDeathRecipient(g_deathRecipient);
225     if (!result) {
226         HDF_LOGI("AddPowerDeathRecipient fail");
227         return HDF_FAILURE;
228     }
229     return HDF_SUCCESS;
230 }
231 
RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> & callback)232 int32_t PowerInterfaceImpl::RemovePowerDeathRecipient(const sptr<IPowerHdiCallback> &callback)
233 {
234     HDF_LOGI("RemovePowerDeathRecipient");
235     const sptr<IRemoteObject> &remote = OHOS::HDI::hdi_objcast<IPowerHdiCallback>(callback);
236     bool result = remote->RemoveDeathRecipient(g_deathRecipient);
237     if (!result) {
238         HDF_LOGI("RemovePowerDeathRecipient fail");
239         return HDF_FAILURE;
240     }
241     return HDF_SUCCESS;
242 }
243 
OnRemoteDied(const wptr<IRemoteObject> & object)244 void PowerInterfaceImpl::PowerDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
245 {
246     powerInterfaceImpl_->UnRegister();
247 }
248 
LoadStringFd(int32_t fd,std::string & content)249 void LoadStringFd(int32_t fd, std::string& content)
250 {
251     if (fd <= 0) {
252         HDF_LOGW("invalid fd: %{public}d", fd);
253         return;
254     }
255 
256     const int32_t fileLength = lseek(fd, 0, SEEK_END);
257     if (fileLength > MAX_FILE_LENGTH || fileLength <= 0) {
258         HDF_LOGW("invalid file length(%{public}d)!", fileLength);
259         return;
260     }
261     int32_t loc = lseek(fd, 0, SEEK_SET);
262     if (loc == -1) {
263         HDF_LOGE("lseek file to begin failed!");
264         return;
265     }
266     content.resize(fileLength);
267     const int32_t len = static_cast<int32_t>(read(fd, content.data(), fileLength));
268     if (len <= 0) {
269         HDF_LOGW("the length read from file is failed, len: %{public}d, fileLen: %{public}d",
270             len, fileLength);
271         content.clear();
272     }
273 }
274 
ReadWakeCount()275 std::string ReadWakeCount()
276 {
277     if (wakeupCountFd < 0) {
278         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
279     }
280     std::string wakeupCount;
281     LoadStringFd(wakeupCountFd, wakeupCount);
282 
283     return wakeupCount;
284 }
285 
WriteWakeCount(const std::string & count)286 bool WriteWakeCount(const std::string& count)
287 {
288     if (wakeupCountFd < 0) {
289         wakeupCountFd = UniqueFd(TEMP_FAILURE_RETRY(open(WAKEUP_COUNT_PATH, O_RDWR | O_CLOEXEC)));
290     }
291     bool ret = SaveStringToFd(wakeupCountFd, count.c_str());
292     return ret;
293 }
294 
LoadSystemInfo(const std::string & path,std::string & info)295 static void LoadSystemInfo(const std::string& path, std::string& info)
296 {
297     UniqueFd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDWR | O_CLOEXEC)));
298     std::string str;
299     if (fd >= 0) {
300         bool ret = LoadStringFromFd(fd, str);
301         if (!ret) {
302             str = "# Failed to read";
303         }
304     } else {
305         str = "# Failed to open";
306     }
307     info.append(path);
308     info.append(": " + str + "\n");
309 }
310 
PowerDump(std::string & info)311 int32_t PowerInterfaceImpl::PowerDump(std::string& info)
312 {
313     std::string dumpInfo("");
314     LoadSystemInfo(SUSPEND_STATE_PATH, dumpInfo);
315     LoadSystemInfo(WAKEUP_COUNT_PATH, dumpInfo);
316     LoadSystemInfo(LOCK_PATH, dumpInfo);
317     LoadSystemInfo(UNLOCK_PATH, dumpInfo);
318     info = dumpInfo;
319 
320     return HDF_SUCCESS;
321 }
322 } // V1_0
323 } // Power
324 } // HDI
325 } // OHOS
326