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
IMPLEMENT_SINGLE_INSTANCE(TimerProxy)32 IMPLEMENT_SINGLE_INSTANCE(TimerProxy)
33
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(int32_t uid,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(int32_t uid, 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(uid, 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(int32_t uid,int pid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)556 void TimerProxy::UpdateProxyWhenElapsedForProxyPidMap(int32_t uid, 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 if (uid == itPidTimersMap->second->uid) {
578 timePointMap.insert(std::make_pair(itPidTimersMap->first, itPidTimersMap->second->whenElapsed));
579 itPidTimersMap->second->UpdateWhenElapsedFromNow(now, milliseconds(proxyDelayTime_));
580 TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy pid map. "
581 "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
582 itPidTimersMap->second->pid, itPidTimersMap->second->id,
583 itPidTimersMap->second->whenElapsed.time_since_epoch().count(),
584 now.time_since_epoch().count());
585 insertAlarmCallback(itPidTimersMap->second);
586 }
587 }
588 proxyPids_.insert(std::make_pair(pid, timePointMap));
589 }
590
RestoreProxyWhenElapsedByUid(const int32_t uid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)591 bool TimerProxy::RestoreProxyWhenElapsedByUid(const int32_t uid,
592 const std::chrono::steady_clock::time_point &now,
593 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
594 {
595 auto it = proxyUids_.find(uid);
596 if (it == proxyUids_.end()) {
597 TIME_HILOGD(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list.", uid);
598 return false;
599 }
600
601 std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
602 if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
603 TIME_HILOGD(TIME_MODULE_SERVICE, "uid timer info map not found, just erase proxy map. uid: %{public}d", uid);
604 return true;
605 }
606
607 for (auto itProxyUids = proxyUids_.at(uid).begin(); itProxyUids != proxyUids_.at(uid).end(); ++itProxyUids) {
608 auto itTimerInfo = uidTimersMap_.at(uid).find(itProxyUids->first);
609 if (itTimerInfo == uidTimersMap_.at(uid).end()) {
610 continue;
611 }
612 if (itProxyUids->second > now + milliseconds(MILLI_TO_SECOND)) {
613 auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyUids->second - now);
614 itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
615 } else {
616 itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
617 }
618 TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by uid. "
619 "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
620 itTimerInfo->second->uid, itTimerInfo->second->id,
621 itTimerInfo->second->whenElapsed.time_since_epoch().count(),
622 now.time_since_epoch().count());
623 insertAlarmCallback(itTimerInfo->second);
624 }
625
626 return true;
627 }
628
RestoreProxyWhenElapsedByPid(const int pid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)629 bool TimerProxy::RestoreProxyWhenElapsedByPid(const int pid,
630 const std::chrono::steady_clock::time_point &now,
631 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
632 {
633 auto it = proxyPids_.find(pid);
634 if (it == proxyPids_.end()) {
635 TIME_HILOGD(TIME_MODULE_SERVICE, "Pid: %{public}d doesn't exist in the proxy list.", pid);
636 return false;
637 }
638 std::lock_guard<std::mutex> lockPidTimers(pidTimersMutex_);
639 if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
640 TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, just erase proxy map. pid: %{public}d", pid);
641 return true;
642 }
643 for (auto itProxyPids = proxyPids_.at(pid).begin(); itProxyPids != proxyPids_.at(pid).end(); ++itProxyPids) {
644 auto itTimerInfo = pidTimersMap_.at(pid).find(itProxyPids->first);
645 if (itTimerInfo == pidTimersMap_.at(pid).end()) {
646 continue;
647 }
648 if (itProxyPids->second > now + milliseconds(MILLI_TO_SECOND)) {
649 auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyPids->second - now);
650 itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
651 } else {
652 itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
653 }
654 TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by pid. "
655 "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
656 itTimerInfo->second->pid, itTimerInfo->second->id,
657 itTimerInfo->second->whenElapsed.time_since_epoch().count(),
658 now.time_since_epoch().count());
659 insertAlarmCallback(itTimerInfo->second);
660 }
661
662 return true;
663 }
664
665 // 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)666 bool TimerProxy::RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid,
667 const std::chrono::steady_clock::time_point &now,
668 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
669 {
670 bool ret = RestoreProxyWhenElapsedByUid(uid, now, insertAlarmCallback);
671 if (ret) {
672 proxyUids_.erase(uid);
673 }
674 return ret;
675 }
676
RestoreProxyWhenElapsedForProxyPidMap(const int pid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)677 bool TimerProxy::RestoreProxyWhenElapsedForProxyPidMap(const int pid,
678 const std::chrono::steady_clock::time_point &now,
679 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
680 {
681 bool ret = RestoreProxyWhenElapsedByPid(pid, now, insertAlarmCallback);
682 if (ret) {
683 proxyPids_.erase(pid);
684 }
685 return ret;
686 }
687
688
ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)689 void TimerProxy::ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
690 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
691 {
692 std::lock_guard<std::mutex> lockProxy(proxyMutex_);
693 for (auto it = proxyUids_.begin(); it != proxyUids_.end(); ++it) {
694 RestoreProxyWhenElapsedByUid(it->first, now, insertAlarmCallback);
695 }
696 proxyUids_.clear();
697 }
698
ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)699 void TimerProxy::ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
700 std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
701 {
702 std::lock_guard<std::mutex> lockProxy(proxyPidMutex_);
703 for (auto it = proxyPids_.begin(); it != proxyPids_.end(); ++it) {
704 RestoreProxyWhenElapsedByPid(it->first, now, insertAlarmCallback);
705 }
706 proxyPids_.clear();
707 }
708
ShowProxyTimerInfo(int fd,const int64_t now)709 bool TimerProxy::ShowProxyTimerInfo(int fd, const int64_t now)
710 {
711 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
712 std::lock_guard<std::mutex> lockProxy(proxyMutex_);
713 dprintf(fd, "current time %lld\n", now);
714 for (auto itProxyUids = proxyUids_.begin(); itProxyUids != proxyUids_.end(); ++itProxyUids) {
715 dprintf(fd, " - proxy uid = %lu\n", itProxyUids->first);
716 for (auto itTimerIdMap = itProxyUids->second.begin(); itTimerIdMap != itProxyUids->second.end();
717 ++itTimerIdMap) {
718 dprintf(fd, " * save timer id = %llu\n", itTimerIdMap->first);
719 dprintf(fd, " * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
720 }
721 }
722 std::lock_guard<std::mutex> lockPidProxy(proxyPidMutex_);
723 dprintf(fd, "current time %lld\n", now);
724 for (auto itProxyPids = proxyPids_.begin(); itProxyPids != proxyPids_.end(); ++itProxyPids) {
725 dprintf(fd, " - proxy pid = %lu\n", itProxyPids->first);
726 for (auto itTimerIdMap = itProxyPids->second.begin(); itTimerIdMap != itProxyPids->second.end();
727 ++itTimerIdMap) {
728 dprintf(fd, " * save timer id = %llu\n", itTimerIdMap->first);
729 dprintf(fd, " * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
730 }
731 }
732 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
733 return true;
734 }
735
ShowUidTimerMapInfo(int fd,const int64_t now)736 bool TimerProxy::ShowUidTimerMapInfo(int fd, const int64_t now)
737 {
738 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
739 std::lock_guard<std::mutex> lockProxy(uidTimersMutex_);
740 dprintf(fd, "current time %lld\n", now);
741 for (auto itTimerInfoMap = uidTimersMap_.begin(); itTimerInfoMap != uidTimersMap_.end(); ++itTimerInfoMap) {
742 dprintf(fd, " - uid = %lu\n", itTimerInfoMap->first);
743 for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
744 ++itTimerInfo) {
745 dprintf(fd, " * timer id = %llu\n", itTimerInfo->second->id);
746 dprintf(fd, " * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
747 }
748 }
749 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
750 return true;
751 }
752
ShowPidTimerMapInfo(int fd,const int64_t now)753 bool TimerProxy::ShowPidTimerMapInfo(int fd, const int64_t now)
754 {
755 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
756 std::lock_guard<std::mutex> lockProxy(pidTimersMutex_);
757 dprintf(fd, "current time %lld\n", now);
758 for (auto itTimerInfoMap = pidTimersMap_.begin(); itTimerInfoMap != pidTimersMap_.end(); ++itTimerInfoMap) {
759 dprintf(fd, " - pid = %lu\n", itTimerInfoMap->first);
760 for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
761 ++itTimerInfo) {
762 dprintf(fd, " * timer id = %llu\n", itTimerInfo->second->id);
763 dprintf(fd, " * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
764 }
765 }
766 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
767 return true;
768 }
769
770
ShowAdjustTimerInfo(int fd)771 void TimerProxy::ShowAdjustTimerInfo(int fd)
772 {
773 std::lock_guard<std::mutex> lockProxy(adjustMutex_);
774 dprintf(fd, "show adjust timer");
775 for (auto timer : adjustTimers_) {
776 dprintf(fd, " * timer id = %lu\n", timer->id);
777 dprintf(fd, " * timer uid = %d\n\n", timer->uid);
778 dprintf(fd, " * timer bundleName = %s\n\n", timer->bundleName.c_str());
779 dprintf(fd, " * timer originWhenElapsed = %lld\n\n", timer->originWhenElapsed);
780 dprintf(fd, " * timer whenElapsed = %lld\n\n", timer->whenElapsed);
781 dprintf(fd, " * timer originMaxWhenElapsed = %lld\n\n", timer->originMaxWhenElapsed);
782 dprintf(fd, " * timer maxWhenElapsed = %lld\n\n", timer->maxWhenElapsed);
783 }
784 }
785
ShowProxyDelayTime(int fd)786 bool TimerProxy::ShowProxyDelayTime(int fd)
787 {
788 TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
789 dprintf(fd, "proxy delay time: %lld ms\n", proxyDelayTime_);
790 TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
791 return true;
792 }
793
GetProxyDelayTime() const794 int64_t TimerProxy::GetProxyDelayTime() const
795 {
796 return proxyDelayTime_;
797 }
798 } // MiscServices
799 } // OHOS