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
30using namespace android;
31
32using android::base::StringPrintf;
33using android::util::FIELD_COUNT_REPEATED;
34using android::util::FIELD_TYPE_BOOL;
35using android::util::FIELD_TYPE_FLOAT;
36using android::util::FIELD_TYPE_INT32;
37using android::util::FIELD_TYPE_INT64;
38using android::util::FIELD_TYPE_UINT64;
39using android::util::FIELD_TYPE_MESSAGE;
40using android::util::FIELD_TYPE_STRING;
41using android::util::ProtoOutputStream;
42
43namespace android {
44namespace os {
45namespace statsd {
46
47const int FIELD_ID_SNAPSHOT_PACKAGE_NAME = 1;
48const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION = 2;
49const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
50const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
51const int FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH = 5;
52const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
53const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
54const int FIELD_ID_SNAPSHOTS = 1;
55const int FIELD_ID_CHANGES = 2;
56const int FIELD_ID_CHANGE_DELETION = 1;
57const int FIELD_ID_CHANGE_TIMESTAMP = 2;
58const int FIELD_ID_CHANGE_PACKAGE = 3;
59const int FIELD_ID_CHANGE_UID = 4;
60const int FIELD_ID_CHANGE_NEW_VERSION = 5;
61const int FIELD_ID_CHANGE_PREV_VERSION = 6;
62const int FIELD_ID_CHANGE_PACKAGE_HASH = 7;
63
64UidMap::UidMap() : mBytesUsed(0) {}
65
66UidMap::~UidMap() {}
67
68bool 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
75string 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
81std::set<string> UidMap::getAppNamesFromUid(const int32_t& uid, bool returnNormalized) const {
82    lock_guard<mutex> lock(mMutex);
83    return getAppNamesFromUidLocked(uid,returnNormalized);
84}
85
86std::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
96int64_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
106void 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
152void 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
192void 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
209void 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
222void 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
259void UidMap::addListener(wp<PackageInfoListener> producer) {
260    lock_guard<mutex> lock(mMutex);  // Lock for updates
261    mSubscribers.insert(producer);
262}
263
264void UidMap::removeListener(wp<PackageInfoListener> producer) {
265    lock_guard<mutex> lock(mMutex);  // Lock for updates
266    mSubscribers.erase(producer);
267}
268
269void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) {
270    lock_guard<mutex> lock(mIsolatedMutex);
271
272    mIsolatedUidMap[isolatedUid] = parentUid;
273}
274
275void 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
284int 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
294void 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
302int64_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
314size_t UidMap::getBytesUsed() const {
315    return mBytesUsed;
316}
317
318void 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
389void 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
400void UidMap::OnConfigUpdated(const ConfigKey& key) {
401    mLastUpdatePerConfigKey[key] = -1;
402}
403
404void UidMap::OnConfigRemoved(const ConfigKey& key) {
405    mLastUpdatePerConfigKey.erase(key);
406}
407
408set<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.
423const 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