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