1 /*
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 #pragma once
18 
19 #include "anomaly/indexed_priority_queue.h"
20 
21 #include <android/os/IStatsCompanionService.h>
22 #include <utils/RefBase.h>
23 
24 #include <queue>
25 #include <set>
26 #include <unordered_set>
27 #include <vector>
28 
29 using namespace android;
30 
31 using android::os::IStatsCompanionService;
32 using std::unordered_set;
33 
34 namespace android {
35 namespace os {
36 namespace statsd {
37 
38 /**
39  * Represents an alarm, associated with some aggregate metric, holding a
40  * projected time at which the metric is expected to exceed its anomaly
41  * threshold.
42  * Timestamps are in seconds since epoch in a uint32, so will fail in year 2106.
43  */
44 struct InternalAlarm : public RefBase {
InternalAlarmInternalAlarm45     InternalAlarm(uint32_t timestampSec) : timestampSec(timestampSec) {
46     }
47 
48     const uint32_t timestampSec;
49 
50     /** InternalAlarm a is smaller (higher priority) than b if its timestamp is sooner. */
51     struct SmallerTimestamp {
operatorInternalAlarm::SmallerTimestamp52         bool operator()(sp<const InternalAlarm> a, sp<const InternalAlarm> b) const {
53             return (a->timestampSec < b->timestampSec);
54         }
55     };
56 };
57 
58 /**
59  * Manages internal alarms that may get registered with the AlarmManager.
60  */
61 class AlarmMonitor : public RefBase {
62 public:
63     /**
64      * @param minDiffToUpdateRegisteredAlarmTimeSec If the soonest alarm differs
65      * from the registered alarm by more than this amount, update the registered
66      * alarm.
67      */
68     AlarmMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec,
69                  const std::function<void(const sp<IStatsCompanionService>&, int64_t)>& updateAlarm,
70                  const std::function<void(const sp<IStatsCompanionService>&)>& cancelAlarm);
71     ~AlarmMonitor();
72 
73     /**
74      * Tells AnomalyMonitor what IStatsCompanionService to use and, if
75      * applicable, immediately registers an existing alarm with it.
76      * If nullptr, AnomalyMonitor will continue to add/remove alarms, but won't
77      * update IStatsCompanionService (until such time as it is set non-null).
78      */
79     void setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService);
80 
81     /**
82      * Adds the given alarm (reference) to the queue.
83      */
84     void add(sp<const InternalAlarm> alarm);
85 
86     /**
87      * Removes the given alarm (reference) from the queue.
88      * Note that alarm comparison is reference-based; if another alarm exists
89      * with the same timestampSec, that alarm will still remain in the queue.
90      */
91     void remove(sp<const InternalAlarm> alarm);
92 
93     /**
94      * Returns and removes all alarms whose timestamp <= the given timestampSec.
95      * Always updates the registered alarm if return is non-empty.
96      */
97     unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> popSoonerThan(
98             uint32_t timestampSec);
99 
100     /**
101      * Returns the projected alarm timestamp that is registered with
102      * StatsCompanionService. This may not be equal to the soonest alarm,
103      * but should be within minDiffToUpdateRegisteredAlarmTimeSec of it.
104      */
getRegisteredAlarmTimeSec()105     uint32_t getRegisteredAlarmTimeSec() const {
106         return mRegisteredAlarmTimeSec;
107     }
108 
109 private:
110     std::mutex mLock;
111 
112     /**
113      * Timestamp (seconds since epoch) of the alarm registered with
114      * StatsCompanionService. This, in general, may not be equal to the soonest
115      * alarm stored in mPq, but should be within minUpdateTimeSec of it.
116      * A value of 0 indicates that no alarm is currently registered.
117      */
118     uint32_t mRegisteredAlarmTimeSec;
119 
120     /**
121      * Priority queue of alarms, prioritized by soonest alarm.timestampSec.
122      */
123     indexed_priority_queue<InternalAlarm, InternalAlarm::SmallerTimestamp> mPq;
124 
125     /**
126      * Binder interface for communicating with StatsCompanionService.
127      */
128     sp<IStatsCompanionService> mStatsCompanionService = nullptr;
129 
130     /**
131      * Amount by which the soonest projected alarm must differ from
132      * mRegisteredAlarmTimeSec before updateRegisteredAlarmTime_l is called.
133      */
134     uint32_t mMinUpdateTimeSec;
135 
136     /**
137      * Updates the alarm registered with StatsCompanionService to the given time.
138      * Also correspondingly updates mRegisteredAlarmTimeSec.
139      */
140     void updateRegisteredAlarmTime_l(uint32_t timestampSec);
141 
142     /**
143      * Cancels the alarm registered with StatsCompanionService.
144      * Also correspondingly sets mRegisteredAlarmTimeSec to 0.
145      */
146     void cancelRegisteredAlarmTime_l();
147 
148     /** Converts uint32 timestamp in seconds to a Java long in msec. */
149     int64_t secToMs(uint32_t timeSec);
150 
151     // Callback function to update the alarm via StatsCompanionService.
152     std::function<void(const sp<IStatsCompanionService>, int64_t)> mUpdateAlarm;
153 
154     // Callback function to cancel the alarm via StatsCompanionService.
155     std::function<void(const sp<IStatsCompanionService>)> mCancelAlarm;
156 
157 };
158 
159 }  // namespace statsd
160 }  // namespace os
161 }  // namespace android
162