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 49 ConfigManager::ConfigManager() { 50 } 51 52 ConfigManager::~ConfigManager() { 53 } 54 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 63 void ConfigManager::StartupForTest() { 64 // Dummy function to avoid reading configs from disks for tests. 65 } 66 67 void ConfigManager::AddListener(const sp<ConfigListener>& listener) { 68 lock_guard<mutex> lock(mMutex); 69 mListeners.push_back(listener); 70 } 71 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 121 void ConfigManager::SetConfigReceiver(const ConfigKey& key, const sp<IBinder>& intentSender) { 122 lock_guard<mutex> lock(mMutex); 123 mConfigReceivers[key] = intentSender; 124 } 125 126 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) { 127 lock_guard<mutex> lock(mMutex); 128 mConfigReceivers.erase(key); 129 } 130 131 void ConfigManager::SetActiveConfigsChangedReceiver(const int uid, 132 const sp<IBinder>& intentSender) { 133 lock_guard<mutex> lock(mMutex); 134 mActiveConfigsChangedReceivers[uid] = intentSender; 135 } 136 137 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) { 138 lock_guard<mutex> lock(mMutex); 139 mActiveConfigsChangedReceivers.erase(uid); 140 } 141 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 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 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 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 257 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 269 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 280 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 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 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