• 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, bool useUids = true);
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, bool useUids = true);
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                                   bool useUid = true);
123 
124     void UnregisterPullAtomCallback(const int uid, const int32_t atomTag, bool useUids = true);
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, const int64_t eventTimeNs,
156                     vector<std::shared_ptr<LogEvent>>* data, bool useUids = true);
157 
158     bool PullLocked(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
159                     vector<std::shared_ptr<LogEvent>>* data, bool useUids);
160 
161     // locks for data receiver and StatsCompanionService changes
162     std::mutex mLock;
163 
164     void updateAlarmLocked();
165 
166     int64_t mNextPullTimeNs;
167 
168     // Death recipient that is triggered when the process holding the IPullAtomCallback has died.
169     ::ndk::ScopedAIBinder_DeathRecipient mPullAtomCallbackDeathRecipient;
170 
171     /**
172      * Death recipient callback that is called when a pull atom callback dies.
173      * The cookie is a pointer to a PullAtomCallbackDeathCookie.
174      */
175     static void pullAtomCallbackDied(void* cookie);
176 
177     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents);
178     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm);
179     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation);
180     FRIEND_TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition);
181     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
182     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
183     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
184 
185     FRIEND_TEST(StatsLogProcessorTest, TestPullUidProviderSetOnConfigUpdate);
186 };
187 
188 }  // namespace statsd
189 }  // namespace os
190 }  // namespace android
191