blob: ff2509149cf83489d1ff92646a0cc71c7e70d54b [file] [log] [blame]
Joe Onoratoda8cca72017-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 Chen341db892018-03-27 10:59:45 -070017#define DEBUG false // STOPSHIP if true
18#include "Log.h"
19
Joe Onoratoda8cca72017-10-15 20:08:52 -070020#include "config/ConfigManager.h"
yro1528e0f2017-11-15 22:50:23 -080021#include "storage/StorageManager.h"
Joe Onoratoda8cca72017-10-15 20:08:52 -070022
Yao Chen341db892018-03-27 10:59:45 -070023#include "guardrail/StatsdStats.h"
Joe Onoratoda8cca72017-10-15 20:08:52 -070024#include "stats_util.h"
25
yrod3a24362017-11-14 21:31:43 -080026#include <android-base/file.h>
27#include <dirent.h>
Joe Onoratoda8cca72017-10-15 20:08:52 -070028#include <stdio.h>
yrod3a24362017-11-14 21:31:43 -080029#include <vector>
30#include "android-base/stringprintf.h"
Joe Onoratoda8cca72017-10-15 20:08:52 -070031
32namespace android {
33namespace os {
34namespace statsd {
35
Yao Chena277da32017-12-13 17:00:51 -080036using std::map;
37using std::pair;
38using std::set;
39using std::string;
40using std::vector;
41
yro06849152017-12-12 00:17:50 -080042#define STATS_SERVICE_DIR "/data/misc/stats-service"
yrod3a24362017-11-14 21:31:43 -080043
yrod3a24362017-11-14 21:31:43 -080044using android::base::StringPrintf;
45using std::unique_ptr;
46
Joe Onoratoda8cca72017-10-15 20:08:52 -070047ConfigManager::ConfigManager() {
48}
49
50ConfigManager::~ConfigManager() {
51}
52
53void ConfigManager::Startup() {
Yao Chena277da32017-12-13 17:00:51 -080054 map<ConfigKey, StatsdConfig> configsFromDisk;
55 StorageManager::readConfigFromDisk(configsFromDisk);
yro1d5bb082018-01-04 14:57:45 -080056 for (const auto& pair : configsFromDisk) {
57 UpdateConfig(pair.first, pair.second);
58 }
59}
Yao Chen0cf61892017-12-16 14:34:20 -080060
yro1d5bb082018-01-04 14:57:45 -080061void ConfigManager::StartupForTest() {
62 // Dummy function to avoid reading configs from disks for tests.
Joe Onoratoda8cca72017-10-15 20:08:52 -070063}
64
65void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
David Chen687dbd12018-02-09 17:21:48 -080066 lock_guard<mutex> lock(mMutex);
Joe Onoratoda8cca72017-10-15 20:08:52 -070067 mListeners.push_back(listener);
68}
69
70void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
David Chen687dbd12018-02-09 17:21:48 -080071 vector<sp<ConfigListener>> broadcastList;
72 {
73 lock_guard <mutex> lock(mMutex);
Joe Onoratoda8cca72017-10-15 20:08:52 -070074
yro2918b552018-03-12 20:44:05 -070075 const int numBytes = config.ByteSize();
76 vector<uint8_t> buffer(numBytes);
77 config.SerializeToArray(&buffer[0], numBytes);
78
Yao Chen341db892018-03-27 10:59:45 -070079 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 }
yro2918b552018-03-12 20:44:05 -070089
Yao Chen341db892018-03-27 10:59:45 -070090 // 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.
yro2918b552018-03-12 20:44:05 -0700102 update_saved_configs_locked(key, buffer, numBytes);
103
Yao Chen341db892018-03-27 10:59:45 -0700104 // Add to set.
105 mConfigs[key.GetUid()].insert(key);
David Chen687dbd12018-02-09 17:21:48 -0800106
David Chen687dbd12018-02-09 17:21:48 -0800107 for (sp<ConfigListener> listener : mListeners) {
108 broadcastList.push_back(listener);
109 }
110 }
Joe Onoratoda8cca72017-10-15 20:08:52 -0700111
112 // Tell everyone
David Chen687dbd12018-02-09 17:21:48 -0800113 for (sp<ConfigListener> listener:broadcastList) {
Joe Onoratoda8cca72017-10-15 20:08:52 -0700114 listener->OnConfigUpdated(key, config);
115 }
116}
117
David Chen29ada1e2018-01-22 17:46:24 -0800118void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
David Chen687dbd12018-02-09 17:21:48 -0800119 lock_guard<mutex> lock(mMutex);
David Chen29ada1e2018-01-22 17:46:24 -0800120 mConfigReceivers[key] = intentSender;
David Chenec84d132017-11-03 15:42:08 -0700121}
122
123void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
David Chen687dbd12018-02-09 17:21:48 -0800124 lock_guard<mutex> lock(mMutex);
David Chenec84d132017-11-03 15:42:08 -0700125 mConfigReceivers.erase(key);
126}
127
Joe Onoratoda8cca72017-10-15 20:08:52 -0700128void ConfigManager::RemoveConfig(const ConfigKey& key) {
David Chen687dbd12018-02-09 17:21:48 -0800129 vector<sp<ConfigListener>> broadcastList;
130 {
131 lock_guard <mutex> lock(mMutex);
Joe Onoratoda8cca72017-10-15 20:08:52 -0700132
Yao Chen341db892018-03-27 10:59:45 -0700133 auto uidIt = mConfigs.find(key.GetUid());
134 if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
David Chen687dbd12018-02-09 17:21:48 -0800135 // Remove from map
Yao Chen341db892018-03-27 10:59:45 -0700136 uidIt->second.erase(key);
David Chen687dbd12018-02-09 17:21:48 -0800137 for (sp<ConfigListener> listener : mListeners) {
138 broadcastList.push_back(listener);
139 }
Joe Onoratoda8cca72017-10-15 20:08:52 -0700140 }
David Chen687dbd12018-02-09 17:21:48 -0800141
142 auto itReceiver = mConfigReceivers.find(key);
143 if (itReceiver != mConfigReceivers.end()) {
144 // Remove from map
145 mConfigReceivers.erase(itReceiver);
146 }
147
148 // Remove from disk. There can still be a lingering file on disk so we check
149 // whether or not the config was on memory.
150 remove_saved_configs(key);
Joe Onoratoda8cca72017-10-15 20:08:52 -0700151 }
yro9bb4f7d2017-11-19 14:33:56 -0800152
David Chen687dbd12018-02-09 17:21:48 -0800153 for (sp<ConfigListener> listener:broadcastList) {
154 listener->OnConfigRemoved(key);
155 }
Joe Onoratoda8cca72017-10-15 20:08:52 -0700156}
157
yrod3a24362017-11-14 21:31:43 -0800158void ConfigManager::remove_saved_configs(const ConfigKey& key) {
yro0bd9aa12018-02-13 22:06:34 -0800159 string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
yroa8c4ebf2018-01-22 18:37:27 -0800160 StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
yrod3a24362017-11-14 21:31:43 -0800161}
162
Joe Onoratoda8cca72017-10-15 20:08:52 -0700163void ConfigManager::RemoveConfigs(int uid) {
164 vector<ConfigKey> removed;
David Chen687dbd12018-02-09 17:21:48 -0800165 vector<sp<ConfigListener>> broadcastList;
166 {
167 lock_guard <mutex> lock(mMutex);
Joe Onoratoda8cca72017-10-15 20:08:52 -0700168
Yao Chen341db892018-03-27 10:59:45 -0700169 auto uidIt = mConfigs.find(uid);
170 if (uidIt == mConfigs.end()) {
171 return;
172 }
173
174 for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
David Chen687dbd12018-02-09 17:21:48 -0800175 // Remove from map
David Chen687dbd12018-02-09 17:21:48 -0800176 remove_saved_configs(*it);
177 removed.push_back(*it);
178 mConfigReceivers.erase(*it);
David Chen687dbd12018-02-09 17:21:48 -0800179 }
180
Yao Chen341db892018-03-27 10:59:45 -0700181 mConfigs.erase(uidIt);
182
David Chen687dbd12018-02-09 17:21:48 -0800183 for (sp<ConfigListener> listener : mListeners) {
184 broadcastList.push_back(listener);
Joe Onoratoda8cca72017-10-15 20:08:52 -0700185 }
186 }
187
188 // Remove separately so if they do anything in the callback they can't mess up our iteration.
189 for (auto& key : removed) {
190 // Tell everyone
David Chen687dbd12018-02-09 17:21:48 -0800191 for (sp<ConfigListener> listener:broadcastList) {
Joe Onoratoda8cca72017-10-15 20:08:52 -0700192 listener->OnConfigRemoved(key);
193 }
194 }
195}
196
yro11e2da52017-11-27 14:42:42 -0800197void ConfigManager::RemoveAllConfigs() {
198 vector<ConfigKey> removed;
David Chen687dbd12018-02-09 17:21:48 -0800199 vector<sp<ConfigListener>> broadcastList;
200 {
201 lock_guard <mutex> lock(mMutex);
yro11e2da52017-11-27 14:42:42 -0800202
Yao Chen341db892018-03-27 10:59:45 -0700203 for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
204 for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
205 // Remove from map
206 removed.push_back(*it);
207 it = uidIt->second.erase(it);
David Chen687dbd12018-02-09 17:21:48 -0800208 }
Yao Chen341db892018-03-27 10:59:45 -0700209 uidIt = mConfigs.erase(uidIt);
yro11e2da52017-11-27 14:42:42 -0800210 }
David Chen687dbd12018-02-09 17:21:48 -0800211
Yao Chen341db892018-03-27 10:59:45 -0700212 mConfigReceivers.clear();
David Chen687dbd12018-02-09 17:21:48 -0800213 for (sp<ConfigListener> listener : mListeners) {
214 broadcastList.push_back(listener);
215 }
yro11e2da52017-11-27 14:42:42 -0800216 }
217
218 // Remove separately so if they do anything in the callback they can't mess up our iteration.
219 for (auto& key : removed) {
220 // Tell everyone
David Chen687dbd12018-02-09 17:21:48 -0800221 for (sp<ConfigListener> listener:broadcastList) {
yro11e2da52017-11-27 14:42:42 -0800222 listener->OnConfigRemoved(key);
223 }
224 }
225}
226
Yangsterd1df8ed2017-11-22 14:24:24 -0800227vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
David Chen687dbd12018-02-09 17:21:48 -0800228 lock_guard<mutex> lock(mMutex);
229
David Chendd4e8032017-11-15 14:20:04 -0800230 vector<ConfigKey> ret;
Yao Chen341db892018-03-27 10:59:45 -0700231 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
232 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
233 ret.push_back(*it);
234 }
David Chendd4e8032017-11-15 14:20:04 -0800235 }
236 return ret;
237}
238
David Chen29ada1e2018-01-22 17:46:24 -0800239const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
David Chen687dbd12018-02-09 17:21:48 -0800240 lock_guard<mutex> lock(mMutex);
241
David Chendd4e8032017-11-15 14:20:04 -0800242 auto it = mConfigReceivers.find(key);
243 if (it == mConfigReceivers.end()) {
David Chen29ada1e2018-01-22 17:46:24 -0800244 return nullptr;
David Chendd4e8032017-11-15 14:20:04 -0800245 } else {
246 return it->second;
247 }
248}
249
Joe Onoratoda8cca72017-10-15 20:08:52 -0700250void ConfigManager::Dump(FILE* out) {
David Chen687dbd12018-02-09 17:21:48 -0800251 lock_guard<mutex> lock(mMutex);
252
Yao Chen341db892018-03-27 10:59:45 -0700253 fprintf(out, "CONFIGURATIONS\n");
Joe Onoratoda8cca72017-10-15 20:08:52 -0700254 fprintf(out, " uid name\n");
Yao Chen341db892018-03-27 10:59:45 -0700255 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
256 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
257 fprintf(out, " %6d %lld\n", it->GetUid(), (long long)it->GetId());
258 auto receiverIt = mConfigReceivers.find(*it);
259 if (receiverIt != mConfigReceivers.end()) {
260 fprintf(out, " -> received by PendingIntent as binder\n");
261 }
David Chendd4e8032017-11-15 14:20:04 -0800262 }
Joe Onoratoda8cca72017-10-15 20:08:52 -0700263 }
264}
265
yro2918b552018-03-12 20:44:05 -0700266void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
267 const vector<uint8_t>& buffer,
268 const int numBytes) {
yro9bb4f7d2017-11-19 14:33:56 -0800269 // If there is a pre-existing config with same key we should first delete it.
270 remove_saved_configs(key);
271
272 // Then we save the latest config.
yro2918b552018-03-12 20:44:05 -0700273 string file_name =
274 StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
275 key.GetUid(), (long long)key.GetId());
yro1528e0f2017-11-15 22:50:23 -0800276 StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
Joe Onoratoda8cca72017-10-15 20:08:52 -0700277}
278
Joe Onoratoda8cca72017-10-15 20:08:52 -0700279} // namespace statsd
280} // namespace os
281} // namespace android