• 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 #define STATSD_DEBUG false  // STOPSHIP if true
18 #include "Log.h"
19 
20 #include "config/ConfigManager.h"
21 #include "storage/StorageManager.h"
22 
23 #include "guardrail/StatsdStats.h"
24 #include "stats_log_util.h"
25 #include "stats_util.h"
26 #include "stats_log_util.h"
27 
28 #include <stdio.h>
29 #include <vector>
30 #include "android-base/stringprintf.h"
31 
32 namespace android {
33 namespace os {
34 namespace statsd {
35 
36 using std::pair;
37 using std::string;
38 using std::vector;
39 
40 using Status = ::ndk::ScopedAStatus;
41 
42 #define STATS_SERVICE_DIR "/data/misc/stats-service"
43 
44 using android::base::StringPrintf;
45 using std::unique_ptr;
46 
ConfigManager()47 ConfigManager::ConfigManager() {
48 }
49 
~ConfigManager()50 ConfigManager::~ConfigManager() {
51 }
52 
Startup()53 void ConfigManager::Startup() {
54     map<ConfigKey, StatsdConfig> configsFromDisk;
55     StorageManager::readConfigFromDisk(configsFromDisk);
56     for (const auto& pair : configsFromDisk) {
57         UpdateConfig(pair.first, pair.second);
58     }
59 }
60 
StartupForTest()61 void ConfigManager::StartupForTest() {
62     // No-op function to avoid reading configs from disks for tests.
63 }
64 
AddListener(const sp<ConfigListener> & listener)65 void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
66     lock_guard<mutex> lock(mMutex);
67     mListeners.push_back(listener);
68 }
69 
UpdateConfig(const ConfigKey & key,const StatsdConfig & config)70 void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
71     vector<sp<ConfigListener>> broadcastList;
72     {
73         lock_guard <mutex> lock(mMutex);
74 
75         const int numBytes = config.ByteSize();
76         vector<uint8_t> buffer(numBytes);
77         config.SerializeToArray(buffer.data(), numBytes);
78 
79         auto uidIt = mConfigs.find(key.GetUid());
80         // GuardRail: Limit the number of configs per uid.
81         if (uidIt != mConfigs.end()) {
82             auto it = uidIt->second.find(key);
83             if (it == uidIt->second.end() &&
84                 uidIt->second.size() >= StatsdStats::kMaxConfigCountPerUid) {
85                 ALOGE("ConfigManager: uid %d has exceeded the config count limit", key.GetUid());
86                 return;
87             }
88         }
89 
90         // Check if it's a duplicate config.
91         if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end() &&
92             StorageManager::hasIdenticalConfig(key, buffer)) {
93             // This is a duplicate config.
94             ALOGI("ConfigManager This is a duplicate config %s", key.ToString().c_str());
95             // Update saved file on disk. We still update timestamp of file when
96             // there exists a duplicate configuration to avoid garbage collection.
97             update_saved_configs_locked(key, buffer, numBytes);
98             return;
99         }
100 
101         // Update saved file on disk.
102         update_saved_configs_locked(key, buffer, numBytes);
103 
104         // Add to set.
105         mConfigs[key.GetUid()].insert(key);
106 
107         broadcastList = mListeners;
108     }
109 
110     const int64_t timestampNs = getElapsedRealtimeNs();
111     // Tell everyone
112     for (const sp<ConfigListener>& listener : broadcastList) {
113         listener->OnConfigUpdated(timestampNs, key, config);
114     }
115 }
116 
SetConfigReceiver(const ConfigKey & key,const shared_ptr<IPendingIntentRef> & pir)117 void ConfigManager::SetConfigReceiver(const ConfigKey& key,
118                                       const shared_ptr<IPendingIntentRef>& pir) {
119     lock_guard<mutex> lock(mMutex);
120     mConfigReceivers[key] = pir;
121 }
122 
RemoveConfigReceiver(const ConfigKey & key)123 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
124     lock_guard<mutex> lock(mMutex);
125     mConfigReceivers.erase(key);
126 }
127 
RemoveConfigReceiver(const ConfigKey & key,const shared_ptr<IPendingIntentRef> & pir)128 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key,
129                                          const shared_ptr<IPendingIntentRef>& pir) {
130     lock_guard<mutex> lock(mMutex);
131     auto it = mConfigReceivers.find(key);
132     if (it != mConfigReceivers.end() && it->second == pir) {
133         mConfigReceivers.erase(key);
134     }
135 }
136 
SetActiveConfigsChangedReceiver(const int uid,const shared_ptr<IPendingIntentRef> & pir)137 void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
138                                                     const shared_ptr<IPendingIntentRef>& pir) {
139     lock_guard<mutex> lock(mMutex);
140     mActiveConfigsChangedReceivers[uid] = pir;
141 }
142 
RemoveActiveConfigsChangedReceiver(const int uid)143 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
144     lock_guard<mutex> lock(mMutex);
145     mActiveConfigsChangedReceivers.erase(uid);
146 }
147 
RemoveActiveConfigsChangedReceiver(const int uid,const shared_ptr<IPendingIntentRef> & pir)148 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid,
149                                                        const shared_ptr<IPendingIntentRef>& pir) {
150     lock_guard<mutex> lock(mMutex);
151     auto it = mActiveConfigsChangedReceivers.find(uid);
152     if (it != mActiveConfigsChangedReceivers.end() && it->second == pir) {
153         mActiveConfigsChangedReceivers.erase(uid);
154     }
155 }
156 
SetRestrictedMetricsChangedReceiver(const string & configPackage,const int64_t configId,const int32_t callingUid,const shared_ptr<IPendingIntentRef> & pir)157 void ConfigManager::SetRestrictedMetricsChangedReceiver(const string& configPackage,
158                                                         const int64_t configId,
159                                                         const int32_t callingUid,
160                                                         const shared_ptr<IPendingIntentRef>& pir) {
161     lock_guard<mutex> lock(mMutex);
162     ConfigKeyWithPackage configKey(configPackage, configId);
163     mRestrictedMetricsChangedReceivers[configKey][callingUid] = pir;
164 }
165 
RemoveRestrictedMetricsChangedReceiver(const string & configPackage,const int64_t configId,const int32_t callingUid)166 void ConfigManager::RemoveRestrictedMetricsChangedReceiver(const string& configPackage,
167                                                            const int64_t configId,
168                                                            const int32_t callingUid) {
169     lock_guard<mutex> lock(mMutex);
170     ConfigKeyWithPackage configKey(configPackage, configId);
171     const auto& it = mRestrictedMetricsChangedReceivers.find(configKey);
172     if (it != mRestrictedMetricsChangedReceivers.end()) {
173         it->second.erase(callingUid);
174         if (it->second.empty()) {
175             mRestrictedMetricsChangedReceivers.erase(it);
176         }
177     }
178 }
179 
RemoveRestrictedMetricsChangedReceiver(const ConfigKeyWithPackage & key,const int32_t delegateUid,const shared_ptr<IPendingIntentRef> & pir)180 void ConfigManager::RemoveRestrictedMetricsChangedReceiver(
181         const ConfigKeyWithPackage& key, const int32_t delegateUid,
182         const shared_ptr<IPendingIntentRef>& pir) {
183     lock_guard<mutex> lock(mMutex);
184     const auto& it = mRestrictedMetricsChangedReceivers.find(key);
185     if (it != mRestrictedMetricsChangedReceivers.end()) {
186         const auto& pirIt = it->second.find(delegateUid);
187         if (pirIt != it->second.end() && pirIt->second == pir) {
188             it->second.erase(delegateUid);
189             if (it->second.empty()) {
190                 mRestrictedMetricsChangedReceivers.erase(it);
191             }
192         }
193     }
194 }
195 
SendRestrictedMetricsBroadcast(const set<string> & configPackages,const int64_t configId,const set<int32_t> & delegateUids,const vector<int64_t> & metricIds)196 void ConfigManager::SendRestrictedMetricsBroadcast(const set<string>& configPackages,
197                                                    const int64_t configId,
198                                                    const set<int32_t>& delegateUids,
199                                                    const vector<int64_t>& metricIds) {
200     map<ConfigKeyWithPackage, map<int32_t, shared_ptr<IPendingIntentRef>>> intentsToSend;
201     {
202         lock_guard<mutex> lock(mMutex);
203         // Invoke the pending intent for all matching configs, as long as the listening delegates
204         // match the allowed delegate uids specified by the config.
205         for (const string& configPackage : configPackages) {
206             ConfigKeyWithPackage key(configPackage, configId);
207             const auto& it = mRestrictedMetricsChangedReceivers.find(key);
208             if (it != mRestrictedMetricsChangedReceivers.end()) {
209                 for (const auto& [delegateUid, pir] : it->second) {
210                     if (delegateUids.find(delegateUid) != delegateUids.end()) {
211                         intentsToSend[key][delegateUid] = pir;
212                     }
213                 }
214             }
215         }
216     }
217 
218     // Invoke the pending intents without holding the lock.
219     for (const auto& [key, innerMap] : intentsToSend) {
220         for (const auto& [delegateUid, pir] : innerMap) {
221             Status status = pir->sendRestrictedMetricsChangedBroadcast(metricIds);
222             if (status.isOk()) {
223                 VLOG("ConfigManager::SendRestrictedMetricsBroadcast succeeded");
224             }
225             if (status.getExceptionCode() == EX_TRANSACTION_FAILED &&
226                 status.getStatus() == STATUS_DEAD_OBJECT) {
227                 // Must also be called without the lock, since remove will acquire the lock.
228                 RemoveRestrictedMetricsChangedReceiver(key, delegateUid, pir);
229             }
230         }
231     }
232 }
233 
RemoveConfig(const ConfigKey & key)234 void ConfigManager::RemoveConfig(const ConfigKey& key) {
235     vector<sp<ConfigListener>> broadcastList;
236     {
237         lock_guard <mutex> lock(mMutex);
238 
239         auto uid = key.GetUid();
240         auto uidIt = mConfigs.find(uid);
241         if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
242             // Remove from map
243             uidIt->second.erase(key);
244 
245             broadcastList = mListeners;
246         }
247 
248         // Remove from disk. There can still be a lingering file on disk so we check
249         // whether or not the config was on memory.
250         remove_saved_configs(key);
251     }
252 
253     for (const sp<ConfigListener>& listener:broadcastList) {
254         listener->OnConfigRemoved(key);
255     }
256 }
257 
remove_saved_configs(const ConfigKey & key)258 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
259     string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
260     StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
261 }
262 
263 // TODO(b/xxx): consider removing all receivers associated with this uid.
RemoveConfigs(int uid)264 void ConfigManager::RemoveConfigs(int uid) {
265     vector<ConfigKey> removed;
266     vector<sp<ConfigListener>> broadcastList;
267     {
268         lock_guard <mutex> lock(mMutex);
269 
270         auto uidIt = mConfigs.find(uid);
271         if (uidIt == mConfigs.end()) {
272             return;
273         }
274 
275         for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
276             // Remove from map
277                 remove_saved_configs(*it);
278                 removed.push_back(*it);
279         }
280 
281         mConfigs.erase(uidIt);
282 
283         broadcastList = mListeners;
284     }
285 
286     // Remove separately so if they do anything in the callback they can't mess up our iteration.
287     for (auto& key : removed) {
288         // Tell everyone
289         for (const sp<ConfigListener>& listener:broadcastList) {
290             listener->OnConfigRemoved(key);
291         }
292     }
293 }
294 
RemoveAllConfigs()295 void ConfigManager::RemoveAllConfigs() {
296     vector<ConfigKey> removed;
297     vector<sp<ConfigListener>> broadcastList;
298     {
299         lock_guard <mutex> lock(mMutex);
300 
301         for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
302             for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
303                 // Remove from map
304                 removed.push_back(*it);
305                 it = uidIt->second.erase(it);
306             }
307             uidIt = mConfigs.erase(uidIt);
308         }
309 
310         broadcastList = mListeners;
311     }
312 
313     // Remove separately so if they do anything in the callback they can't mess up our iteration.
314     for (auto& key : removed) {
315         // Tell everyone
316         for (const sp<ConfigListener>& listener:broadcastList) {
317             listener->OnConfigRemoved(key);
318         }
319     }
320 }
321 
GetAllConfigKeys() const322 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
323     lock_guard<mutex> lock(mMutex);
324 
325     vector<ConfigKey> ret;
326     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
327         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
328             ret.push_back(*it);
329         }
330     }
331     return ret;
332 }
333 
GetConfigReceiver(const ConfigKey & key) const334 const shared_ptr<IPendingIntentRef> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
335     lock_guard<mutex> lock(mMutex);
336 
337     auto it = mConfigReceivers.find(key);
338     if (it == mConfigReceivers.end()) {
339         return nullptr;
340     } else {
341         return it->second;
342     }
343 }
344 
GetActiveConfigsChangedReceiver(const int uid) const345 const shared_ptr<IPendingIntentRef> ConfigManager::GetActiveConfigsChangedReceiver(const int uid)
346         const {
347     lock_guard<mutex> lock(mMutex);
348 
349     auto it = mActiveConfigsChangedReceivers.find(uid);
350     if (it == mActiveConfigsChangedReceivers.end()) {
351         return nullptr;
352     } else {
353         return it->second;
354     }
355 }
356 
Dump(FILE * out)357 void ConfigManager::Dump(FILE* out) {
358     lock_guard<mutex> lock(mMutex);
359 
360     fprintf(out, "CONFIGURATIONS\n");
361     fprintf(out, "     uid name\n");
362     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
363         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
364             fprintf(out, "  %6d %lld\n", it->GetUid(), (long long)it->GetId());
365             auto receiverIt = mConfigReceivers.find(*it);
366             if (receiverIt != mConfigReceivers.end()) {
367                 fprintf(out, "    -> received by PendingIntent as binder\n");
368             }
369         }
370     }
371 }
372 
update_saved_configs_locked(const ConfigKey & key,const vector<uint8_t> & buffer,const int numBytes)373 void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
374                                                 const vector<uint8_t>& buffer,
375                                                 const int numBytes) {
376     // If there is a pre-existing config with same key we should first delete it.
377     remove_saved_configs(key);
378 
379     // Then we save the latest config.
380     string file_name =
381         StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
382                      key.GetUid(), (long long)key.GetId());
383     StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
384 }
385 
386 }  // namespace statsd
387 }  // namespace os
388 }  // namespace android
389