1 /*
2 * Copyright (C) 2023-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 <string>
17 #include <cinttypes>
18 #include <algorithm>
19
20 #include "timer_proxy.h"
21 #include "time_hilog.h"
22
23 namespace OHOS {
24 namespace MiscServices {
25 using namespace std::chrono;
26 using namespace OHOS::AppExecFwk;
27
28 namespace {
29 constexpr int MILLI_TO_SECOND = 1000;
30 }
31
32 IMPLEMENT_SINGLE_INSTANCE(TimerProxy)
33
RemoveProxy(uint64_t timerNumber, int32_t uid)34 void TimerProxy::RemoveProxy(uint64_t timerNumber, int32_t uid)
35 {
36 std::lock_guard<std::mutex> lock(proxyMutex_);
37 auto itMap = proxyMap_.find(uid);
38 if (itMap != proxyMap_.end()) {
39 auto alarms = &itMap->second;
40 for (auto itAlarm = alarms->begin(); itAlarm != alarms->end();) {
41 if ((*itAlarm)->id == timerNumber) {
42 itAlarm = alarms->erase(itAlarm);
43 } else {
44 itAlarm++;
45 }
46 }
47 if (alarms->empty()) {
48 proxyMap_.erase(uid);
49 }
50 }
51 }
52
RemovePidProxy(uint64_t timerNumber, int pid)53 void TimerProxy::RemovePidProxy(uint64_t timerNumber, int pid)
54 {
55 std::lock_guard<std::mutex> lock(proxyPidMutex_);
56 auto itMap = proxyPidMap_.find(pid);
57 if (itMap != proxyPidMap_.end()) {
58 auto alarms = &itMap->second;
59 for (auto itAlarm = alarms->begin(); itAlarm != alarms->end();) {
60 if ((*itAlarm)->id == timerNumber) {
61 itAlarm = alarms->erase(itAlarm);
62 } else {
63 itAlarm++;
64 }
65 }
66 if (alarms->empty()) {
67 proxyPidMap_.erase(pid);
68 }
69 }
70 }
71
CallbackAlarmIfNeed(const std::shared_ptr<TimerInfo> &alarm)72 int32_t TimerProxy::CallbackAlarmIfNeed(const std::shared_ptr<TimerInfo> &alarm)
73 {
74 if (alarm == nullptr) {
75 TIME_HILOGE(TIME_MODULE_SERVICE, "callback alarm is nullptr!");
76 return E_TIME_NULLPTR;
77 }
78
79 int uid = alarm->uid;
80 int pid = alarm->pid;
81 {
82 std::lock_guard<std::mutex> lock(proxyMutex_);
83 auto uidIt = proxyUids_.find(uid);
84 if (uidIt != proxyUids_.end()) {
85 TIME_HILOGD(TIME_MODULE_SERVICE, "Alarm is uid proxy!");
86 auto itMap = proxyMap_.find(uid);
87 if (itMap == proxyMap_.end()) {
88 std::vector<std::shared_ptr<TimerInfo>> timeInfoVec;
89 timeInfoVec.push_back(alarm);
90 proxyMap_[uid] = timeInfoVec;
91 } else {
92 std::vector<std::shared_ptr<TimerInfo>> timeInfoVec = itMap->second;
93 timeInfoVec.push_back(alarm);
94 proxyMap_[uid] = timeInfoVec;
95 }
96 return E_TIME_OK;
97 }
98 }
99 {
100 std::lock_guard<std::mutex> lock(proxyPidMutex_);
101 auto pidIt = proxyPids_.find(pid);
102 if (pidIt != proxyPids_.end()) {
103 TIME_HILOGD(TIME_MODULE_SERVICE, "Alarm is pid proxy!");
104 auto itMap = proxyPidMap_.find(pid);
105 if (itMap == proxyPidMap_.end()) {
106 std::vector<std::shared_ptr<TimerInfo>> timeInfoVec;
107 timeInfoVec.push_back(alarm);
108 proxyPidMap_[pid] = timeInfoVec;
109 } else {
110 std::vector<std::shared_ptr<TimerInfo>> timeInfoVec = itMap->second;
111 timeInfoVec.push_back(alarm);
112 proxyPidMap_[pid] = timeInfoVec;
113 }
114 return E_TIME_OK;
115 }
116 }
117 int32_t ret = alarm->callback(alarm->id);
118 TIME_SIMPLIFY_HILOGI(TIME_MODULE_SERVICE, "cb: %{public}" PRId64 " ret: %{public}d",
119 alarm->id, ret);
120 return ret;
121 }
122
ProxyTimer(int32_t uid, bool isProxy, bool needRetrigger, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)123 bool TimerProxy::ProxyTimer(int32_t uid, bool isProxy, bool needRetrigger,
124 const std::chrono::steady_clock::time_point &now,
125 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
126 {
127 TIME_HILOGD(TIME_MODULE_SERVICE, "start. uid=%{public}d, isProxy=%{public}u, needRetrigger=%{public}u",
128 uid, isProxy, needRetrigger);
129 std::lock_guard<std::mutex> lockProxy(proxyMutex_);
130 if (isProxy) {
131 UpdateProxyWhenElapsedForProxyUidMap(uid, now, insertAlarmCallback);
132 return true;
133 }
134 if (!RestoreProxyWhenElapsedForProxyUidMap(uid, now, insertAlarmCallback)) {
135 TIME_HILOGE(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list." PRId64 "", uid);
136 return false;
137 }
138
139 if (!needRetrigger) {
140 TIME_HILOGI(TIME_MODULE_SERVICE, "ProxyTimer doesn't need retrigger, clear all callbacks!");
141 proxyMap_.erase(uid);
142 return true;
143 }
144 auto itMap = proxyMap_.find(uid);
145 if (itMap != proxyMap_.end()) {
146 auto timeInfoVec = itMap->second;
147 for (const auto& alarm : timeInfoVec) {
148 if (!alarm->callback) {
149 TIME_HILOGE(TIME_MODULE_SERVICE, "ProxyTimer Callback is nullptr!");
150 continue;
151 }
152 alarm->callback(alarm->id);
153 TIME_HILOGD(TIME_MODULE_SERVICE, "Shut down proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
154 uid, alarm->id);
155 }
156 timeInfoVec.clear();
157 proxyMap_.erase(uid);
158 }
159 return true;
160 }
161
PidProxyTimer(int pid, bool isProxy, bool needRetrigger, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)162 bool TimerProxy::PidProxyTimer(int pid, bool isProxy, bool needRetrigger,
163 const std::chrono::steady_clock::time_point &now,
164 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
165 {
166 TIME_HILOGD(TIME_MODULE_SERVICE, "start. pid=%{public}d, isProxy=%{public}u, needRetrigger=%{public}u",
167 pid, isProxy, needRetrigger);
168
169 std::lock_guard<std::mutex> lockProxy(proxyPidMutex_);
170 if (isProxy) {
171 UpdateProxyWhenElapsedForProxyPidMap(pid, now, insertAlarmCallback);
172 return true;
173 }
174
175 if (!RestoreProxyWhenElapsedForProxyPidMap(pid, now, insertAlarmCallback)) {
176 TIME_HILOGE(TIME_MODULE_SERVICE, "Pid: %{public}d doesn't exist in the proxy list." PRId64 "", pid);
177 return false;
178 }
179
180 if (!needRetrigger) {
181 TIME_HILOGI(TIME_MODULE_SERVICE, "ProxyTimer doesn't need retrigger, clear all callbacks!");
182 proxyPidMap_.erase(pid);
183 return true;
184 }
185
186 auto itMap = proxyPidMap_.find(pid);
187 if (itMap != proxyPidMap_.end()) {
188 auto timeInfoVec = itMap->second;
189 for (const auto& alarm : timeInfoVec) {
190 if (!alarm->callback) {
191 TIME_HILOGE(TIME_MODULE_SERVICE, "ProxyTimer Callback is nullptr!");
192 continue;
193 }
194 alarm->callback(alarm->id);
195 TIME_HILOGD(TIME_MODULE_SERVICE, "Shut down proxy, proxyPid: %{public}d, alarmId: %{public}" PRId64 "",
196 pid, alarm->id);
197 }
198 timeInfoVec.clear();
199 proxyPidMap_.erase(pid);
200 }
201 return true;
202 }
203
AdjustTimer(bool isAdjust, uint32_t interval, const std::chrono::steady_clock::time_point &now, std::function<void(AdjustTimerCallback adjustTimer)> updateTimerDeliveries)204 bool TimerProxy::AdjustTimer(bool isAdjust, uint32_t interval,
205 const std::chrono::steady_clock::time_point &now,
206 std::function<void(AdjustTimerCallback adjustTimer)> updateTimerDeliveries)
207 {
208 std::lock_guard<std::mutex> lockProxy(adjustMutex_);
209 TIME_HILOGD(TIME_MODULE_SERVICE, "adjust timer state: %{public}d, interval: %{public}d", isAdjust, interval);
210 auto callback = [this, isAdjust, interval, now] (std::shared_ptr<TimerInfo> timer) {
211 if (timer == nullptr) {
212 TIME_HILOGE(TIME_MODULE_SERVICE, "adjust timer is nullptr!");
213 return false;
214 }
215 return isAdjust ? UpdateAdjustWhenElapsed(now, interval, timer) : RestoreAdjustWhenElapsed(timer);
216 };
217 updateTimerDeliveries(callback);
218 if (!isAdjust) {
219 adjustTimers_.clear();
220 }
221 return true;
222 }
223
UpdateAdjustWhenElapsed(const std::chrono::steady_clock::time_point &now, uint32_t interval, std::shared_ptr<TimerInfo> &timer)224 bool TimerProxy::UpdateAdjustWhenElapsed(const std::chrono::steady_clock::time_point &now,
225 uint32_t interval, std::shared_ptr<TimerInfo> &timer)
226 {
227 if (IsTimerExemption(timer)) {
228 TIME_HILOGD(TIME_MODULE_SERVICE, "adjust exemption timer bundleName: %{public}s",
229 timer->bundleName.c_str());
230 return false;
231 }
232 TIME_HILOGD(TIME_MODULE_SERVICE, "adjust single time id: %{public}" PRId64 ", "
233 "uid: %{public}d, bundleName: %{public}s",
234 timer->id, timer->uid, timer->bundleName.c_str());
235 adjustTimers_.push_back(timer);
236 return timer->AdjustTimer(now, interval);
237 }
238
RestoreAdjustWhenElapsed(std::shared_ptr<TimerInfo> &timer)239 bool TimerProxy::RestoreAdjustWhenElapsed(std::shared_ptr<TimerInfo> &timer)
240 {
241 auto it = std::find_if(adjustTimers_.begin(),
242 adjustTimers_.end(),
243 [&timer](const std::shared_ptr<TimerInfo> &compareTimer) {
244 return compareTimer->id == timer->id;
245 });
246 if (it == adjustTimers_.end()) {
247 return false;
248 }
249 return timer->RestoreAdjustTimer();
250 }
251
SetTimerExemption(const std::unordered_set<std::string> &nameArr, bool isExemption)252 bool TimerProxy::SetTimerExemption(const std::unordered_set<std::string> &nameArr, bool isExemption)
253 {
254 std::lock_guard<std::mutex> lockProxy(adjustMutex_);
255 bool isChanged = false;
256 if (!isExemption) {
257 for (const auto &name : nameArr) {
258 adjustExemptionList_.erase(name);
259 }
260 return isChanged;
261 }
262 adjustExemptionList_.insert(nameArr.begin(), nameArr.end());
263 return isChanged;
264 }
265
IsTimerExemption(std::shared_ptr<TimerInfo> timer)266 bool TimerProxy::IsTimerExemption(std::shared_ptr<TimerInfo> timer)
267 {
268 if (adjustExemptionList_.find(timer->bundleName) != adjustExemptionList_.end()
269 && timer->windowLength == milliseconds::zero()) {
270 return true;
271 }
272 return false;
273 }
274
ResetProxyMaps()275 void TimerProxy::ResetProxyMaps()
276 {
277 std::lock_guard<std::mutex> lock(proxyMutex_);
278 for (auto it = proxyMap_.begin(); it != proxyMap_.end(); it++) {
279 auto timeInfoVec = it->second;
280 for (const auto& alarm : timeInfoVec) {
281 if (!alarm->callback) {
282 TIME_HILOGE(TIME_MODULE_SERVICE, "Callback is nullptr!");
283 continue;
284 }
285 alarm->callback(alarm->id);
286 TIME_HILOGD(TIME_MODULE_SERVICE, "Reset all proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
287 it->first, alarm->id);
288 }
289 timeInfoVec.clear();
290 }
291 proxyMap_.clear();
292 }
293
ResetProxyPidMaps()294 void TimerProxy::ResetProxyPidMaps()
295 {
296 std::lock_guard<std::mutex> lock(proxyPidMutex_);
297 for (auto it = proxyPidMap_.begin(); it != proxyPidMap_.end(); it++) {
298 auto timeInfoVec = it->second;
299 for (const auto& alarm : timeInfoVec) {
300 if (!alarm->callback) {
301 TIME_HILOGE(TIME_MODULE_SERVICE, "Callback is nullptr!");
302 continue;
303 }
304 alarm->callback(alarm->id);
305 TIME_HILOGD(TIME_MODULE_SERVICE, "Reset all proxy, proxyPid: %{public}d, alarmId: %{public}" PRId64 "",
306 it->first, alarm->id);
307 }
308 timeInfoVec.clear();
309 }
310 proxyPidMap_.clear();
311 }
312
ResetAllProxy(const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)313 bool TimerProxy::ResetAllProxy(const std::chrono::steady_clock::time_point &now,
314 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
315 {
316 TIME_HILOGD(TIME_MODULE_SERVICE, "start");
317 ResetProxyMaps();
318 ResetAllProxyWhenElapsed(now, insertAlarmCallback);
319 ResetProxyPidMaps();
320 ResetAllPidProxyWhenElapsed(now, insertAlarmCallback);
321 return true;
322 }
323
EraseTimerFromProxyUidMap(const uint64_t id, const uint32_t uid)324 void TimerProxy::EraseTimerFromProxyUidMap(const uint64_t id, const uint32_t uid)
325 {
326 TIME_HILOGD(TIME_MODULE_SERVICE, "erase timer from proxy timer map, id=%{public}" PRId64 ", uid=%{public}u",
327 id, uid);
328 std::lock_guard<std::mutex> lock(proxyMutex_);
329 auto it = proxyUids_.find(uid);
330 if (it != proxyUids_.end()) {
331 it->second.erase(id);
332 }
333 }
334
EraseTimerFromProxyPidMap(const uint64_t id, const int pid)335 void TimerProxy::EraseTimerFromProxyPidMap(const uint64_t id, const int pid)
336 {
337 TIME_HILOGD(TIME_MODULE_SERVICE, "erase timer from proxy timer map, id=%{public}" PRId64 ", pid=%{public}u",
338 id, pid);
339 std::lock_guard<std::mutex> lock(proxyPidMutex_);
340 auto it = proxyPids_.find(pid);
341 if (it != proxyPids_.end()) {
342 it->second.erase(id);
343 }
344 }
345
EraseAlarmItem( const uint64_t id, std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> &idAlarmsMap)346 void TimerProxy::EraseAlarmItem(
347 const uint64_t id, std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> &idAlarmsMap)
348 {
349 auto itAlarms = idAlarmsMap.find(id);
350 if (itAlarms != idAlarmsMap.end()) {
351 TIME_HILOGD(TIME_MODULE_SERVICE, "timer already exists, id=%{public}" PRId64 "", id);
352 idAlarmsMap.erase(itAlarms);
353 }
354 }
355
RecordUidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)356 void TimerProxy::RecordUidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)
357 {
358 if (isRebatched) {
359 TIME_HILOGD(TIME_MODULE_SERVICE, "Record uid timer info map, isRebatched: %{public}d", isRebatched);
360 return;
361 }
362 if (alarm == nullptr) {
363 TIME_HILOGE(TIME_MODULE_SERVICE, "record uid timer map alarm is nullptr!");
364 return;
365 }
366
367 std::lock_guard<std::mutex> lock(uidTimersMutex_);
368 auto it = uidTimersMap_.find(alarm->uid);
369 if (it == uidTimersMap_.end()) {
370 std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> idAlarmsMap;
371 idAlarmsMap.insert(std::make_pair(alarm->id, alarm));
372 uidTimersMap_.insert(std::make_pair(alarm->uid, idAlarmsMap));
373 return;
374 }
375
376 EraseAlarmItem(alarm->id, it->second);
377 it->second.insert(std::make_pair(alarm->id, alarm));
378 }
379
RecordPidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)380 void TimerProxy::RecordPidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)
381 {
382 if (isRebatched) {
383 TIME_HILOGD(TIME_MODULE_SERVICE, "Record pid timer info map, isRebatched: %{public}d", isRebatched);
384 return;
385 }
386 if (alarm == nullptr) {
387 TIME_HILOGE(TIME_MODULE_SERVICE, "record pid timer map alarm is nullptr!");
388 return;
389 }
390
391 std::lock_guard<std::mutex> lock(pidTimersMutex_);
392 auto it = pidTimersMap_.find(alarm->pid);
393 if (it == pidTimersMap_.end()) {
394 std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> idAlarmsMap;
395 idAlarmsMap.insert(std::make_pair(alarm->id, alarm));
396 pidTimersMap_.insert(std::make_pair(alarm->pid, idAlarmsMap));
397 return;
398 }
399
400 EraseAlarmItem(alarm->id, it->second);
401 it->second.insert(std::make_pair(alarm->id, alarm));
402 }
403
RemoveUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)404 void TimerProxy::RemoveUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
405 {
406 if (alarm == nullptr) {
407 TIME_HILOGE(TIME_MODULE_SERVICE, "remove uid timer map alarm is nullptr!");
408 return;
409 }
410
411 std::lock_guard<std::mutex> lock(uidTimersMutex_);
412 auto it = uidTimersMap_.find(alarm->uid);
413 if (it == uidTimersMap_.end()) {
414 return;
415 }
416
417 EraseAlarmItem(alarm->id, it->second);
418 if (it->second.empty()) {
419 uidTimersMap_.erase(it);
420 }
421 }
422
RecordProxyUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)423 void TimerProxy::RecordProxyUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
424 {
425 std::lock_guard<std::mutex> lock(proxyMutex_);
426 auto it = proxyUids_.find(alarm->uid);
427 if (it != proxyUids_.end()) {
428 it->second.insert(std::make_pair(alarm->id, alarm->whenElapsed));
429 } else {
430 proxyUids_.insert(std::make_pair(alarm->uid,
431 std::unordered_map<uint64_t, std::chrono::steady_clock::time_point>{{alarm->id, alarm->whenElapsed}}));
432 }
433 }
434
RecordProxyPidTimerMap(const std::shared_ptr<TimerInfo> &alarm)435 void TimerProxy::RecordProxyPidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
436 {
437 std::lock_guard<std::mutex> lock(proxyMutex_);
438 auto it = proxyPids_.find(alarm->pid);
439 if (it != proxyPids_.end()) {
440 it->second.insert(std::make_pair(alarm->id, alarm->whenElapsed));
441 } else {
442 proxyPids_.insert(std::make_pair(alarm->pid,
443 std::unordered_map<uint64_t, std::chrono::steady_clock::time_point>{{alarm->id, alarm->whenElapsed}}));
444 }
445 }
446
RemovePidTimerMap(const std::shared_ptr<TimerInfo> &alarm)447 void TimerProxy::RemovePidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
448 {
449 if (alarm == nullptr) {
450 TIME_HILOGE(TIME_MODULE_SERVICE, "remove pid timer map alarm is nullptr!");
451 return;
452 }
453
454 std::lock_guard<std::mutex> lock(pidTimersMutex_);
455 auto it = pidTimersMap_.find(alarm->pid);
456 if (it == pidTimersMap_.end()) {
457 return;
458 }
459
460 EraseAlarmItem(alarm->id, it->second);
461 if (it->second.empty()) {
462 pidTimersMap_.erase(it);
463 }
464 }
465
RemoveUidTimerMap(const uint64_t id)466 void TimerProxy::RemoveUidTimerMap(const uint64_t id)
467 {
468 std::lock_guard<std::mutex> lock(uidTimersMutex_);
469 for (auto itUidsTimer = uidTimersMap_.begin(); itUidsTimer!= uidTimersMap_.end(); ++itUidsTimer) {
470 for (auto itTimerId = itUidsTimer->second.begin(); itTimerId!= itUidsTimer->second.end(); ++itTimerId) {
471 if (itTimerId->first != id) {
472 continue;
473 }
474
475 itUidsTimer->second.erase(itTimerId);
476 if (itUidsTimer->second.empty()) {
477 uidTimersMap_.erase(itUidsTimer);
478 }
479 return;
480 }
481 }
482 }
483
RemovePidTimerMap(const uint64_t id)484 void TimerProxy::RemovePidTimerMap(const uint64_t id)
485 {
486 std::lock_guard<std::mutex> lock(pidTimersMutex_);
487 for (auto itPidsTimer = pidTimersMap_.begin(); itPidsTimer!= pidTimersMap_.end(); ++itPidsTimer) {
488 for (auto itTimerId = itPidsTimer->second.begin(); itTimerId!= itPidsTimer->second.end(); ++itTimerId) {
489 if (itTimerId->first != id) {
490 continue;
491 }
492
493 itPidsTimer->second.erase(itTimerId);
494 if (itPidsTimer->second.empty()) {
495 pidTimersMap_.erase(itPidsTimer);
496 }
497 return;
498 }
499 }
500 }
501
IsUidProxy(const int32_t uid)502 bool TimerProxy::IsUidProxy(const int32_t uid)
503 {
504 std::lock_guard<std::mutex> lock(proxyMutex_);
505 auto it = proxyUids_.find(uid);
506 if (it == proxyUids_.end()) {
507 return false;
508 }
509 return true;
510 }
511
IsPidProxy(const int32_t pid)512 bool TimerProxy::IsPidProxy(const int32_t pid)
513 {
514 std::lock_guard<std::mutex> lock(proxyPidMutex_);
515 auto it = proxyPids_.find(pid);
516 if (it == proxyPids_.end()) {
517 return false;
518 }
519 return true;
520 }
521
522 // needs to acquire the lock `proxyMutex_` before calling this method
UpdateProxyWhenElapsedForProxyUidMap(const int32_t uid, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)523 void TimerProxy::UpdateProxyWhenElapsedForProxyUidMap(const int32_t uid,
524 const std::chrono::steady_clock::time_point &now,
525 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
526 {
527 auto it = proxyUids_.find(uid);
528 if (it != proxyUids_.end()) {
529 TIME_HILOGD(TIME_MODULE_SERVICE, "uid is already proxy, uid: %{public}d", uid);
530 return;
531 }
532
533 std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
534 if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
535 TIME_HILOGD(TIME_MODULE_SERVICE, "uid timer info map not found, uid: %{public}d", uid);
536 std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
537 proxyUids_.insert(std::make_pair(uid, timePointMap));
538 return;
539 }
540
541 std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
542 for (auto itUidTimersMap = uidTimersMap_.at(uid).begin(); itUidTimersMap!= uidTimersMap_.at(uid).end();
543 ++itUidTimersMap) {
544 timePointMap.insert(std::make_pair(itUidTimersMap->first, itUidTimersMap->second->whenElapsed));
545 itUidTimersMap->second->UpdateWhenElapsedFromNow(now, milliseconds(proxyDelayTime_));
546 TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy uid map. "
547 "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
548 itUidTimersMap->second->uid, itUidTimersMap->second->id,
549 itUidTimersMap->second->whenElapsed.time_since_epoch().count(),
550 now.time_since_epoch().count());
551 insertAlarmCallback(itUidTimersMap->second);
552 }
553 proxyUids_.insert(std::make_pair(uid, timePointMap));
554 }
555
UpdateProxyWhenElapsedForProxyPidMap(int pid, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)556 void TimerProxy::UpdateProxyWhenElapsedForProxyPidMap(int pid,
557 const std::chrono::steady_clock::time_point &now,
558 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
559 {
560 auto it = proxyPids_.find(pid);
561 if (it != proxyPids_.end()) {
562 TIME_HILOGD(TIME_MODULE_SERVICE, "pid is already proxy, pid: %{public}d", pid);
563 return;
564 }
565
566 std::lock_guard<std::mutex> lockUidTimers(pidTimersMutex_);
567 if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
568 TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, pid: %{public}d", pid);
569 std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
570 proxyPids_.insert(std::make_pair(pid, timePointMap));
571 return;
572 }
573
574 std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
575 for (auto itPidTimersMap = pidTimersMap_.at(pid).begin(); itPidTimersMap!= pidTimersMap_.at(pid).end();
576 ++itPidTimersMap) {
577 timePointMap.insert(std::make_pair(itPidTimersMap->first, itPidTimersMap->second->whenElapsed));
578 itPidTimersMap->second->UpdateWhenElapsedFromNow(now, milliseconds(proxyDelayTime_));
579 TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy pid map. "
580 "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
581 itPidTimersMap->second->pid, itPidTimersMap->second->id,
582 itPidTimersMap->second->whenElapsed.time_since_epoch().count(),
583 now.time_since_epoch().count());
584 insertAlarmCallback(itPidTimersMap->second);
585 }
586 proxyPids_.insert(std::make_pair(pid, timePointMap));
587 }
588
RestoreProxyWhenElapsedByUid(const int32_t uid, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)589 bool TimerProxy::RestoreProxyWhenElapsedByUid(const int32_t uid,
590 const std::chrono::steady_clock::time_point &now,
591 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
592 {
593 auto it = proxyUids_.find(uid);
594 if (it == proxyUids_.end()) {
595 TIME_HILOGD(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list.", uid);
596 return false;
597 }
598
599 std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
600 if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
601 TIME_HILOGD(TIME_MODULE_SERVICE, "uid timer info map not found, just erase proxy map. uid: %{public}d", uid);
602 return true;
603 }
604
605 for (auto itProxyUids = proxyUids_.at(uid).begin(); itProxyUids != proxyUids_.at(uid).end(); ++itProxyUids) {
606 auto itTimerInfo = uidTimersMap_.at(uid).find(itProxyUids->first);
607 if (itTimerInfo == uidTimersMap_.at(uid).end()) {
608 continue;
609 }
610 if (itProxyUids->second > now + milliseconds(MILLI_TO_SECOND)) {
611 auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyUids->second - now);
612 itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
613 } else {
614 itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
615 }
616 TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by uid. "
617 "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
618 itTimerInfo->second->uid, itTimerInfo->second->id,
619 itTimerInfo->second->whenElapsed.time_since_epoch().count(),
620 now.time_since_epoch().count());
621 insertAlarmCallback(itTimerInfo->second);
622 }
623
624 return true;
625 }
626
RestoreProxyWhenElapsedByPid(const int pid, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)627 bool TimerProxy::RestoreProxyWhenElapsedByPid(const int pid,
628 const std::chrono::steady_clock::time_point &now,
629 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
630 {
631 auto it = proxyPids_.find(pid);
632 if (it == proxyPids_.end()) {
633 TIME_HILOGD(TIME_MODULE_SERVICE, "Pid: %{public}d doesn't exist in the proxy list.", pid);
634 return false;
635 }
636 std::lock_guard<std::mutex> lockPidTimers(pidTimersMutex_);
637 if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
638 TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, just erase proxy map. pid: %{public}d", pid);
639 return true;
640 }
641 for (auto itProxyPids = proxyPids_.at(pid).begin(); itProxyPids != proxyPids_.at(pid).end(); ++itProxyPids) {
642 auto itTimerInfo = pidTimersMap_.at(pid).find(itProxyPids->first);
643 if (itTimerInfo == pidTimersMap_.at(pid).end()) {
644 continue;
645 }
646 if (itProxyPids->second > now + milliseconds(MILLI_TO_SECOND)) {
647 auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyPids->second - now);
648 itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
649 } else {
650 itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
651 }
652 TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by pid. "
653 "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
654 itTimerInfo->second->pid, itTimerInfo->second->id,
655 itTimerInfo->second->whenElapsed.time_since_epoch().count(),
656 now.time_since_epoch().count());
657 insertAlarmCallback(itTimerInfo->second);
658 }
659
660 return true;
661 }
662
663 // needs to acquire the lock `proxyMutex_` before calling this method
RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)664 bool TimerProxy::RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid,
665 const std::chrono::steady_clock::time_point &now,
666 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
667 {
668 bool ret = RestoreProxyWhenElapsedByUid(uid, now, insertAlarmCallback);
669 if (ret) {
670 proxyUids_.erase(uid);
671 }
672 return ret;
673 }
674
RestoreProxyWhenElapsedForProxyPidMap(const int pid, const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)675 bool TimerProxy::RestoreProxyWhenElapsedForProxyPidMap(const int pid,
676 const std::chrono::steady_clock::time_point &now,
677 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
678 {
679 bool ret = RestoreProxyWhenElapsedByPid(pid, now, insertAlarmCallback);
680 if (ret) {
681 proxyPids_.erase(pid);
682 }
683 return ret;
684 }
685
686
ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)687 void TimerProxy::ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
688 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
689 {
690 std::lock_guard<std::mutex> lockProxy(proxyMutex_);
691 for (auto it = proxyUids_.begin(); it != proxyUids_.end(); ++it) {
692 RestoreProxyWhenElapsedByUid(it->first, now, insertAlarmCallback);
693 }
694 proxyUids_.clear();
695 }
696
ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point &now, std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)697 void TimerProxy::ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
698 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
699 {
700 std::lock_guard<std::mutex> lockProxy(proxyPidMutex_);
701 for (auto it = proxyPids_.begin(); it != proxyPids_.end(); ++it) {
702 RestoreProxyWhenElapsedByPid(it->first, now, insertAlarmCallback);
703 }
704 proxyPids_.clear();
705 }
706
ShowProxyTimerInfo(int fd, const int64_t now)707 bool TimerProxy::ShowProxyTimerInfo(int fd, const int64_t now)
708 {
709 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
710 std::lock_guard<std::mutex> lockProxy(proxyMutex_);
711 dprintf(fd, "current time %lld\n", now);
712 for (auto itProxyUids = proxyUids_.begin(); itProxyUids != proxyUids_.end(); ++itProxyUids) {
713 dprintf(fd, " - proxy uid = %lu\n", itProxyUids->first);
714 for (auto itTimerIdMap = itProxyUids->second.begin(); itTimerIdMap != itProxyUids->second.end();
715 ++itTimerIdMap) {
716 dprintf(fd, " * save timer id = %llu\n", itTimerIdMap->first);
717 dprintf(fd, " * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
718 }
719 }
720 std::lock_guard<std::mutex> lockPidProxy(proxyPidMutex_);
721 dprintf(fd, "current time %lld\n", now);
722 for (auto itProxyPids = proxyPids_.begin(); itProxyPids != proxyPids_.end(); ++itProxyPids) {
723 dprintf(fd, " - proxy pid = %lu\n", itProxyPids->first);
724 for (auto itTimerIdMap = itProxyPids->second.begin(); itTimerIdMap != itProxyPids->second.end();
725 ++itTimerIdMap) {
726 dprintf(fd, " * save timer id = %llu\n", itTimerIdMap->first);
727 dprintf(fd, " * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
728 }
729 }
730 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
731 return true;
732 }
733
ShowUidTimerMapInfo(int fd, const int64_t now)734 bool TimerProxy::ShowUidTimerMapInfo(int fd, const int64_t now)
735 {
736 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
737 std::lock_guard<std::mutex> lockProxy(uidTimersMutex_);
738 dprintf(fd, "current time %lld\n", now);
739 for (auto itTimerInfoMap = uidTimersMap_.begin(); itTimerInfoMap != uidTimersMap_.end(); ++itTimerInfoMap) {
740 dprintf(fd, " - uid = %lu\n", itTimerInfoMap->first);
741 for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
742 ++itTimerInfo) {
743 dprintf(fd, " * timer id = %llu\n", itTimerInfo->second->id);
744 dprintf(fd, " * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
745 }
746 }
747 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
748 return true;
749 }
750
ShowPidTimerMapInfo(int fd, const int64_t now)751 bool TimerProxy::ShowPidTimerMapInfo(int fd, const int64_t now)
752 {
753 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
754 std::lock_guard<std::mutex> lockProxy(pidTimersMutex_);
755 dprintf(fd, "current time %lld\n", now);
756 for (auto itTimerInfoMap = pidTimersMap_.begin(); itTimerInfoMap != pidTimersMap_.end(); ++itTimerInfoMap) {
757 dprintf(fd, " - pid = %lu\n", itTimerInfoMap->first);
758 for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
759 ++itTimerInfo) {
760 dprintf(fd, " * timer id = %llu\n", itTimerInfo->second->id);
761 dprintf(fd, " * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
762 }
763 }
764 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
765 return true;
766 }
767
768
ShowAdjustTimerInfo(int fd)769 void TimerProxy::ShowAdjustTimerInfo(int fd)
770 {
771 std::lock_guard<std::mutex> lockProxy(adjustMutex_);
772 dprintf(fd, "show adjust timer");
773 for (auto timer : adjustTimers_) {
774 dprintf(fd, " * timer id = %lu\n", timer->id);
775 dprintf(fd, " * timer uid = %d\n\n", timer->uid);
776 dprintf(fd, " * timer bundleName = %s\n\n", timer->bundleName.c_str());
777 dprintf(fd, " * timer originWhenElapsed = %lld\n\n", timer->originWhenElapsed);
778 dprintf(fd, " * timer whenElapsed = %lld\n\n", timer->whenElapsed);
779 dprintf(fd, " * timer originMaxWhenElapsed = %lld\n\n", timer->originMaxWhenElapsed);
780 dprintf(fd, " * timer maxWhenElapsed = %lld\n\n", timer->maxWhenElapsed);
781 }
782 }
783
ShowProxyDelayTime(int fd)784 bool TimerProxy::ShowProxyDelayTime(int fd)
785 {
786 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
787 dprintf(fd, "proxy delay time: %lld ms\n", proxyDelayTime_);
788 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
789 return true;
790 }
791
GetProxyDelayTime() const792 int64_t TimerProxy::GetProxyDelayTime() const
793 {
794 return proxyDelayTime_;
795 }
796 } // MiscServices
797 } // OHOS