Home | History | Annotate | Download | only in config
      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