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