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