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     if (adjustExemptionList_.find(timer->bundleName) != adjustExemptionList_.end()
277         && timer->windowLength == milliseconds::zero()) {
278         return true;
279     }
280     return false;
281 }
282 
ResetProxyMaps()283 void TimerProxy::ResetProxyMaps()
284 {
285     std::lock_guard<std::mutex> lock(proxyMutex_);
286     for (auto it = proxyMap_.begin(); it != proxyMap_.end(); it++) {
287         auto timeInfoVec = it->second;
288         for (const auto& alarm : timeInfoVec) {
289             if (!alarm->callback) {
290                 TIME_HILOGE(TIME_MODULE_SERVICE, "Callback is nullptr!");
291                 continue;
292             }
293             alarm->callback(alarm->id);
294             TIME_HILOGD(TIME_MODULE_SERVICE, "Reset all proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
295                 it->first, alarm->id);
296         }
297         timeInfoVec.clear();
298     }
299     proxyMap_.clear();
300 }
301 
ResetProxyPidMaps()302 void TimerProxy::ResetProxyPidMaps()
303 {
304     std::lock_guard<std::mutex> lock(proxyPidMutex_);
305     for (auto it = proxyPidMap_.begin(); it != proxyPidMap_.end(); it++) {
306         auto timeInfoVec = it->second;
307         for (const auto& alarm : timeInfoVec) {
308             if (!alarm->callback) {
309                 TIME_HILOGE(TIME_MODULE_SERVICE, "Callback is nullptr!");
310                 continue;
311             }
312             alarm->callback(alarm->id);
313             TIME_HILOGD(TIME_MODULE_SERVICE, "Reset all proxy, proxyPid: %{public}d, alarmId: %{public}" PRId64 "",
314                 it->first, alarm->id);
315         }
316         timeInfoVec.clear();
317     }
318     proxyPidMap_.clear();
319 }
320 
ResetAllProxy(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)321 bool TimerProxy::ResetAllProxy(const std::chrono::steady_clock::time_point &now,
322     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
323 {
324     TIME_HILOGD(TIME_MODULE_SERVICE, "start");
325     ResetProxyMaps();
326     ResetAllProxyWhenElapsed(now, insertAlarmCallback);
327     ResetProxyPidMaps();
328     ResetAllPidProxyWhenElapsed(now, insertAlarmCallback);
329     return true;
330 }
331 
EraseTimerFromProxyUidMap(const uint64_t id,const uint32_t uid)332 void TimerProxy::EraseTimerFromProxyUidMap(const uint64_t id, const uint32_t uid)
333 {
334     TIME_HILOGD(TIME_MODULE_SERVICE, "erase timer from proxy timer map, id=%{public}" PRId64 ", uid=%{public}u",
335         id, uid);
336     std::lock_guard<std::mutex> lock(proxyMutex_);
337     auto it = proxyUids_.find(uid);
338     if (it != proxyUids_.end()) {
339         it->second.erase(id);
340     }
341 }
342 
EraseTimerFromProxyPidMap(const uint64_t id,const int uid,const int pid)343 void TimerProxy::EraseTimerFromProxyPidMap(const uint64_t id, const int uid, const int pid)
344 {
345     TIME_HILOGD(TIME_MODULE_SERVICE, "erase timer from proxy timer map, id=%{public}" PRId64 ", pid=%{public}u",
346         id, pid);
347     std::lock_guard<std::mutex> lock(proxyPidMutex_);
348     uint64_t key = GetProxyKey(uid, pid);
349     auto it = proxyPids_.find(key);
350     if (it != proxyPids_.end()) {
351         it->second.erase(id);
352     }
353 }
354 
EraseAlarmItem(const uint64_t id,std::unordered_map<uint64_t,std::shared_ptr<TimerInfo>> & idAlarmsMap)355 void TimerProxy::EraseAlarmItem(
356     const uint64_t id, std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> &idAlarmsMap)
357 {
358     auto itAlarms = idAlarmsMap.find(id);
359     if (itAlarms != idAlarmsMap.end()) {
360         TIME_HILOGD(TIME_MODULE_SERVICE, "timer already exists, id=%{public}" PRId64 "", id);
361         idAlarmsMap.erase(itAlarms);
362     }
363 }
364 
RecordUidTimerMap(const std::shared_ptr<TimerInfo> & alarm,const bool isRebatched)365 void TimerProxy::RecordUidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)
366 {
367     if (isRebatched) {
368         TIME_HILOGD(TIME_MODULE_SERVICE, "Record uid timer info map, isRebatched: %{public}d", isRebatched);
369         return;
370     }
371     if (alarm == nullptr) {
372         TIME_HILOGE(TIME_MODULE_SERVICE, "record uid timer map alarm is nullptr!");
373         return;
374     }
375 
376     std::lock_guard<std::mutex> lock(uidTimersMutex_);
377     auto it = uidTimersMap_.find(alarm->uid);
378     if (it == uidTimersMap_.end()) {
379         std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> idAlarmsMap;
380         idAlarmsMap.insert(std::make_pair(alarm->id, alarm));
381         uidTimersMap_.insert(std::make_pair(alarm->uid, idAlarmsMap));
382         return;
383     }
384 
385     EraseAlarmItem(alarm->id, it->second);
386     it->second.insert(std::make_pair(alarm->id, alarm));
387 }
388 
RecordPidTimerMap(const std::shared_ptr<TimerInfo> & alarm,const bool isRebatched)389 void TimerProxy::RecordPidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)
390 {
391     if (isRebatched) {
392         TIME_HILOGD(TIME_MODULE_SERVICE, "Record pid timer info map, isRebatched: %{public}d", isRebatched);
393         return;
394     }
395     if (alarm == nullptr) {
396         TIME_HILOGE(TIME_MODULE_SERVICE, "record pid timer map alarm is nullptr!");
397         return;
398     }
399 
400     std::lock_guard<std::mutex> lock(pidTimersMutex_);
401     auto it = pidTimersMap_.find(alarm->pid);
402     if (it == pidTimersMap_.end()) {
403         std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> idAlarmsMap;
404         idAlarmsMap.insert(std::make_pair(alarm->id, alarm));
405         pidTimersMap_.insert(std::make_pair(alarm->pid, idAlarmsMap));
406         return;
407     }
408 
409     EraseAlarmItem(alarm->id, it->second);
410     it->second.insert(std::make_pair(alarm->id, alarm));
411 }
412 
RemoveUidTimerMap(const std::shared_ptr<TimerInfo> & alarm)413 void TimerProxy::RemoveUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
414 {
415     if (alarm == nullptr) {
416         TIME_HILOGE(TIME_MODULE_SERVICE, "remove uid timer map alarm is nullptr!");
417         return;
418     }
419 
420     std::lock_guard<std::mutex> lock(uidTimersMutex_);
421     auto it = uidTimersMap_.find(alarm->uid);
422     if (it == uidTimersMap_.end()) {
423         return;
424     }
425 
426     EraseAlarmItem(alarm->id, it->second);
427     if (it->second.empty()) {
428         uidTimersMap_.erase(it);
429     }
430 }
431 
RecordProxyUidTimerMap(const std::shared_ptr<TimerInfo> & alarm)432 void TimerProxy::RecordProxyUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
433 {
434     std::lock_guard<std::mutex> lock(proxyMutex_);
435     auto it = proxyUids_.find(alarm->uid);
436     if (it != proxyUids_.end()) {
437         it->second.insert(std::make_pair(alarm->id, alarm->whenElapsed));
438     } else {
439         proxyUids_.insert(std::make_pair(alarm->uid,
440             std::unordered_map<uint64_t, std::chrono::steady_clock::time_point>{{alarm->id, alarm->whenElapsed}}));
441     }
442 }
443 
RecordProxyPidTimerMap(const std::shared_ptr<TimerInfo> & alarm)444 void TimerProxy::RecordProxyPidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
445 {
446     std::lock_guard<std::mutex> lock(proxyMutex_);
447     auto uid = alarm->uid;
448     auto pid = alarm->pid;
449     uint64_t key = GetProxyKey(uid, pid);
450     auto it = proxyPids_.find(key);
451     if (it != proxyPids_.end()) {
452         it->second.insert(std::make_pair(alarm->id, alarm->whenElapsed));
453     } else {
454         proxyPids_.insert(std::make_pair(alarm->pid,
455             std::unordered_map<uint64_t, std::chrono::steady_clock::time_point>{{alarm->id, alarm->whenElapsed}}));
456     }
457 }
458 
RemovePidTimerMap(const std::shared_ptr<TimerInfo> & alarm)459 void TimerProxy::RemovePidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
460 {
461     if (alarm == nullptr) {
462         TIME_HILOGE(TIME_MODULE_SERVICE, "remove pid timer map alarm is nullptr!");
463         return;
464     }
465 
466     std::lock_guard<std::mutex> lock(pidTimersMutex_);
467     auto it = pidTimersMap_.find(alarm->pid);
468     if (it == pidTimersMap_.end()) {
469         return;
470     }
471 
472     EraseAlarmItem(alarm->id, it->second);
473     if (it->second.empty()) {
474         pidTimersMap_.erase(it);
475     }
476 }
477 
RemoveUidTimerMap(const uint64_t id)478 void TimerProxy::RemoveUidTimerMap(const uint64_t id)
479 {
480     std::lock_guard<std::mutex> lock(uidTimersMutex_);
481     for (auto itUidsTimer = uidTimersMap_.begin(); itUidsTimer!= uidTimersMap_.end(); ++itUidsTimer) {
482         for (auto itTimerId = itUidsTimer->second.begin(); itTimerId!= itUidsTimer->second.end(); ++itTimerId) {
483             if (itTimerId->first != id) {
484                 continue;
485             }
486 
487             itUidsTimer->second.erase(itTimerId);
488             if (itUidsTimer->second.empty()) {
489                 uidTimersMap_.erase(itUidsTimer);
490             }
491             return;
492         }
493     }
494 }
495 
RemovePidTimerMap(const uint64_t id)496 void TimerProxy::RemovePidTimerMap(const uint64_t id)
497 {
498     std::lock_guard<std::mutex> lock(pidTimersMutex_);
499     for (auto itPidsTimer = pidTimersMap_.begin(); itPidsTimer!= pidTimersMap_.end(); ++itPidsTimer) {
500         for (auto itTimerId = itPidsTimer->second.begin(); itTimerId!= itPidsTimer->second.end(); ++itTimerId) {
501             if (itTimerId->first != id) {
502                 continue;
503             }
504 
505             itPidsTimer->second.erase(itTimerId);
506             if (itPidsTimer->second.empty()) {
507                 pidTimersMap_.erase(itPidsTimer);
508             }
509             return;
510         }
511     }
512 }
513 
IsUidProxy(const int32_t uid)514 bool TimerProxy::IsUidProxy(const int32_t uid)
515 {
516     std::lock_guard<std::mutex> lock(proxyMutex_);
517     auto it = proxyUids_.find(uid);
518     if (it == proxyUids_.end()) {
519         return false;
520     }
521     return true;
522 }
523 
IsPidProxy(const int32_t uid,const int32_t pid)524 bool TimerProxy::IsPidProxy(const int32_t uid, const int32_t pid)
525 {
526     std::lock_guard<std::mutex> lock(proxyPidMutex_);
527     uint64_t key = GetProxyKey(uid, pid);
528     auto it = proxyPids_.find(key);
529     if (it == proxyPids_.end()) {
530         return false;
531     }
532     return true;
533 }
534 
535 // 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)536 void TimerProxy::UpdateProxyWhenElapsedForProxyUidMap(const int32_t uid,
537     const std::chrono::steady_clock::time_point &now,
538     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
539 {
540     auto it = proxyUids_.find(uid);
541     if (it != proxyUids_.end()) {
542         TIME_HILOGD(TIME_MODULE_SERVICE, "uid is already proxy, uid: %{public}d", uid);
543         return;
544     }
545 
546     std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
547     if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
548         TIME_HILOGD(TIME_MODULE_SERVICE, "uid timer info map not found, uid: %{public}d", uid);
549         std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
550         proxyUids_.insert(std::make_pair(uid, timePointMap));
551         return;
552     }
553 
554     std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
555     for (auto itUidTimersMap = uidTimersMap_.at(uid).begin(); itUidTimersMap!= uidTimersMap_.at(uid).end();
556         ++itUidTimersMap) {
557         timePointMap.insert(std::make_pair(itUidTimersMap->first, itUidTimersMap->second->whenElapsed));
558         itUidTimersMap->second->UpdateWhenElapsedFromNow(now, milliseconds(proxyDelayTime_));
559         TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy uid map. "
560             "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
561             itUidTimersMap->second->uid, itUidTimersMap->second->id,
562             itUidTimersMap->second->whenElapsed.time_since_epoch().count(),
563             now.time_since_epoch().count());
564         insertAlarmCallback(itUidTimersMap->second);
565     }
566     proxyUids_.insert(std::make_pair(uid, timePointMap));
567 }
568 
UpdateProxyWhenElapsedForProxyPidMap(int32_t uid,int pid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)569 void TimerProxy::UpdateProxyWhenElapsedForProxyPidMap(int32_t uid, int pid,
570     const std::chrono::steady_clock::time_point &now,
571     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
572 {
573     uint64_t key = GetProxyKey(uid, pid);
574     auto it = proxyPids_.find(key);
575     if (it != proxyPids_.end()) {
576         TIME_HILOGD(TIME_MODULE_SERVICE, "pid is already proxy, pid: %{public}d", pid);
577         return;
578     }
579 
580     std::lock_guard<std::mutex> lockUidTimers(pidTimersMutex_);
581     if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
582         TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, pid: %{public}d", pid);
583         std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
584         proxyPids_.insert(std::make_pair(key, timePointMap));
585         return;
586     }
587 
588     std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
589     for (auto itPidTimersMap = pidTimersMap_.at(pid).begin(); itPidTimersMap!= pidTimersMap_.at(pid).end();
590         ++itPidTimersMap) {
591         if (uid == itPidTimersMap->second->uid) {
592             timePointMap.insert(std::make_pair(itPidTimersMap->first, itPidTimersMap->second->whenElapsed));
593             itPidTimersMap->second->UpdateWhenElapsedFromNow(now, milliseconds(proxyDelayTime_));
594             TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy pid map. "
595                 "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
596                 itPidTimersMap->second->pid, itPidTimersMap->second->id,
597                 itPidTimersMap->second->whenElapsed.time_since_epoch().count(),
598                 now.time_since_epoch().count());
599             insertAlarmCallback(itPidTimersMap->second);
600         }
601     }
602     proxyPids_.insert(std::make_pair(key, timePointMap));
603 }
604 
RestoreProxyWhenElapsedByUid(const int32_t uid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)605 bool TimerProxy::RestoreProxyWhenElapsedByUid(const int32_t uid,
606     const std::chrono::steady_clock::time_point &now,
607     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
608 {
609     auto it = proxyUids_.find(uid);
610     if (it == proxyUids_.end()) {
611         TIME_HILOGD(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list.", uid);
612         return false;
613     }
614 
615     std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
616     if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
617         TIME_HILOGD(TIME_MODULE_SERVICE, "uid timer info map not found, just erase proxy map. uid: %{public}d", uid);
618         return true;
619     }
620 
621     for (auto itProxyUids = proxyUids_.at(uid).begin(); itProxyUids != proxyUids_.at(uid).end(); ++itProxyUids) {
622         auto itTimerInfo = uidTimersMap_.at(uid).find(itProxyUids->first);
623         if (itTimerInfo == uidTimersMap_.at(uid).end()) {
624             continue;
625         }
626         if (itProxyUids->second > now + milliseconds(MILLI_TO_SECOND)) {
627             auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyUids->second - now);
628             itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
629         } else {
630             itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
631         }
632         TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by uid. "
633             "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
634             itTimerInfo->second->uid, itTimerInfo->second->id,
635             itTimerInfo->second->whenElapsed.time_since_epoch().count(),
636             now.time_since_epoch().count());
637         insertAlarmCallback(itTimerInfo->second);
638     }
639 
640     return true;
641 }
642 
RestoreProxyWhenElapsedByPid(const int uid,const int pid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)643 bool TimerProxy::RestoreProxyWhenElapsedByPid(const int uid, const int pid,
644     const std::chrono::steady_clock::time_point &now,
645     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
646 {
647     uint64_t key = GetProxyKey(uid, pid);
648     auto it = proxyPids_.find(key);
649     if (it == proxyPids_.end()) {
650         TIME_HILOGD(TIME_MODULE_SERVICE, "Pid: %{public}d doesn't exist in the proxy list.", pid);
651         return false;
652     }
653     std::lock_guard<std::mutex> lockPidTimers(pidTimersMutex_);
654     if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
655         TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, just erase proxy map. pid: %{public}d", pid);
656         return true;
657     }
658     for (auto itProxyPids = proxyPids_.at(key).begin(); itProxyPids != proxyPids_.at(key).end(); ++itProxyPids) {
659         auto itTimerInfo = pidTimersMap_.at(pid).find(itProxyPids->first);
660         if (itTimerInfo == pidTimersMap_.at(pid).end()) {
661             continue;
662         }
663         if (itProxyPids->second > now + milliseconds(MILLI_TO_SECOND)) {
664             auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyPids->second - now);
665             itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
666         } else {
667             itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
668         }
669         TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by pid. "
670             "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
671             itTimerInfo->second->pid, itTimerInfo->second->id,
672             itTimerInfo->second->whenElapsed.time_since_epoch().count(),
673             now.time_since_epoch().count());
674         insertAlarmCallback(itTimerInfo->second);
675     }
676 
677     return true;
678 }
679 
680 // 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)681 bool TimerProxy::RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid,
682     const std::chrono::steady_clock::time_point &now,
683     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
684 {
685     bool ret = RestoreProxyWhenElapsedByUid(uid, now, insertAlarmCallback);
686     if (ret) {
687         proxyUids_.erase(uid);
688     }
689     return ret;
690 }
691 
RestoreProxyWhenElapsedForProxyPidMap(const int uid,const int pid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)692 bool TimerProxy::RestoreProxyWhenElapsedForProxyPidMap(const int uid, const int pid,
693     const std::chrono::steady_clock::time_point &now,
694     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
695 {
696     uint64_t key = GetProxyKey(uid, pid);
697     bool ret = RestoreProxyWhenElapsedByPid(uid, pid, now, insertAlarmCallback);
698     if (ret) {
699         proxyPids_.erase(key);
700     }
701     return ret;
702 }
703 
704 
ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)705 void TimerProxy::ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
706     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
707 {
708     std::lock_guard<std::mutex> lockProxy(proxyMutex_);
709     for (auto it = proxyUids_.begin(); it != proxyUids_.end(); ++it) {
710         RestoreProxyWhenElapsedByUid(it->first, now, insertAlarmCallback);
711     }
712     proxyUids_.clear();
713 }
714 
ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)715 void TimerProxy::ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
716     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
717 {
718     std::lock_guard<std::mutex> lockProxy(proxyPidMutex_);
719     for (auto it = proxyPids_.begin(); it != proxyPids_.end(); ++it) {
720         auto uid = static_cast<uint32_t>(it->first >> UID_PROXY_OFFSET);
721         auto pid = it->first & ((static_cast<uint64_t>(1) << UID_PROXY_OFFSET) - 1);
722         RestoreProxyWhenElapsedByPid(uid, pid, now, insertAlarmCallback);
723     }
724     proxyPids_.clear();
725 }
726 
ShowProxyTimerInfo(int fd,const int64_t now)727 bool TimerProxy::ShowProxyTimerInfo(int fd, const int64_t now)
728 {
729     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
730     std::lock_guard<std::mutex> lockProxy(proxyMutex_);
731     dprintf(fd, "current time %lld\n", now);
732     for (auto itProxyUids = proxyUids_.begin(); itProxyUids != proxyUids_.end(); ++itProxyUids) {
733         dprintf(fd, " - proxy uid = %lu\n", itProxyUids->first);
734         for (auto itTimerIdMap = itProxyUids->second.begin(); itTimerIdMap != itProxyUids->second.end();
735             ++itTimerIdMap) {
736             dprintf(fd, "   * save timer id          = %llu\n", itTimerIdMap->first);
737             dprintf(fd, "   * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
738         }
739     }
740     std::lock_guard<std::mutex> lockPidProxy(proxyPidMutex_);
741     dprintf(fd, "current time %lld\n", now);
742     for (auto itProxyPids = proxyPids_.begin(); itProxyPids != proxyPids_.end(); ++itProxyPids) {
743         dprintf(fd, " - proxy pid = %lu\n", itProxyPids->first);
744         for (auto itTimerIdMap = itProxyPids->second.begin(); itTimerIdMap != itProxyPids->second.end();
745             ++itTimerIdMap) {
746             dprintf(fd, "   * save timer id          = %llu\n", itTimerIdMap->first);
747             dprintf(fd, "   * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
748         }
749     }
750     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
751     return true;
752 }
753 
ShowUidTimerMapInfo(int fd,const int64_t now)754 bool TimerProxy::ShowUidTimerMapInfo(int fd, const int64_t now)
755 {
756     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
757     std::lock_guard<std::mutex> lockProxy(uidTimersMutex_);
758     dprintf(fd, "current time %lld\n", now);
759     for (auto itTimerInfoMap = uidTimersMap_.begin(); itTimerInfoMap != uidTimersMap_.end(); ++itTimerInfoMap) {
760             dprintf(fd, " - uid = %lu\n", itTimerInfoMap->first);
761         for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
762             ++itTimerInfo) {
763             dprintf(fd, "   * timer id          = %llu\n", itTimerInfo->second->id);
764             dprintf(fd, "   * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
765         }
766     }
767     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
768     return true;
769 }
770 
ShowPidTimerMapInfo(int fd,const int64_t now)771 bool TimerProxy::ShowPidTimerMapInfo(int fd, const int64_t now)
772 {
773     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
774     std::lock_guard<std::mutex> lockProxy(pidTimersMutex_);
775     dprintf(fd, "current time %lld\n", now);
776     for (auto itTimerInfoMap = pidTimersMap_.begin(); itTimerInfoMap != pidTimersMap_.end(); ++itTimerInfoMap) {
777             dprintf(fd, " - pid = %lu\n", itTimerInfoMap->first);
778         for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
779             ++itTimerInfo) {
780             dprintf(fd, "   * timer id          = %llu\n", itTimerInfo->second->id);
781             dprintf(fd, "   * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
782         }
783     }
784     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
785     return true;
786 }
787 
788 
ShowAdjustTimerInfo(int fd)789 void TimerProxy::ShowAdjustTimerInfo(int fd)
790 {
791     std::lock_guard<std::mutex> lockProxy(adjustMutex_);
792     dprintf(fd, "show adjust timer");
793     for (auto timer : adjustTimers_) {
794         dprintf(fd, " * timer id            = %lu\n", timer->id);
795         dprintf(fd, " * timer uid           = %d\n\n", timer->uid);
796         dprintf(fd, " * timer bundleName           = %s\n\n", timer->bundleName.c_str());
797         dprintf(fd, " * timer originWhenElapsed           = %lld\n\n", timer->originWhenElapsed);
798         dprintf(fd, " * timer whenElapsed           = %lld\n\n", timer->whenElapsed);
799         dprintf(fd, " * timer originMaxWhenElapsed           = %lld\n\n", timer->originMaxWhenElapsed);
800         dprintf(fd, " * timer maxWhenElapsed           = %lld\n\n", timer->maxWhenElapsed);
801     }
802 }
803 
ShowProxyDelayTime(int fd)804 bool TimerProxy::ShowProxyDelayTime(int fd)
805 {
806     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
807     dprintf(fd, "proxy delay time: %lld ms\n", proxyDelayTime_);
808     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
809     return true;
810 }
811 
GetProxyDelayTime() const812 int64_t TimerProxy::GetProxyDelayTime() const
813 {
814     return proxyDelayTime_;
815 }
816 } // MiscServices
817 } // OHOS