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