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 { 46 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 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 { 80 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 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 113 ConfigManager::ConfigManager() : 114 mConfigReceiverDeathRecipient(AIBinder_DeathRecipient_new(configReceiverDied)), 115 mActiveConfigChangedReceiverDeathRecipient( 116 AIBinder_DeathRecipient_new(activeConfigChangedReceiverDied)) { 117 } 118 119 ConfigManager::~ConfigManager() { 120 } 121 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 130 void ConfigManager::StartupForTest() { 131 // No-op function to avoid reading configs from disks for tests. 132 } 133 134 void ConfigManager::AddListener(const sp<ConfigListener>& listener) { 135 lock_guard<mutex> lock(mMutex); 136 mListeners.push_back(listener); 137 } 138 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 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 196 void ConfigManager::RemoveConfigReceiver(const ConfigKey& key) { 197 lock_guard<mutex> lock(mMutex); 198 mConfigReceivers.erase(key); 199 } 200 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 211 void ConfigManager::RemoveActiveConfigsChangedReceiver(const int uid) { 212 lock_guard<mutex> lock(mMutex); 213 mActiveConfigsChangedReceivers.erase(uid); 214 } 215 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 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 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 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 309 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 321 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 332 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 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 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