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 (sp<ConfigListener> listener : mListeners) {
    110             broadcastList.push_back(listener);
    111         }
    112     }
    113 
    114     const int64_t timestampNs = getElapsedRealtimeNs();
    115     // Tell everyone
    116     for (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::RemoveConfig(const ConfigKey& key) {
    132     vector<sp<ConfigListener>> broadcastList;
    133     {
    134         lock_guard <mutex> lock(mMutex);
    135 
    136         auto uidIt = mConfigs.find(key.GetUid());
    137         if (uidIt != mConfigs.end() && uidIt->second.find(key) != uidIt->second.end()) {
    138             // Remove from map
    139             uidIt->second.erase(key);
    140             for (sp<ConfigListener> listener : mListeners) {
    141                 broadcastList.push_back(listener);
    142             }
    143         }
    144 
    145         auto itReceiver = mConfigReceivers.find(key);
    146         if (itReceiver != mConfigReceivers.end()) {
    147             // Remove from map
    148             mConfigReceivers.erase(itReceiver);
    149         }
    150 
    151         // Remove from disk. There can still be a lingering file on disk so we check
    152         // whether or not the config was on memory.
    153         remove_saved_configs(key);
    154     }
    155 
    156     for (sp<ConfigListener> listener:broadcastList) {
    157         listener->OnConfigRemoved(key);
    158     }
    159 }
    160 
    161 void ConfigManager::remove_saved_configs(const ConfigKey& key) {
    162     string suffix = StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId());
    163     StorageManager::deleteSuffixedFiles(STATS_SERVICE_DIR, suffix.c_str());
    164 }
    165 
    166 void ConfigManager::RemoveConfigs(int uid) {
    167     vector<ConfigKey> removed;
    168     vector<sp<ConfigListener>> broadcastList;
    169     {
    170         lock_guard <mutex> lock(mMutex);
    171 
    172         auto uidIt = mConfigs.find(uid);
    173         if (uidIt == mConfigs.end()) {
    174             return;
    175         }
    176 
    177         for (auto it = uidIt->second.begin(); it != uidIt->second.end(); ++it) {
    178             // Remove from map
    179                 remove_saved_configs(*it);
    180                 removed.push_back(*it);
    181                 mConfigReceivers.erase(*it);
    182         }
    183 
    184         mConfigs.erase(uidIt);
    185 
    186         for (sp<ConfigListener> listener : mListeners) {
    187             broadcastList.push_back(listener);
    188         }
    189     }
    190 
    191     // Remove separately so if they do anything in the callback they can't mess up our iteration.
    192     for (auto& key : removed) {
    193         // Tell everyone
    194         for (sp<ConfigListener> listener:broadcastList) {
    195             listener->OnConfigRemoved(key);
    196         }
    197     }
    198 }
    199 
    200 void ConfigManager::RemoveAllConfigs() {
    201     vector<ConfigKey> removed;
    202     vector<sp<ConfigListener>> broadcastList;
    203     {
    204         lock_guard <mutex> lock(mMutex);
    205 
    206         for (auto uidIt = mConfigs.begin(); uidIt != mConfigs.end();) {
    207             for (auto it = uidIt->second.begin(); it != uidIt->second.end();) {
    208                 // Remove from map
    209                 removed.push_back(*it);
    210                 it = uidIt->second.erase(it);
    211             }
    212             uidIt = mConfigs.erase(uidIt);
    213         }
    214 
    215         mConfigReceivers.clear();
    216         for (sp<ConfigListener> listener : mListeners) {
    217             broadcastList.push_back(listener);
    218         }
    219     }
    220 
    221     // Remove separately so if they do anything in the callback they can't mess up our iteration.
    222     for (auto& key : removed) {
    223         // Tell everyone
    224         for (sp<ConfigListener> listener:broadcastList) {
    225             listener->OnConfigRemoved(key);
    226         }
    227     }
    228 }
    229 
    230 vector<ConfigKey> ConfigManager::GetAllConfigKeys() const {
    231     lock_guard<mutex> lock(mMutex);
    232 
    233     vector<ConfigKey> ret;
    234     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
    235         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
    236             ret.push_back(*it);
    237         }
    238     }
    239     return ret;
    240 }
    241 
    242 const sp<android::IBinder> ConfigManager::GetConfigReceiver(const ConfigKey& key) const {
    243     lock_guard<mutex> lock(mMutex);
    244 
    245     auto it = mConfigReceivers.find(key);
    246     if (it == mConfigReceivers.end()) {
    247         return nullptr;
    248     } else {
    249         return it->second;
    250     }
    251 }
    252 
    253 void ConfigManager::Dump(FILE* out) {
    254     lock_guard<mutex> lock(mMutex);
    255 
    256     fprintf(out, "CONFIGURATIONS\n");
    257     fprintf(out, "     uid name\n");
    258     for (auto uidIt = mConfigs.cbegin(); uidIt != mConfigs.cend(); ++uidIt) {
    259         for (auto it = uidIt->second.cbegin(); it != uidIt->second.cend(); ++it) {
    260             fprintf(out, "  %6d %lld\n", it->GetUid(), (long long)it->GetId());
    261             auto receiverIt = mConfigReceivers.find(*it);
    262             if (receiverIt != mConfigReceivers.end()) {
    263                 fprintf(out, "    -> received by PendingIntent as binder\n");
    264             }
    265         }
    266     }
    267 }
    268 
    269 void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
    270                                                 const vector<uint8_t>& buffer,
    271                                                 const int numBytes) {
    272     // If there is a pre-existing config with same key we should first delete it.
    273     remove_saved_configs(key);
    274 
    275     // Then we save the latest config.
    276     string file_name =
    277         StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
    278                      key.GetUid(), (long long)key.GetId());
    279     StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
    280 }
    281 
    282 }  // namespace statsd
    283 }  // namespace os
    284 }  // namespace android
    285