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
23namespace OHOS {
24namespace MiscServices {
25using namespace std::chrono;
26using namespace OHOS::AppExecFwk;
27
28namespace {
29constexpr int MILLI_TO_SECOND =  1000;
30}
31
32IMPLEMENT_SINGLE_INSTANCE(TimerProxy)
33
34void 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
53void 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
72int32_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
123bool 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
162bool TimerProxy::PidProxyTimer(int pid, bool isProxy, bool needRetrigger,
163    const std::chrono::steady_clock::time_point &now,
164    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
165{
166    TIME_HILOGD(TIME_MODULE_SERVICE, "start. pid=%{public}d, isProxy=%{public}u, needRetrigger=%{public}u",
167        pid, isProxy, needRetrigger);
168
169    std::lock_guard<std::mutex> lockProxy(proxyPidMutex_);
170    if (isProxy) {
171        UpdateProxyWhenElapsedForProxyPidMap(pid, now, insertAlarmCallback);
172        return true;
173    }
174
175    if (!RestoreProxyWhenElapsedForProxyPidMap(pid, now, insertAlarmCallback)) {
176        TIME_HILOGE(TIME_MODULE_SERVICE, "Pid: %{public}d doesn't exist in the proxy list." PRId64 "", pid);
177        return false;
178    }
179
180    if (!needRetrigger) {
181        TIME_HILOGI(TIME_MODULE_SERVICE, "ProxyTimer doesn't need retrigger, clear all callbacks!");
182        proxyPidMap_.erase(pid);
183        return true;
184    }
185
186    auto itMap = proxyPidMap_.find(pid);
187    if (itMap != proxyPidMap_.end()) {
188        auto timeInfoVec = itMap->second;
189        for (const auto& alarm : timeInfoVec) {
190            if (!alarm->callback) {
191                TIME_HILOGE(TIME_MODULE_SERVICE, "ProxyTimer Callback is nullptr!");
192                continue;
193            }
194            alarm->callback(alarm->id);
195            TIME_HILOGD(TIME_MODULE_SERVICE, "Shut down proxy, proxyPid: %{public}d, alarmId: %{public}" PRId64 "",
196                pid, alarm->id);
197        }
198        timeInfoVec.clear();
199        proxyPidMap_.erase(pid);
200    }
201    return true;
202}
203
204bool 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
224bool 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
239bool 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
252bool 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
266bool 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
275void 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
294void 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
313bool 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
324void 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
335void 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
346void 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
356void 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
380void 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
404void 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
423void 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
435void 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
447void 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
466void 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
484void 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
502bool 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
512bool 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
523void 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
556void TimerProxy::UpdateProxyWhenElapsedForProxyPidMap(int pid,
557    const std::chrono::steady_clock::time_point &now,
558    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
559{
560    auto it = proxyPids_.find(pid);
561    if (it != proxyPids_.end()) {
562        TIME_HILOGD(TIME_MODULE_SERVICE, "pid is already proxy, pid: %{public}d", pid);
563        return;
564    }
565
566    std::lock_guard<std::mutex> lockUidTimers(pidTimersMutex_);
567    if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
568        TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, pid: %{public}d", pid);
569        std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
570        proxyPids_.insert(std::make_pair(pid, timePointMap));
571        return;
572    }
573
574    std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
575    for (auto itPidTimersMap = pidTimersMap_.at(pid).begin(); itPidTimersMap!= pidTimersMap_.at(pid).end();
576        ++itPidTimersMap) {
577        timePointMap.insert(std::make_pair(itPidTimersMap->first, itPidTimersMap->second->whenElapsed));
578        itPidTimersMap->second->UpdateWhenElapsedFromNow(now, milliseconds(proxyDelayTime_));
579        TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy pid map. "
580            "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
581            itPidTimersMap->second->pid, itPidTimersMap->second->id,
582            itPidTimersMap->second->whenElapsed.time_since_epoch().count(),
583            now.time_since_epoch().count());
584        insertAlarmCallback(itPidTimersMap->second);
585    }
586    proxyPids_.insert(std::make_pair(pid, timePointMap));
587}
588
589bool TimerProxy::RestoreProxyWhenElapsedByUid(const int32_t uid,
590    const std::chrono::steady_clock::time_point &now,
591    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
592{
593    auto it = proxyUids_.find(uid);
594    if (it == proxyUids_.end()) {
595        TIME_HILOGD(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list.", uid);
596        return false;
597    }
598
599    std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
600    if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
601        TIME_HILOGD(TIME_MODULE_SERVICE, "uid timer info map not found, just erase proxy map. uid: %{public}d", uid);
602        return true;
603    }
604
605    for (auto itProxyUids = proxyUids_.at(uid).begin(); itProxyUids != proxyUids_.at(uid).end(); ++itProxyUids) {
606        auto itTimerInfo = uidTimersMap_.at(uid).find(itProxyUids->first);
607        if (itTimerInfo == uidTimersMap_.at(uid).end()) {
608            continue;
609        }
610        if (itProxyUids->second > now + milliseconds(MILLI_TO_SECOND)) {
611            auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyUids->second - now);
612            itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
613        } else {
614            itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
615        }
616        TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by uid. "
617            "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
618            itTimerInfo->second->uid, itTimerInfo->second->id,
619            itTimerInfo->second->whenElapsed.time_since_epoch().count(),
620            now.time_since_epoch().count());
621        insertAlarmCallback(itTimerInfo->second);
622    }
623
624    return true;
625}
626
627bool TimerProxy::RestoreProxyWhenElapsedByPid(const int pid,
628    const std::chrono::steady_clock::time_point &now,
629    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
630{
631    auto it = proxyPids_.find(pid);
632    if (it == proxyPids_.end()) {
633        TIME_HILOGD(TIME_MODULE_SERVICE, "Pid: %{public}d doesn't exist in the proxy list.", pid);
634        return false;
635    }
636    std::lock_guard<std::mutex> lockPidTimers(pidTimersMutex_);
637    if (pidTimersMap_.find(pid) == pidTimersMap_.end()) {
638        TIME_HILOGD(TIME_MODULE_SERVICE, "pid timer info map not found, just erase proxy map. pid: %{public}d", pid);
639        return true;
640    }
641    for (auto itProxyPids = proxyPids_.at(pid).begin(); itProxyPids != proxyPids_.at(pid).end(); ++itProxyPids) {
642        auto itTimerInfo = pidTimersMap_.at(pid).find(itProxyPids->first);
643        if (itTimerInfo == pidTimersMap_.at(pid).end()) {
644            continue;
645        }
646        if (itProxyPids->second > now + milliseconds(MILLI_TO_SECOND)) {
647            auto interval = std::chrono::duration_cast<std::chrono::nanoseconds>(itProxyPids->second - now);
648            itTimerInfo->second->UpdateWhenElapsedFromNow(now, interval);
649        } else {
650            itTimerInfo->second->UpdateWhenElapsedFromNow(now, milliseconds(MILLI_TO_SECOND));
651        }
652        TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by pid. "
653            "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
654            itTimerInfo->second->pid, itTimerInfo->second->id,
655            itTimerInfo->second->whenElapsed.time_since_epoch().count(),
656            now.time_since_epoch().count());
657        insertAlarmCallback(itTimerInfo->second);
658    }
659
660    return true;
661}
662
663// needs to acquire the lock `proxyMutex_` before calling this method
664bool TimerProxy::RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid,
665    const std::chrono::steady_clock::time_point &now,
666    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
667{
668    bool ret = RestoreProxyWhenElapsedByUid(uid, now, insertAlarmCallback);
669    if (ret) {
670        proxyUids_.erase(uid);
671    }
672    return ret;
673}
674
675bool TimerProxy::RestoreProxyWhenElapsedForProxyPidMap(const int pid,
676    const std::chrono::steady_clock::time_point &now,
677    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
678{
679    bool ret = RestoreProxyWhenElapsedByPid(pid, now, insertAlarmCallback);
680    if (ret) {
681        proxyPids_.erase(pid);
682    }
683    return ret;
684}
685
686
687void TimerProxy::ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
688    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
689{
690    std::lock_guard<std::mutex> lockProxy(proxyMutex_);
691    for (auto it = proxyUids_.begin(); it != proxyUids_.end(); ++it) {
692        RestoreProxyWhenElapsedByUid(it->first, now, insertAlarmCallback);
693    }
694    proxyUids_.clear();
695}
696
697void TimerProxy::ResetAllPidProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
698    std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
699{
700    std::lock_guard<std::mutex> lockProxy(proxyPidMutex_);
701    for (auto it = proxyPids_.begin(); it != proxyPids_.end(); ++it) {
702        RestoreProxyWhenElapsedByPid(it->first, now, insertAlarmCallback);
703    }
704    proxyPids_.clear();
705}
706
707bool TimerProxy::ShowProxyTimerInfo(int fd, const int64_t now)
708{
709    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
710    std::lock_guard<std::mutex> lockProxy(proxyMutex_);
711    dprintf(fd, "current time %lld\n", now);
712    for (auto itProxyUids = proxyUids_.begin(); itProxyUids != proxyUids_.end(); ++itProxyUids) {
713        dprintf(fd, " - proxy uid = %lu\n", itProxyUids->first);
714        for (auto itTimerIdMap = itProxyUids->second.begin(); itTimerIdMap != itProxyUids->second.end();
715            ++itTimerIdMap) {
716            dprintf(fd, "   * save timer id          = %llu\n", itTimerIdMap->first);
717            dprintf(fd, "   * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
718        }
719    }
720    std::lock_guard<std::mutex> lockPidProxy(proxyPidMutex_);
721    dprintf(fd, "current time %lld\n", now);
722    for (auto itProxyPids = proxyPids_.begin(); itProxyPids != proxyPids_.end(); ++itProxyPids) {
723        dprintf(fd, " - proxy pid = %lu\n", itProxyPids->first);
724        for (auto itTimerIdMap = itProxyPids->second.begin(); itTimerIdMap != itProxyPids->second.end();
725            ++itTimerIdMap) {
726            dprintf(fd, "   * save timer id          = %llu\n", itTimerIdMap->first);
727            dprintf(fd, "   * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
728        }
729    }
730    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
731    return true;
732}
733
734bool TimerProxy::ShowUidTimerMapInfo(int fd, const int64_t now)
735{
736    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
737    std::lock_guard<std::mutex> lockProxy(uidTimersMutex_);
738    dprintf(fd, "current time %lld\n", now);
739    for (auto itTimerInfoMap = uidTimersMap_.begin(); itTimerInfoMap != uidTimersMap_.end(); ++itTimerInfoMap) {
740            dprintf(fd, " - uid = %lu\n", itTimerInfoMap->first);
741        for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
742            ++itTimerInfo) {
743            dprintf(fd, "   * timer id          = %llu\n", itTimerInfo->second->id);
744            dprintf(fd, "   * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
745        }
746    }
747    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
748    return true;
749}
750
751bool TimerProxy::ShowPidTimerMapInfo(int fd, const int64_t now)
752{
753    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
754    std::lock_guard<std::mutex> lockProxy(pidTimersMutex_);
755    dprintf(fd, "current time %lld\n", now);
756    for (auto itTimerInfoMap = pidTimersMap_.begin(); itTimerInfoMap != pidTimersMap_.end(); ++itTimerInfoMap) {
757            dprintf(fd, " - pid = %lu\n", itTimerInfoMap->first);
758        for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
759            ++itTimerInfo) {
760            dprintf(fd, "   * timer id          = %llu\n", itTimerInfo->second->id);
761            dprintf(fd, "   * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
762        }
763    }
764    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
765    return true;
766}
767
768
769void TimerProxy::ShowAdjustTimerInfo(int fd)
770{
771    std::lock_guard<std::mutex> lockProxy(adjustMutex_);
772    dprintf(fd, "show adjust timer");
773    for (auto timer : adjustTimers_) {
774        dprintf(fd, " * timer id            = %lu\n", timer->id);
775        dprintf(fd, " * timer uid           = %d\n\n", timer->uid);
776        dprintf(fd, " * timer bundleName           = %s\n\n", timer->bundleName.c_str());
777        dprintf(fd, " * timer originWhenElapsed           = %lld\n\n", timer->originWhenElapsed);
778        dprintf(fd, " * timer whenElapsed           = %lld\n\n", timer->whenElapsed);
779        dprintf(fd, " * timer originMaxWhenElapsed           = %lld\n\n", timer->originMaxWhenElapsed);
780        dprintf(fd, " * timer maxWhenElapsed           = %lld\n\n", timer->maxWhenElapsed);
781    }
782}
783
784bool TimerProxy::ShowProxyDelayTime(int fd)
785{
786    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
787    dprintf(fd, "proxy delay time: %lld ms\n", proxyDelayTime_);
788    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
789    return true;
790}
791
792int64_t TimerProxy::GetProxyDelayTime() const
793{
794    return proxyDelayTime_;
795}
796} // MiscServices
797} // OHOS