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 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
45 struct ConfigReceiverDeathCookie {
ConfigReceiverDeathCookieandroid::os::statsd::ConfigReceiverDeathCookie46 ConfigReceiverDeathCookie(const wp<ConfigManager>& configManager, const ConfigKey& configKey,
47 const shared_ptr<IPendingIntentRef>& pir) :
48 mConfigManager(configManager), mConfigKey(configKey), mPir(pir) {
49 }
50
51 wp<ConfigManager> mConfigManager;
52 ConfigKey mConfigKey;
53 shared_ptr<IPendingIntentRef> mPir;
54 };
55
configReceiverDied(void * cookie)56 void ConfigManager::configReceiverDied(void* cookie) {
57 auto cookie_ = static_cast<ConfigReceiverDeathCookie*>(cookie);
58 sp<ConfigManager> thiz = cookie_->mConfigManager.promote();
59 if (!thiz) {
60 return;
61 }
62
63 ConfigKey& configKey = cookie_->mConfigKey;
64 shared_ptr<IPendingIntentRef>& pir = cookie_->mPir;
65
66 // Erase the mapping from the config key to the config receiver (pir) if the
67 // mapping still exists.
68 lock_guard<mutex> lock(thiz->mMutex);
69 auto it = thiz->mConfigReceivers.find(configKey);
70 if (it != thiz->mConfigReceivers.end() && it->second == pir) {
71 thiz->mConfigReceivers.erase(configKey);
72 }
73
74 // The death recipient corresponding to this specific pir can never be
75 // triggered again, so free up resources.
76 delete cookie_;
77 }
78
79 struct ActiveConfigChangedReceiverDeathCookie {
ActiveConfigChangedReceiverDeathCookieandroid::os::statsd::ActiveConfigChangedReceiverDeathCookie80 ActiveConfigChangedReceiverDeathCookie(const wp<ConfigManager>& configManager, const int uid,
81 const shared_ptr<IPendingIntentRef>& pir) :
82 mConfigManager(configManager), mUid(uid), mPir(pir) {
83 }
84
85 wp<ConfigManager> mConfigManager;
86 int mUid;
87 shared_ptr<IPendingIntentRef> mPir;
88 };
89
activeConfigChangedReceiverDied(void * cookie)90 void ConfigManager::activeConfigChangedReceiverDied(void* cookie) {
91 auto cookie_ = static_cast<ActiveConfigChangedReceiverDeathCookie*>(cookie);
92 sp<ConfigManager> thiz = cookie_->mConfigManager.promote();
93 if (!thiz) {
94 return;
95 }
96
97 int uid = cookie_->mUid;
98 shared_ptr<IPendingIntentRef>& pir = cookie_->mPir;
99
100 // Erase the mapping from the config key to the active config changed
101 // receiver (pir) if the mapping still exists.
102 lock_guard<mutex> lock(thiz->mMutex);
103 auto it = thiz->mActiveConfigsChangedReceivers.find(uid);
104 if (it != thiz->mActiveConfigsChangedReceivers.end() && it->second == pir) {
105 thiz->mActiveConfigsChangedReceivers.erase(uid);
106 }
107
108 // The death recipient corresponding to this specific pir can never
109 // be triggered again, so free up resources.
110 delete cookie_;
111 }
112
ConfigManager()113 ConfigManager::ConfigManager() :
114 mConfigReceiverDeathRecipient(AIBinder_DeathRecipient_new(configReceiverDied)),
115 mActiveConfigChangedReceiverDeathRecipient(
116 AIBinder_DeathRecipient_new(activeConfigChangedReceiverDied)) {
117 }
118
~ConfigManager()119 ConfigManager::~ConfigManager() {
120 }
121
Startup()122 void ConfigManager::Startup() {
123 map<ConfigKey, StatsdConfig> configsFromDisk;
124 StorageManager::readConfigFromDisk(configsFromDisk);
125 for (const auto& pair : configsFromDisk) {
126 UpdateConfig(pair.first, pair.second);
127 }
128 }
129
StartupForTest()130 void ConfigManager::StartupForTest() {
131 // Dummy function to avoid reading configs from disks for tests.
132 }
133
AddListener(const sp<ConfigListener> & listener)134 void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
135 lock_guard<mutex> lock(mMutex);
136 mListeners.push_back(listener);
137 }
138
UpdateConfig(const ConfigKey & key,const StatsdConfig & config)139 void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
140 vector<sp<ConfigListener>> broadcastList;
141 {
142 lock_guard <mutex> lock(mMutex);
143
144 const int numBytes = config.ByteSize();
145 vector<uint8_t> buffer(numBytes);
146 config.SerializeToArray(&buffer[0], numBytes);
147
148 auto uidIt = mConfigs.find(key.GetUid());
149 // GuardRail: Limit the number of configs per uid.
150 if (uidIt != mConfigs.end()) {
151 auto it = uidIt->second.find(key);
152 if (it == uidIt->second.end() &&
153 uidIt->second.size() >= StatsdStats::kMaxConfigCountPerUid) {
154 ALOGE("ConfigManager: uid %d has exceeded the config count limit", key.GetUid());
155 return;
156 }
157 }
158
159 // Check if it's a duplicate config.
160 if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end() &&
161 StorageManager::hasIdenticalConfig(key, buffer)) {
162 // This is a duplicate config.
163 ALOGI("ConfigManager This is a duplicate config %s", key.ToString().c_str());
164 // Update saved file on disk. We still update timestamp of file when
165 // there exists a duplicate configuration to avoid garbage collection.
166 update_saved_configs_locked(key, buffer, numBytes);
167 return;
168 }
169
170 // Update saved file on disk.
171 update_saved_configs_locked(key, buffer, numBytes);
172
173 // Add to set.
174 mConfigs[key.GetUid()].insert(key);
175
176 for (const sp<ConfigListener>& listener : mListeners) {
177 broadcastList.push_back(listener);
178 }
179 }
180
181 const int64_t timestampNs = getElapsedRealtimeNs();
182 // Tell everyone
183 for (const sp<ConfigListener>& listener : broadcastList) {
184 listener->OnConfigUpdated(timestampNs, key, config);
185 }
186 }
187
SetConfigReceiver(const ConfigKey & key,const shared_ptr<IPendingIntentRef> & pir)188 void ConfigManager::SetConfigReceiver(const ConfigKey& key,
189 const shared_ptr<IPendingIntentRef>& pir) {
190 lock_guard<mutex> lock(mMutex);
191 mConfigReceivers[key] = pir;
192 AIBinder_linkToDeath(pir->asBinder().get(), mConfigReceiverDeathRecipient.get(),
193 new ConfigReceiverDeathCookie(this, key, pir));
194 }
195
RemoveConfigReceiver(const ConfigKey & key)196 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
197 lock_guard<mutex> lock(mMutex);
198 mConfigReceivers.erase(key);
199 }
200
SetActiveConfigsChangedReceiver(const int uid,const shared_ptr<IPendingIntentRef> & pir)201 void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
202 const shared_ptr<IPendingIntentRef>& pir) {
203 {
204 lock_guard<mutex> lock(mMutex);
205 mActiveConfigsChangedReceivers[uid] = pir;
206 }
207 AIBinder_linkToDeath(pir->asBinder().get(), mActiveConfigChangedReceiverDeathRecipient.get(),
208 new ActiveConfigChangedReceiverDeathCookie(this, uid, pir));
209 }
210
RemoveActiveConfigsChangedReceiver(const int uid)211 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
212 lock_guard<mutex> lock(mMutex);
213 mActiveConfigsChangedReceivers.erase(uid);
214 }
215
RemoveConfig(const ConfigKey & key)216 void ConfigManager::RemoveConfig(const ConfigKey& key) {
217 vector<sp<ConfigListener>> broadcastList;
218 {
219 lock_guard <mutex> lock(mMutex);
220
221 auto uid = key.GetUid();
222 auto uidIt = mConfigs.find(uid);
223 if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
224 // Remove from map
225 uidIt->second.erase(key);
226
227 for (const sp<ConfigListener>& listener : mListeners) {
228 broadcastList.push_back(listener);
229 }
230 }
231
232 // Remove from disk. There can still be a lingering file on disk so we check
233 // whether or not the config was on memory.
234 remove_saved_configs(key);
235 }
236
237 for (const sp<ConfigListener>& listener:broadcastList) {
238 listener->OnConfigRemoved(key);
239 }
240 }
241
remove_saved_configs(const ConfigKey & key)242 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
243 string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
244 StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
245 }
246
RemoveConfigs(int uid)247 void ConfigManager::RemoveConfigs(int uid) {
248 vector<ConfigKey> removed;
249 vector<sp<ConfigListener>> broadcastList;
250 {
251 lock_guard <mutex> lock(mMutex);
252
253 auto uidIt = mConfigs.find(uid);
254 if (uidIt == mConfigs.end()) {
255 return;
256 }
257
258 for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
259 // Remove from map
260 remove_saved_configs(*it);
261 removed.push_back(*it);
262 }
263
264 mConfigs.erase(uidIt);
265
266 for (const sp<ConfigListener>& listener : mListeners) {
267 broadcastList.push_back(listener);
268 }
269 }
270
271 // Remove separately so if they do anything in the callback they can't mess up our iteration.
272 for (auto& key : removed) {
273 // Tell everyone
274 for (const sp<ConfigListener>& listener:broadcastList) {
275 listener->OnConfigRemoved(key);
276 }
277 }
278 }
279
RemoveAllConfigs()280 void ConfigManager::RemoveAllConfigs() {
281 vector<ConfigKey> removed;
282 vector<sp<ConfigListener>> broadcastList;
283 {
284 lock_guard <mutex> lock(mMutex);
285
286 for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
287 for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
288 // Remove from map
289 removed.push_back(*it);
290 it = uidIt->second.erase(it);
291 }
292 uidIt = mConfigs.erase(uidIt);
293 }
294
295 for (const sp<ConfigListener>& listener : mListeners) {
296 broadcastList.push_back(listener);
297 }
298 }
299
300 // Remove separately so if they do anything in the callback they can't mess up our iteration.
301 for (auto& key : removed) {
302 // Tell everyone
303 for (const sp<ConfigListener>& listener:broadcastList) {
304 listener->OnConfigRemoved(key);
305 }
306 }
307 }
308
GetAllConfigKeys() const309 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
310 lock_guard<mutex> lock(mMutex);
311
312 vector<ConfigKey> ret;
313 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
314 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
315 ret.push_back(*it);
316 }
317 }
318 return ret;
319 }
320
GetConfigReceiver(const ConfigKey & key) const321 const shared_ptr<IPendingIntentRef> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
322 lock_guard<mutex> lock(mMutex);
323
324 auto it = mConfigReceivers.find(key);
325 if (it == mConfigReceivers.end()) {
326 return nullptr;
327 } else {
328 return it->second;
329 }
330 }
331
GetActiveConfigsChangedReceiver(const int uid) const332 const shared_ptr<IPendingIntentRef> ConfigManager::GetActiveConfigsChangedReceiver(const int uid)
333 const {
334 lock_guard<mutex> lock(mMutex);
335
336 auto it = mActiveConfigsChangedReceivers.find(uid);
337 if (it == mActiveConfigsChangedReceivers.end()) {
338 return nullptr;
339 } else {
340 return it->second;
341 }
342 }
343
Dump(FILE * out)344 void ConfigManager::Dump(FILE* out) {
345 lock_guard<mutex> lock(mMutex);
346
347 fprintf(out, "CONFIGURATIONS\n");
348 fprintf(out, " uid name\n");
349 for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
350 for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
351 fprintf(out, " %6d %lld\n", it->GetUid(), (long long)it->GetId());
352 auto receiverIt = mConfigReceivers.find(*it);
353 if (receiverIt != mConfigReceivers.end()) {
354 fprintf(out, " -> received by PendingIntent as binder\n");
355 }
356 }
357 }
358 }
359
update_saved_configs_locked(const ConfigKey & key,const vector<uint8_t> & buffer,const int numBytes)360 void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
361 const vector<uint8_t>& buffer,
362 const int numBytes) {
363 // If there is a pre-existing config with same key we should first delete it.
364 remove_saved_configs(key);
365
366 // Then we save the latest config.
367 string file_name =
368 StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
369 key.GetUid(), (long long)key.GetId());
370 StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
371 }
372
373 } // namespace statsd
374 } // namespace os
375 } // namespace android
376