Home | History | Annotate | Download | only in packages
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, versionCode 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 #define DEBUG false  // STOPSHIP if true
     17 #include "Log.h"
     18 
     19 #include "hash.h"
     20 #include "stats_log_util.h"
     21 #include "guardrail/StatsdStats.h"
     22 #include "packages/UidMap.h"
     23 
     24 #include <android/os/IStatsCompanionService.h>
     25 #include <binder/IServiceManager.h>
     26 #include <utils/Errors.h>
     27 
     28 #include <inttypes.h>
     29 
     30 using namespace android;
     31 
     32 using android::base::StringPrintf;
     33 using android::util::FIELD_COUNT_REPEATED;
     34 using android::util::FIELD_TYPE_BOOL;
     35 using android::util::FIELD_TYPE_FLOAT;
     36 using android::util::FIELD_TYPE_INT32;
     37 using android::util::FIELD_TYPE_INT64;
     38 using android::util::FIELD_TYPE_UINT64;
     39 using android::util::FIELD_TYPE_MESSAGE;
     40 using android::util::FIELD_TYPE_STRING;
     41 using android::util::ProtoOutputStream;
     42 
     43 namespace android {
     44 namespace os {
     45 namespace statsd {
     46 
     47 const int FIELD_ID_SNAPSHOT_PACKAGE_NAME = 1;
     48 const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION = 2;
     49 const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
     50 const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
     51 const int FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH = 5;
     52 const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
     53 const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
     54 const int FIELD_ID_SNAPSHOTS = 1;
     55 const int FIELD_ID_CHANGES = 2;
     56 const int FIELD_ID_CHANGE_DELETION = 1;
     57 const int FIELD_ID_CHANGE_TIMESTAMP = 2;
     58 const int FIELD_ID_CHANGE_PACKAGE = 3;
     59 const int FIELD_ID_CHANGE_UID = 4;
     60 const int FIELD_ID_CHANGE_NEW_VERSION = 5;
     61 const int FIELD_ID_CHANGE_PREV_VERSION = 6;
     62 const int FIELD_ID_CHANGE_PACKAGE_HASH = 7;
     63 
     64 UidMap::UidMap() : mBytesUsed(0) {}
     65 
     66 UidMap::~UidMap() {}
     67 
     68 bool UidMap::hasApp(int uid, const string& packageName) const {
     69     lock_guard<mutex> lock(mMutex);
     70 
     71     auto it = mMap.find(std::make_pair(uid, packageName));
     72     return it != mMap.end() && !it->second.deleted;
     73 }
     74 
     75 string UidMap::normalizeAppName(const string& appName) const {
     76     string normalizedName = appName;
     77     std::transform(normalizedName.begin(), normalizedName.end(), normalizedName.begin(), ::tolower);
     78     return normalizedName;
     79 }
     80 
     81 std::set<string> UidMap::getAppNamesFromUid(const int32_t& uid, bool returnNormalized) const {
     82     lock_guard<mutex> lock(mMutex);
     83     return getAppNamesFromUidLocked(uid,returnNormalized);
     84 }
     85 
     86 std::set<string> UidMap::getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const {
     87     std::set<string> names;
     88     for (const auto& kv : mMap) {
     89         if (kv.first.first == uid && !kv.second.deleted) {
     90             names.insert(returnNormalized ? normalizeAppName(kv.first.second) : kv.first.second);
     91         }
     92     }
     93     return names;
     94 }
     95 
     96 int64_t UidMap::getAppVersion(int uid, const string& packageName) const {
     97     lock_guard<mutex> lock(mMutex);
     98 
     99     auto it = mMap.find(std::make_pair(uid, packageName));
    100     if (it == mMap.end() || it->second.deleted) {
    101         return 0;
    102     }
    103     return it->second.versionCode;
    104 }
    105 
    106 void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
    107                        const vector<int64_t>& versionCode, const vector<String16>& packageName) {
    108     vector<wp<PackageInfoListener>> broadcastList;
    109     {
    110         lock_guard<mutex> lock(mMutex);  // Exclusively lock for updates.
    111 
    112         std::unordered_map<std::pair<int, string>, AppData, PairHash> deletedApps;
    113 
    114         // Copy all the deleted apps.
    115         for (const auto& kv : mMap) {
    116             if (kv.second.deleted) {
    117                 deletedApps[kv.first] = kv.second;
    118             }
    119         }
    120 
    121         mMap.clear();
    122         for (size_t j = 0; j < uid.size(); j++) {
    123             string package = string(String8(packageName[j]).string());
    124             mMap[std::make_pair(uid[j], package)] = AppData(versionCode[j]);
    125         }
    126 
    127         for (const auto& kv : deletedApps) {
    128             auto mMapIt = mMap.find(kv.first);
    129             if (mMapIt != mMap.end()) {
    130                 // Insert this deleted app back into the current map.
    131                 mMap[kv.first] = kv.second;
    132             }
    133         }
    134 
    135         ensureBytesUsedBelowLimit();
    136         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
    137         getListenerListCopyLocked(&broadcastList);
    138     }
    139     // To avoid invoking callback while holding the internal lock. we get a copy of the listener
    140     // list and invoke the callback. It's still possible that after we copy the list, a
    141     // listener removes itself before we call it. It's then the listener's job to handle it (expect
    142     // the callback to be called after listener is removed, and the listener should properly
    143     // ignore it).
    144     for (auto weakPtr : broadcastList) {
    145         auto strongPtr = weakPtr.promote();
    146         if (strongPtr != NULL) {
    147             strongPtr->onUidMapReceived(timestamp);
    148         }
    149     }
    150 }
    151 
    152 void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
    153                        const int64_t& versionCode) {
    154     vector<wp<PackageInfoListener>> broadcastList;
    155     string appName = string(String8(app_16).string());
    156     {
    157         lock_guard<mutex> lock(mMutex);
    158         int32_t prevVersion = 0;
    159         bool found = false;
    160         auto it = mMap.find(std::make_pair(uid, appName));
    161         if (it != mMap.end()) {
    162             found = true;
    163             prevVersion = it->second.versionCode;
    164             it->second.versionCode = versionCode;
    165             it->second.deleted = false;
    166         }
    167         if (!found) {
    168             // Otherwise, we need to add an app at this uid.
    169             mMap[std::make_pair(uid, appName)] = AppData(versionCode);
    170         } else {
    171             // Only notify the listeners if this is an app upgrade. If this app is being installed
    172             // for the first time, then we don't notify the listeners.
    173             // It's also OK to split again if we're forming a partial bucket after re-installing an
    174             // app after deletion.
    175             getListenerListCopyLocked(&broadcastList);
    176         }
    177         mChanges.emplace_back(false, timestamp, appName, uid, versionCode, prevVersion);
    178         mBytesUsed += kBytesChangeRecord;
    179         ensureBytesUsedBelowLimit();
    180         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
    181         StatsdStats::getInstance().setUidMapChanges(mChanges.size());
    182     }
    183 
    184     for (auto weakPtr : broadcastList) {
    185         auto strongPtr = weakPtr.promote();
    186         if (strongPtr != NULL) {
    187             strongPtr->notifyAppUpgrade(timestamp, appName, uid, versionCode);
    188         }
    189     }
    190 }
    191 
    192 void UidMap::ensureBytesUsedBelowLimit() {
    193     size_t limit;
    194     if (maxBytesOverride <= 0) {
    195         limit = StatsdStats::kMaxBytesUsedUidMap;
    196     } else {
    197         limit = maxBytesOverride;
    198     }
    199     while (mBytesUsed > limit) {
    200         ALOGI("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
    201         if (mChanges.size() > 0) {
    202             mBytesUsed -= kBytesChangeRecord;
    203             mChanges.pop_front();
    204             StatsdStats::getInstance().noteUidMapDropped(1);
    205         }
    206     }
    207 }
    208 
    209 void UidMap::getListenerListCopyLocked(vector<wp<PackageInfoListener>>* output) {
    210     for (auto weakIt = mSubscribers.begin(); weakIt != mSubscribers.end();) {
    211         auto strongPtr = weakIt->promote();
    212         if (strongPtr != NULL) {
    213             output->push_back(*weakIt);
    214             weakIt++;
    215         } else {
    216             weakIt = mSubscribers.erase(weakIt);
    217             VLOG("The UidMap listener is gone, remove it now");
    218         }
    219     }
    220 }
    221 
    222 void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid) {
    223     vector<wp<PackageInfoListener>> broadcastList;
    224     string app = string(String8(app_16).string());
    225     {
    226         lock_guard<mutex> lock(mMutex);
    227 
    228         int64_t prevVersion = 0;
    229         auto key = std::make_pair(uid, app);
    230         auto it = mMap.find(key);
    231         if (it != mMap.end() && !it->second.deleted) {
    232             prevVersion = it->second.versionCode;
    233             it->second.deleted = true;
    234             mDeletedApps.push_back(key);
    235         }
    236         if (mDeletedApps.size() > StatsdStats::kMaxDeletedAppsInUidMap) {
    237             // Delete the oldest one.
    238             auto oldest = mDeletedApps.front();
    239             mDeletedApps.pop_front();
    240             mMap.erase(oldest);
    241             StatsdStats::getInstance().noteUidMapAppDeletionDropped();
    242         }
    243         mChanges.emplace_back(true, timestamp, app, uid, 0, prevVersion);
    244         mBytesUsed += kBytesChangeRecord;
    245         ensureBytesUsedBelowLimit();
    246         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
    247         StatsdStats::getInstance().setUidMapChanges(mChanges.size());
    248         getListenerListCopyLocked(&broadcastList);
    249     }
    250 
    251     for (auto weakPtr : broadcastList) {
    252         auto strongPtr = weakPtr.promote();
    253         if (strongPtr != NULL) {
    254             strongPtr->notifyAppRemoved(timestamp, app, uid);
    255         }
    256     }
    257 }
    258 
    259 void UidMap::addListener(wp<PackageInfoListener> producer) {
    260     lock_guard<mutex> lock(mMutex);  // Lock for updates
    261     mSubscribers.insert(producer);
    262 }
    263 
    264 void UidMap::removeListener(wp<PackageInfoListener> producer) {
    265     lock_guard<mutex> lock(mMutex);  // Lock for updates
    266     mSubscribers.erase(producer);
    267 }
    268 
    269 void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) {
    270     lock_guard<mutex> lock(mIsolatedMutex);
    271 
    272     mIsolatedUidMap[isolatedUid] = parentUid;
    273 }
    274 
    275 void UidMap::removeIsolatedUid(int isolatedUid, int parentUid) {
    276     lock_guard<mutex> lock(mIsolatedMutex);
    277 
    278     auto it = mIsolatedUidMap.find(isolatedUid);
    279     if (it != mIsolatedUidMap.end()) {
    280         mIsolatedUidMap.erase(it);
    281     }
    282 }
    283 
    284 int UidMap::getHostUidOrSelf(int uid) const {
    285     lock_guard<mutex> lock(mIsolatedMutex);
    286 
    287     auto it = mIsolatedUidMap.find(uid);
    288     if (it != mIsolatedUidMap.end()) {
    289         return it->second;
    290     }
    291     return uid;
    292 }
    293 
    294 void UidMap::clearOutput() {
    295     mChanges.clear();
    296     // Also update the guardrail trackers.
    297     StatsdStats::getInstance().setUidMapChanges(0);
    298     mBytesUsed = 0;
    299     StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
    300 }
    301 
    302 int64_t UidMap::getMinimumTimestampNs() {
    303     int64_t m = 0;
    304     for (const auto& kv : mLastUpdatePerConfigKey) {
    305         if (m == 0) {
    306             m = kv.second;
    307         } else if (kv.second < m) {
    308             m = kv.second;
    309         }
    310     }
    311     return m;
    312 }
    313 
    314 size_t UidMap::getBytesUsed() const {
    315     return mBytesUsed;
    316 }
    317 
    318 void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
    319                           std::set<string> *str_set, ProtoOutputStream* proto) {
    320     lock_guard<mutex> lock(mMutex);  // Lock for updates
    321 
    322     for (const ChangeRecord& record : mChanges) {
    323         if (record.timestampNs > mLastUpdatePerConfigKey[key]) {
    324             uint64_t changesToken =
    325                     proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CHANGES);
    326             proto->write(FIELD_TYPE_BOOL | FIELD_ID_CHANGE_DELETION, (bool)record.deletion);
    327             proto->write(FIELD_TYPE_INT64 | FIELD_ID_CHANGE_TIMESTAMP,
    328                          (long long)record.timestampNs);
    329             if (str_set != nullptr) {
    330                 str_set->insert(record.package);
    331                 proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PACKAGE_HASH,
    332                              (long long)Hash64(record.package));
    333             } else {
    334                 proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
    335             }
    336 
    337             proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
    338             proto->write(FIELD_TYPE_INT64 | FIELD_ID_CHANGE_NEW_VERSION, (long long)record.version);
    339             proto->write(FIELD_TYPE_INT64 | FIELD_ID_CHANGE_PREV_VERSION,
    340                          (long long)record.prevVersion);
    341             proto->end(changesToken);
    342         }
    343     }
    344 
    345     // Write snapshot from current uid map state.
    346     uint64_t snapshotsToken =
    347             proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
    348     proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
    349     for (const auto& kv : mMap) {
    350         uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
    351                                       FIELD_ID_SNAPSHOT_PACKAGE_INFO);
    352 
    353         if (str_set != nullptr) {
    354             str_set->insert(kv.first.second);
    355             proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
    356                          (long long)Hash64(kv.first.second));
    357         } else {
    358             proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
    359         }
    360 
    361         proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
    362                      (long long)kv.second.versionCode);
    363         proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
    364         proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
    365         proto->end(token);
    366     }
    367     proto->end(snapshotsToken);
    368 
    369     int64_t prevMin = getMinimumTimestampNs();
    370     mLastUpdatePerConfigKey[key] = timestamp;
    371     int64_t newMin = getMinimumTimestampNs();
    372 
    373     if (newMin > prevMin) {  // Delete anything possible now that the minimum has
    374                              // moved forward.
    375         int64_t cutoff_nanos = newMin;
    376         for (auto it_changes = mChanges.begin(); it_changes != mChanges.end();) {
    377             if (it_changes->timestampNs < cutoff_nanos) {
    378                 mBytesUsed -= kBytesChangeRecord;
    379                 it_changes = mChanges.erase(it_changes);
    380             } else {
    381                 ++it_changes;
    382             }
    383         }
    384     }
    385     StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
    386     StatsdStats::getInstance().setUidMapChanges(mChanges.size());
    387 }
    388 
    389 void UidMap::printUidMap(FILE* out) const {
    390     lock_guard<mutex> lock(mMutex);
    391 
    392     for (const auto& kv : mMap) {
    393         if (!kv.second.deleted) {
    394             fprintf(out, "%s, v%" PRId64 " (%i)\n", kv.first.second.c_str(), kv.second.versionCode,
    395                     kv.first.first);
    396         }
    397     }
    398 }
    399 
    400 void UidMap::OnConfigUpdated(const ConfigKey& key) {
    401     mLastUpdatePerConfigKey[key] = -1;
    402 }
    403 
    404 void UidMap::OnConfigRemoved(const ConfigKey& key) {
    405     mLastUpdatePerConfigKey.erase(key);
    406 }
    407 
    408 set<int32_t> UidMap::getAppUid(const string& package) const {
    409     lock_guard<mutex> lock(mMutex);
    410 
    411     set<int32_t> results;
    412     for (const auto& kv : mMap) {
    413         if (kv.first.second == package && !kv.second.deleted) {
    414             results.insert(kv.first.first);
    415         }
    416     }
    417     return results;
    418 }
    419 
    420 // Note not all the following AIDs are used as uids. Some are used only for gids.
    421 // It's ok to leave them in the map, but we won't ever see them in the log's uid field.
    422 // App's uid starts from 10000, and will not overlap with the following AIDs.
    423 const std::map<string, uint32_t> UidMap::sAidToUidMapping = {{"AID_ROOT", 0},
    424                                                              {"AID_SYSTEM", 1000},
    425                                                              {"AID_RADIO", 1001},
    426                                                              {"AID_BLUETOOTH", 1002},
    427                                                              {"AID_GRAPHICS", 1003},
    428                                                              {"AID_INPUT", 1004},
    429                                                              {"AID_AUDIO", 1005},
    430                                                              {"AID_CAMERA", 1006},
    431                                                              {"AID_LOG", 1007},
    432                                                              {"AID_COMPASS", 1008},
    433                                                              {"AID_MOUNT", 1009},
    434                                                              {"AID_WIFI", 1010},
    435                                                              {"AID_ADB", 1011},
    436                                                              {"AID_INSTALL", 1012},
    437                                                              {"AID_MEDIA", 1013},
    438                                                              {"AID_DHCP", 1014},
    439                                                              {"AID_SDCARD_RW", 1015},
    440                                                              {"AID_VPN", 1016},
    441                                                              {"AID_KEYSTORE", 1017},
    442                                                              {"AID_USB", 1018},
    443                                                              {"AID_DRM", 1019},
    444                                                              {"AID_MDNSR", 1020},
    445                                                              {"AID_GPS", 1021},
    446                                                              // {"AID_UNUSED1", 1022},
    447                                                              {"AID_MEDIA_RW", 1023},
    448                                                              {"AID_MTP", 1024},
    449                                                              // {"AID_UNUSED2", 1025},
    450                                                              {"AID_DRMRPC", 1026},
    451                                                              {"AID_NFC", 1027},
    452                                                              {"AID_SDCARD_R", 1028},
    453                                                              {"AID_CLAT", 1029},
    454                                                              {"AID_LOOP_RADIO", 1030},
    455                                                              {"AID_MEDIA_DRM", 1031},
    456                                                              {"AID_PACKAGE_INFO", 1032},
    457                                                              {"AID_SDCARD_PICS", 1033},
    458                                                              {"AID_SDCARD_AV", 1034},
    459                                                              {"AID_SDCARD_ALL", 1035},
    460                                                              {"AID_LOGD", 1036},
    461                                                              {"AID_SHARED_RELRO", 1037},
    462                                                              {"AID_DBUS", 1038},
    463                                                              {"AID_TLSDATE", 1039},
    464                                                              {"AID_MEDIA_EX", 1040},
    465                                                              {"AID_AUDIOSERVER", 1041},
    466                                                              {"AID_METRICS_COLL", 1042},
    467                                                              {"AID_METRICSD", 1043},
    468                                                              {"AID_WEBSERV", 1044},
    469                                                              {"AID_DEBUGGERD", 1045},
    470                                                              {"AID_MEDIA_CODEC", 1046},
    471                                                              {"AID_CAMERASERVER", 1047},
    472                                                              {"AID_FIREWALL", 1048},
    473                                                              {"AID_TRUNKS", 1049},
    474                                                              {"AID_NVRAM", 1050},
    475                                                              {"AID_DNS", 1051},
    476                                                              {"AID_DNS_TETHER", 1052},
    477                                                              {"AID_WEBVIEW_ZYGOTE", 1053},
    478                                                              {"AID_VEHICLE_NETWORK", 1054},
    479                                                              {"AID_MEDIA_AUDIO", 1055},
    480                                                              {"AID_MEDIA_VIDEO", 1056},
    481                                                              {"AID_MEDIA_IMAGE", 1057},
    482                                                              {"AID_TOMBSTONED", 1058},
    483                                                              {"AID_MEDIA_OBB", 1059},
    484                                                              {"AID_ESE", 1060},
    485                                                              {"AID_OTA_UPDATE", 1061},
    486                                                              {"AID_AUTOMOTIVE_EVS", 1062},
    487                                                              {"AID_LOWPAN", 1063},
    488                                                              {"AID_HSM", 1064},
    489                                                              {"AID_RESERVED_DISK", 1065},
    490                                                              {"AID_STATSD", 1066},
    491                                                              {"AID_INCIDENTD", 1067},
    492                                                              {"AID_SHELL", 2000},
    493                                                              {"AID_CACHE", 2001},
    494                                                              {"AID_DIAG", 2002}};
    495 
    496 }  // namespace statsd
    497 }  // namespace os
    498 }  // namespace android
    499