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 #define STATS_SERVICE_DIR "/data/misc/stats-service"
41
42 using android::base::StringPrintf;
43 using std::unique_ptr;
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& pair : configsFromDisk) {
55 UpdateConfig(pair.first, pair.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 for (const sp<ConfigListener>& listener : mListeners) {
106 broadcastList.push_back(listener);
107 }
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
RemoveConfig(const ConfigKey & key)157 void ConfigManager::RemoveConfig(const ConfigKey& key) {
158 vector<sp<ConfigListener>> broadcastList;
159 {
160 lock_guard <mutex> lock(mMutex);
161
162 auto uid = key.GetUid();
163 auto uidIt = mConfigs.find(uid);
164 if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
165 // Remove from map
166 uidIt->second.erase(key);
167
168 for (const sp<ConfigListener>& listener : mListeners) {
169 broadcastList.push_back(listener);
170 }
171 }
172
173 // Remove from disk. There can still be a lingering file on disk so we check
174 // whether or not the config was on memory.
175 remove_saved_configs(key);
176 }
177
178 for (const sp<ConfigListener>& listener:broadcastList) {
179 listener->OnConfigRemoved(key);
180 }
181 }
182
remove_saved_configs(const ConfigKey & key)183 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
184 string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
185 StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
186 }
187
RemoveConfigs(int uid)188 void ConfigManager::RemoveConfigs(int uid) {
189 vector<ConfigKey> removed;
190 vector<sp<ConfigListener>> broadcastList;
191 {
192 lock_guard <mutex> lock(mMutex);
193
194 auto uidIt = mConfigs.find(uid);
195 if (uidIt == mConfigs.end()) {
196 return;
197 }
198
199 for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
200 // Remove from map
201 remove_saved_configs(*it);
202 removed.push_back(*it);
203 }
204
205 mConfigs.erase(uidIt);
206
207 for (const sp<ConfigListener>& listener : mListeners) {
208 broadcastList.push_back(listener);
209 }
210 }
211
212 // Remove separately so if they do anything in the callback they can't mess up our iteration.
213 for (auto& key : removed) {
214 // Tell everyone
215 for (const sp<ConfigListener>& listener:broadcastList) {
216 listener->OnConfigRemoved(key);
217 }
218 }
219 }
220
RemoveAllConfigs()221 void ConfigManager::RemoveAllConfigs() {
222 vector<ConfigKey> removed;
223 vector<sp<ConfigListener>> broadcastList;
224 {
225 lock_guard <mutex> lock(mMutex);
226
227 for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
228 for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
229 // Remove from map
230 removed.push_back(*it);
231 it = uidIt->second.erase(it);
232 }
233 uidIt = mConfigs.erase(uidIt);
234 }
235
236 for (const sp<ConfigListener>& listener : mListeners) {
237 broadcastList.push_back(listener);
238 }
239 }
240
241 // Remove separately so if they do anything in the callback they can't mess up our iteration.
242 for (auto& key : removed) {
243 // Tell everyone
244 for (const sp<ConfigListener>& listener:broadcastList) {
245 listener->OnConfigRemoved(key);
246 }
247 }
248 }
249
GetAllConfigKeys() const250 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
251 lock_guard<mutex> lock(mMutex);
252
253 vector<ConfigKey> ret;
254 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
255 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
256 ret.push_back(*it);
257 }
258 }
259 return ret;
260 }
261
GetConfigReceiver(const ConfigKey & key) const262 const shared_ptr<IPendingIntentRef> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
263 lock_guard<mutex> lock(mMutex);
264
265 auto it = mConfigReceivers.find(key);
266 if (it == mConfigReceivers.end()) {
267 return nullptr;
268 } else {
269 return it->second;
270 }
271 }
272
GetActiveConfigsChangedReceiver(const int uid) const273 const shared_ptr<IPendingIntentRef> ConfigManager::GetActiveConfigsChangedReceiver(const int uid)
274 const {
275 lock_guard<mutex> lock(mMutex);
276
277 auto it = mActiveConfigsChangedReceivers.find(uid);
278 if (it == mActiveConfigsChangedReceivers.end()) {
279 return nullptr;
280 } else {
281 return it->second;
282 }
283 }
284
Dump(FILE * out)285 void ConfigManager::Dump(FILE* out) {
286 lock_guard<mutex> lock(mMutex);
287
288 fprintf(out, "CONFIGURATIONS\n");
289 fprintf(out, " uid name\n");
290 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
291 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
292 fprintf(out, " %6d %lld\n", it->GetUid(), (long long)it->GetId());
293 auto receiverIt = mConfigReceivers.find(*it);
294 if (receiverIt != mConfigReceivers.end()) {
295 fprintf(out, " -> received by PendingIntent as binder\n");
296 }
297 }
298 }
299 }
300
update_saved_configs_locked(const ConfigKey & key,const vector<uint8_t> & buffer,const int numBytes)301 void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
302 const vector<uint8_t>& buffer,
303 const int numBytes) {
304 // If there is a pre-existing config with same key we should first delete it.
305 remove_saved_configs(key);
306
307 // Then we save the latest config.
308 string file_name =
309 StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
310 key.GetUid(), (long long)key.GetId());
311 StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
312 }
313
314 } // namespace statsd
315 } // namespace os
316 } // namespace android
317