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
UidMap()64 UidMap::UidMap() : mBytesUsed(0) {}
65
~UidMap()66 UidMap::~UidMap() {}
67
hasApp(int uid,const string & packageName) const68 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
normalizeAppName(const string & appName) const75 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
getAppNamesFromUid(const int32_t & uid,bool returnNormalized) const81 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
getAppNamesFromUidLocked(const int32_t & uid,bool returnNormalized) const86 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
getAppVersion(int uid,const string & packageName) const96 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
updateMap(const int64_t & timestamp,const vector<int32_t> & uid,const vector<int64_t> & versionCode,const vector<String16> & packageName)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
updateApp(const int64_t & timestamp,const String16 & app_16,const int32_t & uid,const int64_t & versionCode)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
ensureBytesUsedBelowLimit()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
getListenerListCopyLocked(vector<wp<PackageInfoListener>> * output)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
removeApp(const int64_t & timestamp,const String16 & app_16,const int32_t & uid)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
addListener(wp<PackageInfoListener> producer)259 void UidMap::addListener(wp<PackageInfoListener> producer) {
260 lock_guard<mutex> lock(mMutex); // Lock for updates
261 mSubscribers.insert(producer);
262 }
263
removeListener(wp<PackageInfoListener> producer)264 void UidMap::removeListener(wp<PackageInfoListener> producer) {
265 lock_guard<mutex> lock(mMutex); // Lock for updates
266 mSubscribers.erase(producer);
267 }
268
assignIsolatedUid(int isolatedUid,int parentUid)269 void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) {
270 lock_guard<mutex> lock(mIsolatedMutex);
271
272 mIsolatedUidMap[isolatedUid] = parentUid;
273 }
274
removeIsolatedUid(int isolatedUid,int parentUid)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
getHostUidOrSelf(int uid) const284 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
clearOutput()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
getMinimumTimestampNs()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
getBytesUsed() const314 size_t UidMap::getBytesUsed() const {
315 return mBytesUsed;
316 }
317
appendUidMap(const int64_t & timestamp,const ConfigKey & key,std::set<string> * str_set,ProtoOutputStream * proto)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
printUidMap(FILE * out) const389 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
OnConfigUpdated(const ConfigKey & key)400 void UidMap::OnConfigUpdated(const ConfigKey& key) {
401 mLastUpdatePerConfigKey[key] = -1;
402 }
403
OnConfigRemoved(const ConfigKey & key)404 void UidMap::OnConfigRemoved(const ConfigKey& key) {
405 mLastUpdatePerConfigKey.erase(key);
406 }
407
getAppUid(const string & package) const408 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