blob: 7bfb991ab1acfc90d7b99368b12eb53ecb78708f [file] [log] [blame]
Joe Onorato9fc9edf2017-10-15 20:08:52 -07001/*
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
Yao Chen52b478b2018-03-27 10:59:45 -070017#define DEBUG false // STOPSHIP if true
18#include "Log.h"
19
Joe Onorato9fc9edf2017-10-15 20:08:52 -070020#include "config/ConfigManager.h"
yro947fbce2017-11-15 22:50:23 -080021#include "storage/StorageManager.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070022
Yao Chen52b478b2018-03-27 10:59:45 -070023#include "guardrail/StatsdStats.h"
Yangster-macc04feba2018-04-02 14:37:33 -070024#include "stats_log_util.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070025#include "stats_util.h"
Yangster-macb142cc82018-03-30 15:22:08 -070026#include "stats_log_util.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070027
yro87d983c2017-11-14 21:31:43 -080028#include <android-base/file.h>
29#include <dirent.h>
Joe Onorato9fc9edf2017-10-15 20:08:52 -070030#include <stdio.h>
yro87d983c2017-11-14 21:31:43 -080031#include <vector>
32#include "android-base/stringprintf.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070033
34namespace android {
35namespace os {
36namespace statsd {
37
Yao Chenf09569f2017-12-13 17:00:51 -080038using std::map;
39using std::pair;
40using std::set;
41using std::string;
42using std::vector;
43
yro03faf092017-12-12 00:17:50 -080044#define STATS_SERVICE_DIR "/data/misc/stats-service"
yro87d983c2017-11-14 21:31:43 -080045
yro87d983c2017-11-14 21:31:43 -080046using android::base::StringPrintf;
47using std::unique_ptr;
48
Jeffrey Huangad213742019-12-16 13:50:06 -080049class ConfigReceiverDeathRecipient : public android::IBinder::DeathRecipient {
50 public:
51 ConfigReceiverDeathRecipient(sp<ConfigManager> configManager, const ConfigKey& configKey):
52 mConfigManager(configManager),
53 mConfigKey(configKey) {}
54 ~ConfigReceiverDeathRecipient() override = default;
55 private:
56 sp<ConfigManager> mConfigManager;
57 ConfigKey mConfigKey;
58
59 void binderDied(const android::wp<android::IBinder>& who) override {
60 if (IInterface::asBinder(mConfigManager->GetConfigReceiver(mConfigKey)) == who.promote()) {
61 mConfigManager->RemoveConfigReceiver(mConfigKey);
62 }
63 }
64};
65
Joe Onorato9fc9edf2017-10-15 20:08:52 -070066ConfigManager::ConfigManager() {
67}
68
69ConfigManager::~ConfigManager() {
70}
71
72void ConfigManager::Startup() {
Yao Chenf09569f2017-12-13 17:00:51 -080073 map<ConfigKey, StatsdConfig> configsFromDisk;
74 StorageManager::readConfigFromDisk(configsFromDisk);
yro469cd802018-01-04 14:57:45 -080075 for (const auto& pair : configsFromDisk) {
76 UpdateConfig(pair.first, pair.second);
77 }
78}
Yao Chen3c0b95c2017-12-16 14:34:20 -080079
yro469cd802018-01-04 14:57:45 -080080void ConfigManager::StartupForTest() {
81 // Dummy function to avoid reading configs from disks for tests.
Joe Onorato9fc9edf2017-10-15 20:08:52 -070082}
83
84void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
David Chenfdc123b2018-02-09 17:21:48 -080085 lock_guard<mutex> lock(mMutex);
Joe Onorato9fc9edf2017-10-15 20:08:52 -070086 mListeners.push_back(listener);
87}
88
89void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
David Chenfdc123b2018-02-09 17:21:48 -080090 vector<sp<ConfigListener>> broadcastList;
91 {
92 lock_guard <mutex> lock(mMutex);
Joe Onorato9fc9edf2017-10-15 20:08:52 -070093
yro44907652018-03-12 20:44:05 -070094 const int numBytes = config.ByteSize();
95 vector<uint8_t> buffer(numBytes);
96 config.SerializeToArray(&buffer[0], numBytes);
97
Yao Chen52b478b2018-03-27 10:59:45 -070098 auto uidIt = mConfigs.find(key.GetUid());
99 // GuardRail: Limit the number of configs per uid.
100 if (uidIt != mConfigs.end()) {
101 auto it = uidIt->second.find(key);
102 if (it == uidIt->second.end() &&
103 uidIt->second.size() >= StatsdStats::kMaxConfigCountPerUid) {
104 ALOGE("ConfigManager: uid %d has exceeded the config count limit", key.GetUid());
105 return;
106 }
107 }
yro44907652018-03-12 20:44:05 -0700108
Yao Chen52b478b2018-03-27 10:59:45 -0700109 // Check if it's a duplicate config.
110 if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end() &&
111 StorageManager::hasIdenticalConfig(key, buffer)) {
112 // This is a duplicate config.
113 ALOGI("ConfigManager This is a duplicate config %s", key.ToString().c_str());
114 // Update saved file on disk. We still update timestamp of file when
115 // there exists a duplicate configuration to avoid garbage collection.
116 update_saved_configs_locked(key, buffer, numBytes);
117 return;
118 }
119
120 // Update saved file on disk.
yro44907652018-03-12 20:44:05 -0700121 update_saved_configs_locked(key, buffer, numBytes);
122
Yao Chen52b478b2018-03-27 10:59:45 -0700123 // Add to set.
124 mConfigs[key.GetUid()].insert(key);
David Chenfdc123b2018-02-09 17:21:48 -0800125
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800126 for (const sp<ConfigListener>& listener : mListeners) {
David Chenfdc123b2018-02-09 17:21:48 -0800127 broadcastList.push_back(listener);
128 }
129 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700130
Yangster-macc04feba2018-04-02 14:37:33 -0700131 const int64_t timestampNs = getElapsedRealtimeNs();
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700132 // Tell everyone
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800133 for (const sp<ConfigListener>& listener : broadcastList) {
Yangster-macc04feba2018-04-02 14:37:33 -0700134 listener->OnConfigUpdated(timestampNs, key, config);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700135 }
136}
137
Jeffrey Huangad213742019-12-16 13:50:06 -0800138void ConfigManager::SetConfigReceiver(const ConfigKey& key,
139 const sp<IPendingIntentRef>& pir) {
David Chenfdc123b2018-02-09 17:21:48 -0800140 lock_guard<mutex> lock(mMutex);
Jeffrey Huangad213742019-12-16 13:50:06 -0800141 mConfigReceivers[key] = pir;
142 IInterface::asBinder(pir)->linkToDeath(new ConfigReceiverDeathRecipient(this, key));
David Chenadaf8b32017-11-03 15:42:08 -0700143}
144
145void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
David Chenfdc123b2018-02-09 17:21:48 -0800146 lock_guard<mutex> lock(mMutex);
David Chenadaf8b32017-11-03 15:42:08 -0700147 mConfigReceivers.erase(key);
148}
149
Tej Singh2c9ef2a2019-01-22 11:33:51 -0800150void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
151 const sp<IBinder>& intentSender) {
152 lock_guard<mutex> lock(mMutex);
153 mActiveConfigsChangedReceivers[uid] = intentSender;
154}
155
156void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
157 lock_guard<mutex> lock(mMutex);
158 mActiveConfigsChangedReceivers.erase(uid);
159}
160
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700161void ConfigManager::RemoveConfig(const ConfigKey& key) {
David Chenfdc123b2018-02-09 17:21:48 -0800162 vector<sp<ConfigListener>> broadcastList;
163 {
164 lock_guard <mutex> lock(mMutex);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700165
Tej Singh6ede28b2019-01-29 17:06:54 -0800166 auto uid = key.GetUid();
167 auto uidIt = mConfigs.find(uid);
Yao Chen52b478b2018-03-27 10:59:45 -0700168 if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
David Chenfdc123b2018-02-09 17:21:48 -0800169 // Remove from map
Yao Chen52b478b2018-03-27 10:59:45 -0700170 uidIt->second.erase(key);
Tej Singh6ede28b2019-01-29 17:06:54 -0800171
172 // No more configs for this uid, lets remove the active configs callback.
173 if (uidIt->second.empty()) {
174 auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
175 if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
176 mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
177 }
178 }
179
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800180 for (const sp<ConfigListener>& listener : mListeners) {
David Chenfdc123b2018-02-09 17:21:48 -0800181 broadcastList.push_back(listener);
182 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700183 }
David Chenfdc123b2018-02-09 17:21:48 -0800184
185 auto itReceiver = mConfigReceivers.find(key);
186 if (itReceiver != mConfigReceivers.end()) {
187 // Remove from map
188 mConfigReceivers.erase(itReceiver);
189 }
190
191 // Remove from disk. There can still be a lingering file on disk so we check
192 // whether or not the config was on memory.
193 remove_saved_configs(key);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700194 }
yro9c98c052017-11-19 14:33:56 -0800195
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800196 for (const sp<ConfigListener>& listener:broadcastList) {
David Chenfdc123b2018-02-09 17:21:48 -0800197 listener->OnConfigRemoved(key);
198 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700199}
200
yro87d983c2017-11-14 21:31:43 -0800201void ConfigManager::remove_saved_configs(const ConfigKey& key) {
yrof4ae56b2018-02-13 22:06:34 -0800202 string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
yroe5f82922018-01-22 18:37:27 -0800203 StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
yro87d983c2017-11-14 21:31:43 -0800204}
205
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700206void ConfigManager::RemoveConfigs(int uid) {
207 vector<ConfigKey> removed;
David Chenfdc123b2018-02-09 17:21:48 -0800208 vector<sp<ConfigListener>> broadcastList;
209 {
210 lock_guard <mutex> lock(mMutex);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700211
Yao Chen52b478b2018-03-27 10:59:45 -0700212 auto uidIt = mConfigs.find(uid);
213 if (uidIt == mConfigs.end()) {
214 return;
215 }
216
217 for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
David Chenfdc123b2018-02-09 17:21:48 -0800218 // Remove from map
David Chenfdc123b2018-02-09 17:21:48 -0800219 remove_saved_configs(*it);
220 removed.push_back(*it);
221 mConfigReceivers.erase(*it);
David Chenfdc123b2018-02-09 17:21:48 -0800222 }
223
Tej Singh2c9ef2a2019-01-22 11:33:51 -0800224 auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
225 if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
226 mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
227 }
228
Yao Chen52b478b2018-03-27 10:59:45 -0700229 mConfigs.erase(uidIt);
230
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800231 for (const sp<ConfigListener>& listener : mListeners) {
David Chenfdc123b2018-02-09 17:21:48 -0800232 broadcastList.push_back(listener);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700233 }
234 }
235
236 // Remove separately so if they do anything in the callback they can't mess up our iteration.
237 for (auto& key : removed) {
238 // Tell everyone
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800239 for (const sp<ConfigListener>& listener:broadcastList) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700240 listener->OnConfigRemoved(key);
241 }
242 }
243}
244
yro74fed972017-11-27 14:42:42 -0800245void ConfigManager::RemoveAllConfigs() {
246 vector<ConfigKey> removed;
David Chenfdc123b2018-02-09 17:21:48 -0800247 vector<sp<ConfigListener>> broadcastList;
248 {
249 lock_guard <mutex> lock(mMutex);
yro74fed972017-11-27 14:42:42 -0800250
Yao Chen52b478b2018-03-27 10:59:45 -0700251 for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
252 for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
253 // Remove from map
254 removed.push_back(*it);
255 it = uidIt->second.erase(it);
David Chenfdc123b2018-02-09 17:21:48 -0800256 }
Yao Chen52b478b2018-03-27 10:59:45 -0700257 uidIt = mConfigs.erase(uidIt);
yro74fed972017-11-27 14:42:42 -0800258 }
David Chenfdc123b2018-02-09 17:21:48 -0800259
Yao Chen52b478b2018-03-27 10:59:45 -0700260 mConfigReceivers.clear();
Tej Singh2c9ef2a2019-01-22 11:33:51 -0800261 mActiveConfigsChangedReceivers.clear();
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800262 for (const sp<ConfigListener>& listener : mListeners) {
David Chenfdc123b2018-02-09 17:21:48 -0800263 broadcastList.push_back(listener);
264 }
yro74fed972017-11-27 14:42:42 -0800265 }
266
267 // Remove separately so if they do anything in the callback they can't mess up our iteration.
268 for (auto& key : removed) {
269 // Tell everyone
Chih-Hung Hsieha1b644e2018-12-11 11:09:20 -0800270 for (const sp<ConfigListener>& listener:broadcastList) {
yro74fed972017-11-27 14:42:42 -0800271 listener->OnConfigRemoved(key);
272 }
273 }
274}
275
Yangster7c334a12017-11-22 14:24:24 -0800276vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
David Chenfdc123b2018-02-09 17:21:48 -0800277 lock_guard<mutex> lock(mMutex);
278
David Chen1d7b0cd2017-11-15 14:20:04 -0800279 vector<ConfigKey> ret;
Yao Chen52b478b2018-03-27 10:59:45 -0700280 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
281 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
282 ret.push_back(*it);
283 }
David Chen1d7b0cd2017-11-15 14:20:04 -0800284 }
285 return ret;
286}
287
Jeffrey Huangad213742019-12-16 13:50:06 -0800288const sp<IPendingIntentRef> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
David Chenfdc123b2018-02-09 17:21:48 -0800289 lock_guard<mutex> lock(mMutex);
290
David Chen1d7b0cd2017-11-15 14:20:04 -0800291 auto it = mConfigReceivers.find(key);
292 if (it == mConfigReceivers.end()) {
David Chen661f7912018-01-22 17:46:24 -0800293 return nullptr;
David Chen1d7b0cd2017-11-15 14:20:04 -0800294 } else {
295 return it->second;
296 }
297}
298
Tej Singh2c9ef2a2019-01-22 11:33:51 -0800299const sp<android::IBinder> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
300 lock_guard<mutex> lock(mMutex);
301
302 auto it = mActiveConfigsChangedReceivers.find(uid);
303 if (it == mActiveConfigsChangedReceivers.end()) {
304 return nullptr;
305 } else {
306 return it->second;
307 }
308}
309
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700310void ConfigManager::Dump(FILE* out) {
David Chenfdc123b2018-02-09 17:21:48 -0800311 lock_guard<mutex> lock(mMutex);
312
Yao Chen52b478b2018-03-27 10:59:45 -0700313 fprintf(out, "CONFIGURATIONS\n");
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700314 fprintf(out, " uid name\n");
Yao Chen52b478b2018-03-27 10:59:45 -0700315 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
316 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
317 fprintf(out, " %6d %lld\n", it->GetUid(), (long long)it->GetId());
318 auto receiverIt = mConfigReceivers.find(*it);
319 if (receiverIt != mConfigReceivers.end()) {
320 fprintf(out, " -> received by PendingIntent as binder\n");
321 }
David Chen1d7b0cd2017-11-15 14:20:04 -0800322 }
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700323 }
324}
325
yro44907652018-03-12 20:44:05 -0700326void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
327 const vector<uint8_t>& buffer,
328 const int numBytes) {
yro9c98c052017-11-19 14:33:56 -0800329 // If there is a pre-existing config with same key we should first delete it.
330 remove_saved_configs(key);
331
332 // Then we save the latest config.
yro44907652018-03-12 20:44:05 -0700333 string file_name =
334 StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
335 key.GetUid(), (long long)key.GetId());
yro947fbce2017-11-15 22:50:23 -0800336 StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700337}
338
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700339} // namespace statsd
340} // namespace os
341} // namespace android