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