• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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