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