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 <aidl/android/os/IPullAtomCallback.h>
20 #include <aidl/android/os/IStatsCompanionService.h>
21 #include <utils/RefBase.h>
22 
23 #include <list>
24 #include <vector>
25 
26 #include "PullDataReceiver.h"
27 #include "PullUidProvider.h"
28 #include "StatsPuller.h"
29 #include "guardrail/StatsdStats.h"
30 #include "logd/LogEvent.h"
31 #include "packages/UidMap.h"
32 
33 using aidl::android::os::IPullAtomCallback;
34 using aidl::android::os::IStatsCompanionService;
35 using std::shared_ptr;
36 
37 namespace android {
38 namespace os {
39 namespace statsd {
40 
41 typedef struct PullerKey {
42     // The uid of the process that registers this puller.
43     const int uid = -1;
44     // The atom that this puller is for.
45     const int atomTag;
46 
47     bool operator<(const PullerKey& that) const {
48         if (uid < that.uid) {
49             return true;
50         }
51         if (uid > that.uid) {
52             return false;
53         }
54         return atomTag < that.atomTag;
55     };
56 
57     bool operator==(const PullerKey& that) const {
58         return uid == that.uid && atomTag == that.atomTag;
59     };
60 } PullerKey;
61 
62 class StatsPullerManager : public virtual RefBase {
63 public:
64     StatsPullerManager();
65 
~StatsPullerManager()66     virtual ~StatsPullerManager() {
67     }
68 
69 
70     // Registers a receiver for tagId. It will be pulled on the nextPullTimeNs
71     // and then every intervalNs thereafter.
72     virtual void RegisterReceiver(int tagId, const ConfigKey& configKey,
73                                   const wp<PullDataReceiver>& receiver, int64_t nextPullTimeNs,
74                                   int64_t intervalNs);
75 
76     // Stop listening on a tagId.
77     virtual void UnRegisterReceiver(int tagId, const ConfigKey& configKey,
78                                     const wp<PullDataReceiver>& receiver);
79 
80     // Registers a pull uid provider for the config key. When pulling atoms, it will be used to
81     // determine which uids to pull from.
82     virtual void RegisterPullUidProvider(const ConfigKey& configKey,
83                                          const wp<PullUidProvider>& provider);
84 
85     // Unregister a pull uid provider.
86     virtual void UnregisterPullUidProvider(const ConfigKey& configKey,
87                                            const wp<PullUidProvider>& provider);
88 
89     // Verify if we know how to pull for this matcher
90     bool PullerForMatcherExists(int tagId) const;
91 
92     void OnAlarmFired(int64_t elapsedTimeNs);
93 
94     // Pulls the most recent data.
95     // The data may be served from cache if consecutive pulls come within
96     // mCoolDownNs.
97     // Returns true if the pull was successful.
98     // Returns false when
99     //   1) the pull fails
100     //   2) pull takes longer than mPullTimeoutNs (intrinsic to puller)
101     //   3) Either a PullUidProvider was not registered for the config, or the there was no puller
102     //      registered for any of the uids for this atom.
103     // If the metric wants to make any change to the data, like timestamps, they
104     // should make a copy as this data may be shared with multiple metrics.
105     virtual bool Pull(int tagId, const ConfigKey& configKey, int64_t eventTimeNs,
106                       vector<std::shared_ptr<LogEvent>>* data);
107 
108     // Same as above, but directly specify the allowed uids to pull from.
109     virtual bool Pull(int tagId, const vector<int32_t>& uids, int64_t eventTimeNs,
110                       vector<std::shared_ptr<LogEvent>>* data);
111 
112     // Clear pull data cache immediately.
113     int ForceClearPullerCache();
114 
115     // Clear pull data cache if it is beyond respective cool down time.
116     int ClearPullerCacheIfNecessary(int64_t timestampNs);
117 
118     void SetStatsCompanionService(const shared_ptr<IStatsCompanionService>& statsCompanionService);
119 
120     void RegisterPullAtomCallback(const int uid, const int32_t atomTag, int64_t coolDownNs,
121                                   const int64_t timeoutNs, const vector<int32_t>& additiveFields,
122                                   const shared_ptr<IPullAtomCallback>& callback);
123 
124     void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
125 
126     std::map<const PullerKey, sp<StatsPuller>> kAllPullAtomInfo;
127 
128 private:
129     const static int64_t kMinCoolDownNs = NS_PER_SEC;
130     const static int64_t kMaxTimeoutNs = 10 * NS_PER_SEC;
131     shared_ptr<IStatsCompanionService> mStatsCompanionService = nullptr;
132 
133     // A struct containing an atom id and a Config Key
134     typedef struct ReceiverKey {
135         const int atomTag;
136         const ConfigKey configKey;
137 
138         inline bool operator<(const ReceiverKey& that) const {
139             return atomTag == that.atomTag ? configKey < that.configKey : atomTag < that.atomTag;
140         }
141     } ReceiverKey;
142 
143     typedef struct {
144         int64_t nextPullTimeNs;
145         int64_t intervalNs;
146         wp<PullDataReceiver> receiver;
147     } ReceiverInfo;
148 
149     // mapping from Receiver Key to receivers
150     std::map<ReceiverKey, std::list<ReceiverInfo>> mReceivers;
151 
152     // mapping from Config Key to the PullUidProvider for that config
153     std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
154 
155     bool PullLocked(int tagId, const ConfigKey& configKey, int64_t eventTimeNs,
156                     vector<std::shared_ptr<LogEvent>>* data);
157 
158     bool PullLocked(int tagId, const vector<int32_t>& uids, int64_t eventTimeNs,
159                     vector<std::shared_ptr<LogEvent>>* data);
160 
161     // locks for data receiver and StatsCompanionService changes
162     std::mutex mLock;
163 
164     void updateAlarmLocked();
165 
166     int64_t mNextPullTimeNs;
167 
168     FRIEND_TEST(GaugeMetricE2ePulledTest, TestFirstNSamplesPulledNoTrigger);
169     FRIEND_TEST(GaugeMetricE2ePulledTest, TestFirstNSamplesPulledNoTriggerWithActivation);
170     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents);
171     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm);
172     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation);
173     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition);
174     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
175     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
176     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
177 
178     FRIEND_TEST(StatsLogProcessorTest, TestPullUidProviderSetOnConfigUpdate);
179 
180     FRIEND_TEST(ConfigUpdateE2eTest, TestGaugeMetric);
181     FRIEND_TEST(ConfigUpdateE2eTest, TestValueMetric);
182 };
183 
184 }  // namespace statsd
185 }  // namespace os
186 }  // namespace android
187