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