• 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 
19 #include "timer_proxy.h"
20 #include "time_hilog.h"
21 
22 namespace OHOS {
23 namespace MiscServices {
24 using namespace std::chrono;
25 using namespace OHOS::AppExecFwk;
26 
27 namespace {
28 constexpr int MILLI_TO_SECOND =  1000;
29 /* ms for 3 days */
30 constexpr int64_t PROXY_DELAY_TIME_IN_MILLI = 3 * 24 * 60 * 60 * 1000;
31 }
32 
IMPLEMENT_SINGLE_INSTANCE(TimerProxy)33 IMPLEMENT_SINGLE_INSTANCE(TimerProxy)
34 
35 void TimerProxy::RemoveProxy(uint64_t timerNumber, int32_t uid)
36 {
37     std::lock_guard<std::mutex> lock(proxyMutex_);
38     auto itMap = proxyMap_.find(uid);
39     if (itMap != proxyMap_.end()) {
40         auto alarms = itMap->second;
41         for (auto itAlarm = alarms.begin(); itAlarm != alarms.end();) {
42             if ((*itAlarm)->id == timerNumber) {
43                 alarms.erase(itAlarm);
44             }
45             itAlarm++;
46         }
47         if (alarms.empty()) {
48             proxyMap_.erase(uid);
49         }
50     }
51 }
52 
CallbackAlarmIfNeed(const std::shared_ptr<TimerInfo> & alarm)53 void TimerProxy::CallbackAlarmIfNeed(const std::shared_ptr<TimerInfo> &alarm)
54 {
55     if (alarm == nullptr) {
56         TIME_HILOGE(TIME_MODULE_SERVICE, "callback alarm is nullptr!");
57         return;
58     }
59 
60     int uid = alarm->uid;
61     std::lock_guard<std::mutex> lock(proxyMutex_);
62     auto it = proxyUids_.find(uid);
63     if (it == proxyUids_.end()) {
64         alarm->callback(alarm->id);
65         TIME_HILOGI(TIME_MODULE_SERVICE, "Trigger id: %{public}" PRId64 "", alarm->id);
66         return;
67     }
68 
69     TIME_HILOGD(TIME_MODULE_SERVICE, "Alarm is proxy!");
70     auto itMap = proxyMap_.find(uid);
71     if (itMap == proxyMap_.end()) {
72         std::vector<std::shared_ptr<TimerInfo>> timeInfoVec;
73         timeInfoVec.push_back(alarm);
74         proxyMap_[uid] = timeInfoVec;
75     } else {
76         std::vector<std::shared_ptr<TimerInfo>> timeInfoVec = itMap->second;
77         timeInfoVec.push_back(alarm);
78         proxyMap_[uid] = timeInfoVec;
79     }
80 }
81 
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)82 bool TimerProxy::ProxyTimer(int32_t uid, bool isProxy, bool needRetrigger,
83     const std::chrono::steady_clock::time_point &now,
84     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
85 {
86     TIME_HILOGD(TIME_MODULE_SERVICE, "start. uid=%{public}d, isProxy=%{public}u, needRetrigger=%{public}u",
87         uid, isProxy, needRetrigger);
88     if (isProxy) {
89         UpdateProxyWhenElapsedForProxyUidMap(uid, now, insertAlarmCallback);
90         return true;
91     }
92     if (!RestoreProxyWhenElapsedForProxyUidMap(uid, now, insertAlarmCallback)) {
93         TIME_HILOGE(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list." PRId64 "", uid);
94         return false;
95     }
96 
97     if (!needRetrigger) {
98         TIME_HILOGI(TIME_MODULE_SERVICE, "ProxyTimer doesn't need retrigger, clear all callbacks!");
99         proxyMap_.erase(uid);
100         return true;
101     }
102     auto itMap = proxyMap_.find(uid);
103     if (itMap != proxyMap_.end()) {
104         auto timeInfoVec = itMap->second;
105         for (const auto& alarm : timeInfoVec) {
106             if (!alarm->callback) {
107                 TIME_HILOGE(TIME_MODULE_SERVICE, "ProxyTimer Callback is nullptr!");
108                 continue;
109             }
110             alarm->callback(alarm->id);
111             TIME_HILOGD(TIME_MODULE_SERVICE, "Shut down proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
112                 uid, alarm->id);
113         }
114         timeInfoVec.clear();
115         proxyMap_.erase(uid);
116     }
117     return true;
118 }
119 
ResetProxyMaps()120 void TimerProxy::ResetProxyMaps()
121 {
122     std::lock_guard<std::mutex> lock(proxyMutex_);
123     for (auto it = proxyMap_.begin(); it != proxyMap_.end(); it++) {
124         auto timeInfoVec = it->second;
125         for (const auto& alarm : timeInfoVec) {
126             if (!alarm->callback) {
127                 TIME_HILOGE(TIME_MODULE_SERVICE, "Callback is nullptr!");
128                 continue;
129             }
130             alarm->callback(alarm->id);
131             TIME_HILOGD(TIME_MODULE_SERVICE, "Reset all proxy, proxyUid: %{public}d, alarmId: %{public}" PRId64 "",
132                 it->first, alarm->id);
133         }
134         timeInfoVec.clear();
135     }
136     proxyMap_.clear();
137 }
138 
ResetAllProxy(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)139 bool TimerProxy::ResetAllProxy(const std::chrono::steady_clock::time_point &now,
140     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
141 {
142     TIME_HILOGD(TIME_MODULE_SERVICE, "start");
143     ResetProxyMaps();
144     ResetAllProxyWhenElapsed(now, insertAlarmCallback);
145     return true;
146 }
147 
EraseTimerFromProxyUidMap(const uint64_t id,const uint32_t uid)148 void TimerProxy::EraseTimerFromProxyUidMap(const uint64_t id, const uint32_t uid)
149 {
150     TIME_HILOGD(TIME_MODULE_SERVICE, "erase timer from proxy timer map, id=%{public}" PRId64 ", uid=%{public}u",
151         id, uid);
152     std::lock_guard<std::mutex> lock(proxyMutex_);
153     auto it = proxyUids_.find(uid);
154     if (it != proxyUids_.end()) {
155         it->second.erase(id);
156     }
157 }
158 
EraseAlarmItem(const uint64_t id,std::unordered_map<uint64_t,std::shared_ptr<TimerInfo>> & idAlarmsMap)159 void TimerProxy::EraseAlarmItem(
160     const uint64_t id, std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> &idAlarmsMap)
161 {
162     auto itAlarms = idAlarmsMap.find(id);
163     if (itAlarms != idAlarmsMap.end()) {
164         TIME_HILOGD(TIME_MODULE_SERVICE, "timer already exists, id=%{public}" PRId64 "", id);
165         idAlarmsMap.erase(itAlarms);
166     }
167 }
168 
RecordUidTimerMap(const std::shared_ptr<TimerInfo> & alarm,const bool isRebatched)169 void TimerProxy::RecordUidTimerMap(const std::shared_ptr<TimerInfo> &alarm, const bool isRebatched)
170 {
171     if (isRebatched) {
172         TIME_HILOGD(TIME_MODULE_SERVICE, "Record uid timer info map, isRebatched: %{public}d", isRebatched);
173         return;
174     }
175     if (alarm == nullptr) {
176         TIME_HILOGE(TIME_MODULE_SERVICE, "record uid timer map alarm is nullptr!");
177         return;
178     }
179 
180     std::lock_guard<std::mutex> lock(uidTimersMutex_);
181     auto it = uidTimersMap_.find(alarm->uid);
182     if (it == uidTimersMap_.end()) {
183         std::unordered_map<uint64_t, std::shared_ptr<TimerInfo>> idAlarmsMap;
184         idAlarmsMap.insert(std::make_pair(alarm->id, alarm));
185         uidTimersMap_.insert(std::make_pair(alarm->uid, idAlarmsMap));
186         return;
187     }
188 
189     EraseAlarmItem(alarm->id, it->second);
190     it->second.insert(std::make_pair(alarm->id, alarm));
191 }
192 
RemoveUidTimerMap(const std::shared_ptr<TimerInfo> & alarm)193 void TimerProxy::RemoveUidTimerMap(const std::shared_ptr<TimerInfo> &alarm)
194 {
195     if (alarm == nullptr) {
196         TIME_HILOGE(TIME_MODULE_SERVICE, "remove uid timer map alarm is nullptr!");
197         return;
198     }
199 
200     std::lock_guard<std::mutex> lock(uidTimersMutex_);
201     auto it = uidTimersMap_.find(alarm->uid);
202     if (it == uidTimersMap_.end()) {
203         return;
204     }
205 
206     EraseAlarmItem(alarm->id, it->second);
207     if (it->second.empty()) {
208         uidTimersMap_.erase(it);
209     }
210 }
211 
RemoveUidTimerMap(const uint64_t id)212 void TimerProxy::RemoveUidTimerMap(const uint64_t id)
213 {
214     std::lock_guard<std::mutex> lock(uidTimersMutex_);
215     for (auto itUidsTimer = uidTimersMap_.begin(); itUidsTimer!= uidTimersMap_.end(); ++itUidsTimer) {
216         for (auto itTimerId = itUidsTimer->second.begin(); itTimerId!= itUidsTimer->second.end(); ++itTimerId) {
217             if (itTimerId->first != id) {
218                 continue;
219             }
220 
221             itUidsTimer->second.erase(itTimerId);
222             if (itUidsTimer->second.empty()) {
223                 uidTimersMap_.erase(itUidsTimer);
224             }
225             return;
226         }
227     }
228 }
229 
IsUidProxy(const int32_t uid)230 bool TimerProxy::IsUidProxy(const int32_t uid)
231 {
232     std::lock_guard<std::mutex> lock(proxyMutex_);
233     auto it = proxyUids_.find(uid);
234     if (it == proxyUids_.end()) {
235         return false;
236     }
237     return true;
238 }
239 
UpdateProxyWhenElapsedForProxyUidMap(const int32_t uid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)240 void TimerProxy::UpdateProxyWhenElapsedForProxyUidMap(const int32_t uid,
241     const std::chrono::steady_clock::time_point &now,
242     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
243 {
244     std::lock_guard<std::mutex> lockProxy(proxyMutex_);
245     auto it = proxyUids_.find(uid);
246     if (it != proxyUids_.end()) {
247         TIME_HILOGI(TIME_MODULE_SERVICE, "uid is already proxy, uid: %{public}d", uid);
248         return;
249     }
250 
251     std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
252     if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
253         TIME_HILOGI(TIME_MODULE_SERVICE, "uid timer info map not found, uid: %{public}d", uid);
254         std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
255         proxyUids_.insert(std::make_pair(uid, timePointMap));
256         return;
257     }
258 
259     std::unordered_map<uint64_t, std::chrono::steady_clock::time_point> timePointMap {};
260     for (auto itUidTimersMap = uidTimersMap_.at(uid).begin(); itUidTimersMap!= uidTimersMap_.at(uid).end();
261         ++itUidTimersMap) {
262         timePointMap.insert(std::make_pair(itUidTimersMap->first, itUidTimersMap->second->whenElapsed));
263         itUidTimersMap->second->UpdateWhenElapsed(now, milliseconds(proxyDelayTime_));
264         TIME_HILOGD(TIME_MODULE_SERVICE, "Update proxy WhenElapsed for proxy uid map. "
265             "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
266             itUidTimersMap->second->uid, itUidTimersMap->second->id,
267             itUidTimersMap->second->whenElapsed.time_since_epoch().count(),
268             now.time_since_epoch().count());
269         insertAlarmCallback(itUidTimersMap->second);
270     }
271     proxyUids_.insert(std::make_pair(uid, timePointMap));
272 }
273 
RestoreProxyWhenElapsedByUid(const int32_t uid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)274 bool TimerProxy::RestoreProxyWhenElapsedByUid(const int32_t uid,
275     const std::chrono::steady_clock::time_point &now,
276     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
277 {
278     auto it = proxyUids_.find(uid);
279     if (it == proxyUids_.end()) {
280         TIME_HILOGI(TIME_MODULE_SERVICE, "Uid: %{public}d doesn't exist in the proxy list.", uid);
281         return false;
282     }
283 
284     std::lock_guard<std::mutex> lockUidTimers(uidTimersMutex_);
285     if (uidTimersMap_.find(uid) == uidTimersMap_.end()) {
286         TIME_HILOGI(TIME_MODULE_SERVICE, "uid timer info map not found, just erase proxy map. uid: %{public}d", uid);
287         return true;
288     }
289 
290     for (auto itProxyUids = proxyUids_.at(uid).begin(); itProxyUids != proxyUids_.at(uid).end(); ++itProxyUids) {
291         auto itTimerInfo = uidTimersMap_.at(uid).find(itProxyUids->first);
292         if (itTimerInfo == uidTimersMap_.at(uid).end()) {
293             continue;
294         }
295         if (itProxyUids->second > now + milliseconds(MILLI_TO_SECOND)) {
296             itTimerInfo->second->UpdateWhenElapsed(itProxyUids->second, milliseconds(0));
297         } else {
298             itTimerInfo->second->UpdateWhenElapsed(now, milliseconds(MILLI_TO_SECOND));
299         }
300         TIME_HILOGD(TIME_MODULE_SERVICE, "Restore proxy WhenElapsed by uid. "
301             "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
302             itTimerInfo->second->uid, itTimerInfo->second->id,
303             itTimerInfo->second->whenElapsed.time_since_epoch().count(),
304             now.time_since_epoch().count());
305         insertAlarmCallback(itTimerInfo->second);
306     }
307 
308     return true;
309 }
310 
RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid,const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)311 bool TimerProxy::RestoreProxyWhenElapsedForProxyUidMap(const int32_t uid,
312     const std::chrono::steady_clock::time_point &now,
313     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
314 {
315     std::lock_guard<std::mutex> lockProxy(proxyMutex_);
316     bool ret = RestoreProxyWhenElapsedByUid(uid, now, insertAlarmCallback);
317     if (ret) {
318         proxyUids_.erase(uid);
319     }
320     return ret;
321 }
322 
ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point & now,std::function<void (std::shared_ptr<TimerInfo> & alarm)> insertAlarmCallback)323 void TimerProxy::ResetAllProxyWhenElapsed(const std::chrono::steady_clock::time_point &now,
324     std::function<void(std::shared_ptr<TimerInfo> &alarm)> insertAlarmCallback)
325 {
326     std::lock_guard<std::mutex> lockProxy(proxyMutex_);
327     for (auto it = proxyUids_.begin(); it != proxyUids_.end(); ++it) {
328         RestoreProxyWhenElapsedByUid(it->first, now, insertAlarmCallback);
329     }
330     proxyUids_.clear();
331 }
332 
ShowProxyTimerInfo(int fd,const int64_t now)333 bool TimerProxy::ShowProxyTimerInfo(int fd, const int64_t now)
334 {
335     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
336     std::lock_guard<std::mutex> lockProxy(proxyMutex_);
337     dprintf(fd, "current time %lld\n", now);
338     for (auto itProxyUids = proxyUids_.begin(); itProxyUids != proxyUids_.end(); ++itProxyUids) {
339             dprintf(fd, " - proxy uid = %lu\n", itProxyUids->first);
340         for (auto itTimerIdMap = itProxyUids->second.begin(); itTimerIdMap != itProxyUids->second.end();
341             ++itTimerIdMap) {
342             dprintf(fd, "   * save timer id          = %llu\n", itTimerIdMap->first);
343             dprintf(fd, "   * save timer whenElapsed = %lld\n", itTimerIdMap->second.time_since_epoch().count());
344         }
345     }
346     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
347     return true;
348 }
349 
ShowUidTimerMapInfo(int fd,const int64_t now)350 bool TimerProxy::ShowUidTimerMapInfo(int fd, const int64_t now)
351 {
352     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
353     std::lock_guard<std::mutex> lockProxy(uidTimersMutex_);
354     dprintf(fd, "current time %lld\n", now);
355     for (auto itTimerInfoMap = uidTimersMap_.begin(); itTimerInfoMap != uidTimersMap_.end(); ++itTimerInfoMap) {
356             dprintf(fd, " - uid = %lu\n", itTimerInfoMap->first);
357         for (auto itTimerInfo = itTimerInfoMap->second.begin(); itTimerInfo != itTimerInfoMap->second.end();
358             ++itTimerInfo) {
359             dprintf(fd, "   * timer id          = %llu\n", itTimerInfo->second->id);
360             dprintf(fd, "   * timer whenElapsed = %lld\n", itTimerInfo->second->whenElapsed.time_since_epoch().count());
361         }
362     }
363     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
364     return true;
365 }
366 
SetProxyDelayTime(int fd,const int64_t proxyDelayTime)367 bool TimerProxy::SetProxyDelayTime(int fd, const int64_t proxyDelayTime)
368 {
369     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
370     if (proxyDelayTime < 0) {
371         dprintf(fd, "set proxy delay time err: %lld\n", proxyDelayTime);
372         TIME_HILOGD(TIME_MODULE_SERVICE, "err.");
373         return true;
374     }
375 
376     if (proxyDelayTime == 0) {
377         proxyDelayTime_ = PROXY_DELAY_TIME_IN_MILLI;
378     } else {
379         proxyDelayTime_ = proxyDelayTime;
380     }
381     dprintf(fd, "proxy delay time is set to %lld ms\n", proxyDelayTime_);
382 
383     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
384     return true;
385 }
386 
ShowProxyDelayTime(int fd)387 bool TimerProxy::ShowProxyDelayTime(int fd)
388 {
389     TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
390     dprintf(fd, "proxy delay time: %lld ms\n", proxyDelayTime_);
391     TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
392     return true;
393 }
394 
GetProxyDelayTime() const395 int64_t TimerProxy::GetProxyDelayTime() const
396 {
397     return proxyDelayTime_;
398 }
399 } // MiscServices
400 } // OHOS