• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <android-base/file.h>
29 #include <dirent.h>
30 #include <stdio.h>
31 #include <vector>
32 #include "android-base/stringprintf.h"
33 
34 namespace android {
35 namespace os {
36 namespace statsd {
37 
38 using std::map;
39 using std::pair;
40 using std::set;
41 using std::string;
42 using std::vector;
43 
44 #define STATS_SERVICE_DIR "/data/misc/stats-service"
45 
46 using android::base::StringPrintf;
47 using std::unique_ptr;
48 
ConfigManager()49 ConfigManager::ConfigManager() {
50 }
51 
~ConfigManager()52 ConfigManager::~ConfigManager() {
53 }
54 
Startup()55 void ConfigManager::Startup() {
56     map<ConfigKey, StatsdConfig> configsFromDisk;
57     StorageManager::readConfigFromDisk(configsFromDisk);
58     for (const auto& pair : configsFromDisk) {
59         UpdateConfig(pair.first, pair.second);
60     }
61 }
62 
StartupForTest()63 void ConfigManager::StartupForTest() {
64     // Dummy function to avoid reading configs from disks for tests.
65 }
66 
AddListener(const sp<ConfigListener> & listener)67 void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
68     lock_guard<mutex> lock(mMutex);
69     mListeners.push_back(listener);
70 }
71 
UpdateConfig(const ConfigKey & key,const StatsdConfig & config)72 void ConfigManager::UpdateConfig(const ConfigKey& key, const StatsdConfig& config) {
73     vector<sp<ConfigListener>> broadcastList;
74     {
75         lock_guard <mutex> lock(mMutex);
76 
77         const int numBytes = config.ByteSize();
78         vector<uint8_t> buffer(numBytes);
79         config.SerializeToArray(&buffer[0], numBytes);
80 
81         auto uidIt = mConfigs.find(key.GetUid());
82         // GuardRail: Limit the number of configs per uid.
83         if (uidIt != mConfigs.end()) {
84             auto it = uidIt->second.find(key);
85             if (it == uidIt->second.end() &&
86                 uidIt->second.size() >= StatsdStats::kMaxConfigCountPerUid) {
87                 ALOGE("ConfigManager: uid %d has exceeded the config count limit", key.GetUid());
88                 return;
89             }
90         }
91 
92         // Check if it's a duplicate config.
93         if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end() &&
94             StorageManager::hasIdenticalConfig(key, buffer)) {
95             // This is a duplicate config.
96             ALOGI("ConfigManager This is a duplicate config %s", key.ToString().c_str());
97             // Update saved file on disk. We still update timestamp of file when
98             // there exists a duplicate configuration to avoid garbage collection.
99             update_saved_configs_locked(key, buffer, numBytes);
100             return;
101         }
102 
103         // Update saved file on disk.
104         update_saved_configs_locked(key, buffer, numBytes);
105 
106         // Add to set.
107         mConfigs[key.GetUid()].insert(key);
108 
109         for (const sp<ConfigListener>& listener : mListeners) {
110             broadcastList.push_back(listener);
111         }
112     }
113 
114     const int64_t timestampNs = getElapsedRealtimeNs();
115     // Tell everyone
116     for (const sp<ConfigListener>& listener : broadcastList) {
117         listener->OnConfigUpdated(timestampNs, key, config);
118     }
119 }
120 
SetConfigReceiver(const ConfigKey & key,const sp<IBinder> & intentSender)121 void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) {
122     lock_guard<mutex> lock(mMutex);
123     mConfigReceivers[key] = intentSender;
124 }
125 
RemoveConfigReceiver(const ConfigKey & key)126 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) {
127     lock_guard<mutex> lock(mMutex);
128     mConfigReceivers.erase(key);
129 }
130 
SetActiveConfigsChangedReceiver(const int uid,const sp<IBinder> & intentSender)131 void ConfigManager::SetActiveConfigsChangedReceiver(const int uid,
132                                                     const sp<IBinder>& intentSender) {
133     lock_guard<mutex> lock(mMutex);
134     mActiveConfigsChangedReceivers[uid] = intentSender;
135 }
136 
RemoveActiveConfigsChangedReceiver(const int uid)137 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) {
138     lock_guard<mutex> lock(mMutex);
139     mActiveConfigsChangedReceivers.erase(uid);
140 }
141 
RemoveConfig(const ConfigKey & key)142 void ConfigManager::RemoveConfig(const ConfigKey& key) {
143     vector<sp<ConfigListener>> broadcastList;
144     {
145         lock_guard <mutex> lock(mMutex);
146 
147         auto uid = key.GetUid();
148         auto uidIt = mConfigs.find(uid);
149         if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
150             // Remove from map
151             uidIt->second.erase(key);
152 
153             // No more configs for this uid, lets remove the active configs callback.
154             if (uidIt->second.empty()) {
155                 auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
156                     if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
157                         mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
158                     }
159             }
160 
161             for (const sp<ConfigListener>& listener : mListeners) {
162                 broadcastList.push_back(listener);
163             }
164         }
165 
166         auto itReceiver = mConfigReceivers.find(key);
167         if (itReceiver != mConfigReceivers.end()) {
168             // Remove from map
169             mConfigReceivers.erase(itReceiver);
170         }
171 
172         // Remove from disk. There can still be a lingering file on disk so we check
173         // whether or not the config was on memory.
174         remove_saved_configs(key);
175     }
176 
177     for (const sp<ConfigListener>& listener:broadcastList) {
178         listener->OnConfigRemoved(key);
179     }
180 }
181 
remove_saved_configs(const ConfigKey & key)182 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
183     string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
184     StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
185 }
186 
RemoveConfigs(int uid)187 void ConfigManager::RemoveConfigs(int uid) {
188     vector<ConfigKey> removed;
189     vector<sp<ConfigListener>> broadcastList;
190     {
191         lock_guard <mutex> lock(mMutex);
192 
193         auto uidIt = mConfigs.find(uid);
194         if (uidIt == mConfigs.end()) {
195             return;
196         }
197 
198         for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
199             // Remove from map
200                 remove_saved_configs(*it);
201                 removed.push_back(*it);
202                 mConfigReceivers.erase(*it);
203         }
204 
205         auto itActiveConfigsChangedReceiver = mActiveConfigsChangedReceivers.find(uid);
206         if (itActiveConfigsChangedReceiver != mActiveConfigsChangedReceivers.end()) {
207             mActiveConfigsChangedReceivers.erase(itActiveConfigsChangedReceiver);
208         }
209 
210         mConfigs.erase(uidIt);
211 
212         for (const sp<ConfigListener>& listener : mListeners) {
213             broadcastList.push_back(listener);
214         }
215     }
216 
217     // Remove separately so if they do anything in the callback they can't mess up our iteration.
218     for (auto& key : removed) {
219         // Tell everyone
220         for (const sp<ConfigListener>& listener:broadcastList) {
221             listener->OnConfigRemoved(key);
222         }
223     }
224 }
225 
RemoveAllConfigs()226 void ConfigManager::RemoveAllConfigs() {
227     vector<ConfigKey> removed;
228     vector<sp<ConfigListener>> broadcastList;
229     {
230         lock_guard <mutex> lock(mMutex);
231 
232         for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
233             for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
234                 // Remove from map
235                 removed.push_back(*it);
236                 it = uidIt->second.erase(it);
237             }
238             uidIt = mConfigs.erase(uidIt);
239         }
240 
241         mConfigReceivers.clear();
242         mActiveConfigsChangedReceivers.clear();
243         for (const sp<ConfigListener>& listener : mListeners) {
244             broadcastList.push_back(listener);
245         }
246     }
247 
248     // Remove separately so if they do anything in the callback they can't mess up our iteration.
249     for (auto& key : removed) {
250         // Tell everyone
251         for (const sp<ConfigListener>& listener:broadcastList) {
252             listener->OnConfigRemoved(key);
253         }
254     }
255 }
256 
GetAllConfigKeys() const257 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
258     lock_guard<mutex> lock(mMutex);
259 
260     vector<ConfigKey> ret;
261     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
262         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
263             ret.push_back(*it);
264         }
265     }
266     return ret;
267 }
268 
GetConfigReceiver(const ConfigKey & key) const269 const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
270     lock_guard<mutex> lock(mMutex);
271 
272     auto it = mConfigReceivers.find(key);
273     if (it == mConfigReceivers.end()) {
274         return nullptr;
275     } else {
276         return it->second;
277     }
278 }
279 
GetActiveConfigsChangedReceiver(const int uid) const280 const sp<android::IBinder> ConfigManager::GetActiveConfigsChangedReceiver(const int uid) const {
281     lock_guard<mutex> lock(mMutex);
282 
283     auto it = mActiveConfigsChangedReceivers.find(uid);
284     if (it == mActiveConfigsChangedReceivers.end()) {
285         return nullptr;
286     } else {
287         return it->second;
288     }
289 }
290 
Dump(FILE * out)291 void ConfigManager::Dump(FILE* out) {
292     lock_guard<mutex> lock(mMutex);
293 
294     fprintf(out, "CONFIGURATIONS\n");
295     fprintf(out, "     uid name\n");
296     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
297         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
298             fprintf(out, "  %6d %lld\n", it->GetUid(), (long long)it->GetId());
299             auto receiverIt = mConfigReceivers.find(*it);
300             if (receiverIt != mConfigReceivers.end()) {
301                 fprintf(out, "    -> received by PendingIntent as binder\n");
302             }
303         }
304     }
305 }
306 
update_saved_configs_locked(const ConfigKey & key,const vector<uint8_t> & buffer,const int numBytes)307 void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
308                                                 const vector<uint8_t>& buffer,
309                                                 const int numBytes) {
310     // If there is a pre-existing config with same key we should first delete it.
311     remove_saved_configs(key);
312 
313     // Then we save the latest config.
314     string file_name =
315         StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
316                      key.GetUid(), (long long)key.GetId());
317     StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
318 }
319 
320 }  // namespace statsd
321 }  // namespace os
322 }  // namespace android
323