• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                                   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                                     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, wp<PullUidProvider> provider);
83 
84     // Unregister a pull uid provider.
85     virtual void UnregisterPullUidProvider(const ConfigKey& configKey,
86                                            wp<PullUidProvider> provider);
87 
88     // Verify if we know how to pull for this matcher
89     bool PullerForMatcherExists(int tagId) const;
90 
91     void OnAlarmFired(int64_t elapsedTimeNs);
92 
93     // Pulls the most recent data.
94     // The data may be served from cache if consecutive pulls come within
95     // mCoolDownNs.
96     // Returns true if the pull was successful.
97     // Returns false when
98     //   1) the pull fails
99     //   2) pull takes longer than mPullTimeoutNs (intrinsic to puller)
100     //   3) Either a PullUidProvider was not registered for the config, or the there was no puller
101     //      registered for any of the uids for this atom.
102     // If the metric wants to make any change to the data, like timestamps, they
103     // should make a copy as this data may be shared with multiple metrics.
104     virtual bool Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
105                       vector<std::shared_ptr<LogEvent>>* data);
106 
107     // Same as above, but directly specify the allowed uids to pull from.
108     virtual bool Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
109                       vector<std::shared_ptr<LogEvent>>* data);
110 
111     // Clear pull data cache immediately.
112     int ForceClearPullerCache();
113 
114     // Clear pull data cache if it is beyond respective cool down time.
115     int ClearPullerCacheIfNecessary(int64_t timestampNs);
116 
117     void SetStatsCompanionService(shared_ptr<IStatsCompanionService> statsCompanionService);
118 
119     void RegisterPullAtomCallback(const int uid, const int32_t atomTag, const int64_t coolDownNs,
120                                   const int64_t timeoutNs, const vector<int32_t>& additiveFields,
121                                   const shared_ptr<IPullAtomCallback>& callback);
122 
123     void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
124 
125     std::map<const PullerKey, sp<StatsPuller>> kAllPullAtomInfo;
126 
127 private:
128     const static int64_t kMinCoolDownNs = NS_PER_SEC;
129     const static int64_t kMaxTimeoutNs = 10 * NS_PER_SEC;
130     shared_ptr<IStatsCompanionService> mStatsCompanionService = nullptr;
131 
132     // A struct containing an atom id and a Config Key
133     typedef struct ReceiverKey {
134         const int atomTag;
135         const ConfigKey configKey;
136 
137         inline bool operator<(const ReceiverKey& that) const {
138             return atomTag == that.atomTag ? configKey < that.configKey : atomTag < that.atomTag;
139         }
140     } ReceiverKey;
141 
142     typedef struct {
143         int64_t nextPullTimeNs;
144         int64_t intervalNs;
145         wp<PullDataReceiver> receiver;
146     } ReceiverInfo;
147 
148     // mapping from Receiver Key to receivers
149     std::map<ReceiverKey, std::list<ReceiverInfo>> mReceivers;
150 
151     // mapping from Config Key to the PullUidProvider for that config
152     std::map<ConfigKey, wp<PullUidProvider>> mPullUidProviders;
153 
154     bool PullLocked(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
155                     vector<std::shared_ptr<LogEvent>>* data);
156 
157     bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
158                     vector<std::shared_ptr<LogEvent>>* data);
159 
160     // locks for data receiver and StatsCompanionService changes
161     std::mutex mLock;
162 
163     void updateAlarmLocked();
164 
165     int64_t mNextPullTimeNs;
166 
167     // Death recipient that is triggered when the process holding the IPullAtomCallback has died.
168     ::ndk::ScopedAIBinder_DeathRecipient mPullAtomCallbackDeathRecipient;
169 
170     /**
171      * Death recipient callback that is called when a pull atom callback dies.
172      * The cookie is a pointer to a PullAtomCallbackDeathCookie.
173      */
174     static void pullAtomCallbackDied(void* cookie);
175 
176     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
177     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
178     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
179     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition);
180     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
181     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
182     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
183 
184     FRIEND_TEST(StatsLogProcessorTest, TestPullUidProviderSetOnConfigUpdate);
185 
186     FRIEND_TEST(ConfigUpdateE2eTest, TestGaugeMetric);
187     FRIEND_TEST(ConfigUpdateE2eTest, TestValueMetric);
188 };
189 
190 }  // namespace statsd
191 }  // namespace os
192 }  // namespace android
193