blob: 4fbbc7a2267f95f39c4dbc7a3dbee56e423e9fc3 [file] [log] [blame]
Bookatz486d1cf2017-09-01 13:10:41 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "AnomalyMonitor"
18#define DEBUG true
19
Bookatz906a35c2017-09-20 15:26:44 -070020#include "AnomalyMonitor.h"
Bookatz486d1cf2017-09-01 13:10:41 -070021
Bookatz486d1cf2017-09-01 13:10:41 -070022#include <cutils/log.h>
23
Bookatz906a35c2017-09-20 15:26:44 -070024namespace android {
25namespace os {
26namespace statsd {
Bookatz486d1cf2017-09-01 13:10:41 -070027
28AnomalyMonitor::AnomalyMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec)
Yao Chenef99c4f2017-09-22 16:26:54 -070029 : mRegisteredAlarmTimeSec(0), mMinUpdateTimeSec(minDiffToUpdateRegisteredAlarmTimeSec) {
Bookatz486d1cf2017-09-01 13:10:41 -070030}
31
32AnomalyMonitor::~AnomalyMonitor() {
33}
34
Bookatzb487b552017-09-18 11:26:01 -070035void AnomalyMonitor::setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) {
36 std::lock_guard<std::mutex> lock(mLock);
37 sp<IStatsCompanionService> tmpForLock = mStatsCompanionService;
38 mStatsCompanionService = statsCompanionService;
39 if (statsCompanionService == nullptr) {
40 if (DEBUG) ALOGD("Erasing link to statsCompanionService");
41 return;
42 }
43 if (DEBUG) ALOGD("Creating link to statsCompanionService");
44 const sp<const AnomalyAlarm> top = mPq.top();
45 if (top != nullptr) {
46 updateRegisteredAlarmTime_l(top->timestampSec);
47 }
48}
49
Bookatz486d1cf2017-09-01 13:10:41 -070050void AnomalyMonitor::add(sp<const AnomalyAlarm> alarm) {
Bookatzb487b552017-09-18 11:26:01 -070051 std::lock_guard<std::mutex> lock(mLock);
Bookatz486d1cf2017-09-01 13:10:41 -070052 if (alarm == nullptr) {
53 ALOGW("Asked to add a null alarm.");
54 return;
55 }
56 if (alarm->timestampSec < 1) {
57 // forbidden since a timestamp 0 is used to indicate no alarm registered
58 ALOGW("Asked to add a 0-time alarm.");
59 return;
60 }
Bookatz486d1cf2017-09-01 13:10:41 -070061 // TODO: Ensure that refractory period is respected.
62 if (DEBUG) ALOGD("Adding alarm with time %u", alarm->timestampSec);
63 mPq.push(alarm);
64 if (mRegisteredAlarmTimeSec < 1 ||
Yao Chenef99c4f2017-09-22 16:26:54 -070065 alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) {
Bookatzb487b552017-09-18 11:26:01 -070066 updateRegisteredAlarmTime_l(alarm->timestampSec);
Bookatz486d1cf2017-09-01 13:10:41 -070067 }
68}
69
70void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) {
Bookatzb487b552017-09-18 11:26:01 -070071 std::lock_guard<std::mutex> lock(mLock);
Bookatz486d1cf2017-09-01 13:10:41 -070072 if (alarm == nullptr) {
73 ALOGW("Asked to remove a null alarm.");
74 return;
75 }
Bookatz486d1cf2017-09-01 13:10:41 -070076 if (DEBUG) ALOGD("Removing alarm with time %u", alarm->timestampSec);
Bookatz0e959092017-09-07 17:39:37 -070077 mPq.remove(alarm);
Bookatz486d1cf2017-09-01 13:10:41 -070078 if (mPq.empty()) {
79 if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
80 mRegisteredAlarmTimeSec = 0;
Bookatzb487b552017-09-18 11:26:01 -070081 if (mStatsCompanionService != nullptr) {
82 mStatsCompanionService->cancelAnomalyAlarm();
Bookatz486d1cf2017-09-01 13:10:41 -070083 }
84 return;
85 }
86 uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec;
87 if (DEBUG) ALOGD("Soonest alarm is %u", soonestAlarmTimeSec);
88 if (soonestAlarmTimeSec > mRegisteredAlarmTimeSec + mMinUpdateTimeSec) {
Bookatzb487b552017-09-18 11:26:01 -070089 updateRegisteredAlarmTime_l(soonestAlarmTimeSec);
Bookatz486d1cf2017-09-01 13:10:41 -070090 }
91}
92
Bookatzece5f702017-10-09 14:59:38 -070093// More efficient than repeatedly calling remove(mPq.top()) since it batches the
94// updates to the registered alarm.
95unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>
96 AnomalyMonitor::popSoonerThan(uint32_t timestampSec) {
97
98 if (DEBUG) ALOGD("Removing alarms with time <= %u", timestampSec);
99 unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>> oldAlarms;
100 std::lock_guard<std::mutex> lock(mLock);
101
102 for (sp<const AnomalyAlarm> t = mPq.top();
103 t != nullptr && t->timestampSec <= timestampSec; t = mPq.top()) {
104 oldAlarms.insert(t);
105 mPq.pop(); // remove t
106 }
107 // Always update registered alarm time (if anything has changed).
108 if (!oldAlarms.empty()) {
109 if (mPq.empty()) {
110 if (DEBUG) ALOGD("Queue is empty. Cancel any alarm.");
111 mRegisteredAlarmTimeSec = 0;
112 if (mStatsCompanionService != nullptr) {
113 mStatsCompanionService->cancelAnomalyAlarm();
114 }
115 } else {
116 // Always update the registered alarm in this case (unlike remove()).
117 updateRegisteredAlarmTime_l(mPq.top()->timestampSec);
118 }
119 }
120 return oldAlarms;
121}
122
Bookatzb487b552017-09-18 11:26:01 -0700123void AnomalyMonitor::updateRegisteredAlarmTime_l(uint32_t timestampSec) {
Bookatz486d1cf2017-09-01 13:10:41 -0700124 if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec);
125 mRegisteredAlarmTimeSec = timestampSec;
Bookatzb487b552017-09-18 11:26:01 -0700126 if (mStatsCompanionService != nullptr) {
127 mStatsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec));
Bookatz486d1cf2017-09-01 13:10:41 -0700128 }
129}
130
Bookatz486d1cf2017-09-01 13:10:41 -0700131int64_t AnomalyMonitor::secToMs(uint32_t timeSec) {
Yao Chenef99c4f2017-09-22 16:26:54 -0700132 return ((int64_t)timeSec) * 1000;
Bookatz486d1cf2017-09-01 13:10:41 -0700133}
Bookatz906a35c2017-09-20 15:26:44 -0700134
Yao Chenef99c4f2017-09-22 16:26:54 -0700135} // namespace statsd
136} // namespace os
137} // namespace android