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