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