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 
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[0], 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 sp<IBinder> & intentSender)117 void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
118     lock_guard<mutex> lock(mMutex);
119     mConfigReceivers[key] = intentSender;
120 }
121 
RemoveConfigReceiver(const ConfigKey & key)122 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
123     lock_guard<mutex> lock(mMutex);
124     mConfigReceivers.erase(key);
125 }
126 
SetActiveConfigsChangedReceiver(const int uid,const sp<IBinder> & intentSender)127 void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
128                                                     const sp<IBinder>& intentSender) {
129     lock_guard<mutex> lock(mMutex);
130     mActiveConfigsChangedReceivers[uid] = intentSender;
131 }
132 
RemoveActiveConfigsChangedReceiver(const int uid)133 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
134     lock_guard<mutex> lock(mMutex);
135     mActiveConfigsChangedReceivers.erase(uid);
136 }
137 
RemoveConfig(const ConfigKey & key)138 void ConfigManager::RemoveConfig(const ConfigKey& key) {
139     vector<sp<ConfigListener>> broadcastList;
140     {
141         lock_guard <mutex> lock(mMutex);
142 
143         auto uid = key.GetUid();
144         auto uidIt = mConfigs.find(uid);
145         if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
146             // Remove from map
147             uidIt->second.erase(key);
148 
149             // No more configs for this uid, lets remove the active configs callback.
150             if (uidIt->second.empty()) {
151                 auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
152                     if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
153                         mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
154                     }
155             }
156 
157             for (const sp<ConfigListener>& listener : mListeners) {
158                 broadcastList.push_back(listener);
159             }
160         }
161 
162         auto itReceiver = mConfigReceivers.find(key);
163         if (itReceiver != mConfigReceivers.end()) {
164             // Remove from map
165             mConfigReceivers.erase(itReceiver);
166         }
167 
168         // Remove from disk. There can still be a lingering file on disk so we check
169         // whether or not the config was on memory.
170         remove_saved_configs(key);
171     }
172 
173     for (const sp<ConfigListener>& listener:broadcastList) {
174         listener->OnConfigRemoved(key);
175     }
176 }
177 
remove_saved_configs(const ConfigKey & key)178 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
179     string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
180     StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
181 }
182 
RemoveConfigs(int uid)183 void ConfigManager::RemoveConfigs(int uid) {
184     vector<ConfigKey> removed;
185     vector<sp<ConfigListener>> broadcastList;
186     {
187         lock_guard <mutex> lock(mMutex);
188 
189         auto uidIt = mConfigs.find(uid);
190         if (uidIt == mConfigs.end()) {
191             return;
192         }
193 
194         for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
195             // Remove from map
196                 remove_saved_configs(*it);
197                 removed.push_back(*it);
198                 mConfigReceivers.erase(*it);
199         }
200 
201         auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
202         if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
203             mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
204         }
205 
206         mConfigs.erase(uidIt);
207 
208         for (const sp<ConfigListener>& listener : mListeners) {
209             broadcastList.push_back(listener);
210         }
211     }
212 
213     // Remove separately so if they do anything in the callback they can't mess up our iteration.
214     for (auto& key : removed) {
215         // Tell everyone
216         for (const sp<ConfigListener>& listener:broadcastList) {
217             listener->OnConfigRemoved(key);
218         }
219     }
220 }
221 
RemoveAllConfigs()222 void ConfigManager::RemoveAllConfigs() {
223     vector<ConfigKey> removed;
224     vector<sp<ConfigListener>> broadcastList;
225     {
226         lock_guard <mutex> lock(mMutex);
227 
228         for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
229             for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
230                 // Remove from map
231                 removed.push_back(*it);
232                 it = uidIt->second.erase(it);
233             }
234             uidIt = mConfigs.erase(uidIt);
235         }
236 
237         mConfigReceivers.clear();
238         mActiveConfigsChangedReceivers.clear();
239         for (const sp<ConfigListener>& listener : mListeners) {
240             broadcastList.push_back(listener);
241         }
242     }
243 
244     // Remove separately so if they do anything in the callback they can't mess up our iteration.
245     for (auto& key : removed) {
246         // Tell everyone
247         for (const sp<ConfigListener>& listener:broadcastList) {
248             listener->OnConfigRemoved(key);
249         }
250     }
251 }
252 
GetAllConfigKeys() const253 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
254     lock_guard<mutex> lock(mMutex);
255 
256     vector<ConfigKey> ret;
257     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
258         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
259             ret.push_back(*it);
260         }
261     }
262     return ret;
263 }
264 
GetConfigReceiver(const ConfigKey & key) const265 const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
266     lock_guard<mutex> lock(mMutex);
267 
268     auto it = mConfigReceivers.find(key);
269     if (it == mConfigReceivers.end()) {
270         return nullptr;
271     } else {
272         return it->second;
273     }
274 }
275 
GetActiveConfigsChangedReceiver(const int uid) const276 const sp<android::IBinder> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
277     lock_guard<mutex> lock(mMutex);
278 
279     auto it = mActiveConfigsChangedReceivers.find(uid);
280     if (it == mActiveConfigsChangedReceivers.end()) {
281         return nullptr;
282     } else {
283         return it->second;
284     }
285 }
286 
Dump(FILE * out)287 void ConfigManager::Dump(FILE* out) {
288     lock_guard<mutex> lock(mMutex);
289 
290     fprintf(out, "CONFIGURATIONS\n");
291     fprintf(out, "     uid name\n");
292     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
293         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
294             fprintf(out, "  %6d %lld\n", it->GetUid(), (long long)it->GetId());
295             auto receiverIt = mConfigReceivers.find(*it);
296             if (receiverIt != mConfigReceivers.end()) {
297                 fprintf(out, "    -> received by PendingIntent as binder\n");
298             }
299         }
300     }
301 }
302 
update_saved_configs_locked(const ConfigKey & key,const vector<uint8_t> & buffer,const int numBytes)303 void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
304                                                 const vector<uint8_t>& buffer,
305                                                 const int numBytes) {
306     // If there is a pre-existing config with same key we should first delete it.
307     remove_saved_configs(key);
308 
309     // Then we save the latest config.
310     string file_name =
311         StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
312                      key.GetUid(), (long long)key.GetId());
313     StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
314 }
315 
316 }  // namespace statsd
317 }  // namespace os
318 }  // namespace android
319