blob: 91279661b61f5d83dc09bacb6551e211a1b8994e [file] [log] [blame]
David Chende701692017-10-05 13:16:02 -07001/*
yro0feae942017-11-15 14:38:48 -08002 * Copyright (C) 2017 The Android Open Source Project
David Chende701692017-10-05 13:16:02 -07003 *
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 */
David Chenc136f452017-11-27 11:52:26 -080016#define DEBUG true // STOPSHIP if true
Joe Onorato9fc9edf2017-10-15 20:08:52 -070017#include "Log.h"
18
David Chenc136f452017-11-27 11:52:26 -080019#include "guardrail/StatsdStats.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070020#include "packages/UidMap.h"
21
David Chenc136f452017-11-27 11:52:26 -080022#include <android/os/IStatsCompanionService.h>
23#include <binder/IServiceManager.h>
David Chende701692017-10-05 13:16:02 -070024#include <utils/Errors.h>
25
Dianne Hackborn3accca02013-09-20 09:32:11 -070026#include <inttypes.h>
27
David Chende701692017-10-05 13:16:02 -070028using namespace android;
29
30namespace android {
31namespace os {
32namespace statsd {
33
Yangster9df9a7f2017-12-18 13:33:05 -080034UidMap::UidMap() : mBytesUsed(0) {}
35
36UidMap::~UidMap() {}
David Chenc136f452017-11-27 11:52:26 -080037
David Chende701692017-10-05 13:16:02 -070038bool UidMap::hasApp(int uid, const string& packageName) const {
39 lock_guard<mutex> lock(mMutex);
40
41 auto range = mMap.equal_range(uid);
42 for (auto it = range.first; it != range.second; ++it) {
43 if (it->second.packageName == packageName) {
44 return true;
45 }
46 }
47 return false;
48}
49
Yangster9df9a7f2017-12-18 13:33:05 -080050string UidMap::normalizeAppName(const string& appName) const {
51 string normalizedName = appName;
52 std::transform(normalizedName.begin(), normalizedName.end(), normalizedName.begin(), ::tolower);
53 return normalizedName;
54}
55
56std::set<string> UidMap::getAppNamesFromUid(const int32_t& uid, bool returnNormalized) const {
57 lock_guard<mutex> lock(mMutex);
58 return getAppNamesFromUidLocked(uid,returnNormalized);
59}
60
61std::set<string> UidMap::getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const {
62 std::set<string> names;
63 auto range = mMap.equal_range(uid);
64 for (auto it = range.first; it != range.second; ++it) {
65 names.insert(returnNormalized ?
66 normalizeAppName(it->second.packageName) : it->second.packageName);
67 }
68 return names;
69}
70
Dianne Hackborn3accca02013-09-20 09:32:11 -070071int64_t UidMap::getAppVersion(int uid, const string& packageName) const {
David Chende701692017-10-05 13:16:02 -070072 lock_guard<mutex> lock(mMutex);
73
74 auto range = mMap.equal_range(uid);
75 for (auto it = range.first; it != range.second; ++it) {
76 if (it->second.packageName == packageName) {
77 return it->second.versionCode;
78 }
79 }
80 return 0;
81}
82
Dianne Hackborn3accca02013-09-20 09:32:11 -070083void UidMap::updateMap(const vector<int32_t>& uid, const vector<int64_t>& versionCode,
Joe Onorato9fc9edf2017-10-15 20:08:52 -070084 const vector<String16>& packageName) {
yrob0378b02017-11-09 20:36:25 -080085 updateMap(time(nullptr) * NS_PER_SEC, uid, versionCode, packageName);
David Chend6896892017-10-25 11:49:03 -070086}
87
88void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
Dianne Hackborn3accca02013-09-20 09:32:11 -070089 const vector<int64_t>& versionCode, const vector<String16>& packageName) {
Yao Chend10f7b12017-12-18 12:53:50 -080090 vector<wp<PackageInfoListener>> broadcastList;
91 {
92 lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
David Chende701692017-10-05 13:16:02 -070093
Yao Chend10f7b12017-12-18 12:53:50 -080094 mMap.clear();
95 for (size_t j = 0; j < uid.size(); j++) {
96 mMap.insert(make_pair(
97 uid[j], AppData(string(String8(packageName[j]).string()), versionCode[j])));
98 }
David Chende701692017-10-05 13:16:02 -070099
Yao Chend10f7b12017-12-18 12:53:50 -0800100 auto snapshot = mOutput.add_snapshots();
101 snapshot->set_timestamp_nanos(timestamp);
102 for (size_t j = 0; j < uid.size(); j++) {
103 auto t = snapshot->add_package_info();
104 t->set_name(string(String8(packageName[j]).string()));
105 t->set_version(int(versionCode[j]));
106 t->set_uid(uid[j]);
107 }
108 mBytesUsed += snapshot->ByteSize();
David Chenc0f6f632018-01-18 16:02:42 -0800109 ensureBytesUsedBelowLimit();
Yao Chend10f7b12017-12-18 12:53:50 -0800110 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
111 StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
Yao Chend10f7b12017-12-18 12:53:50 -0800112 getListenerListCopyLocked(&broadcastList);
David Chende701692017-10-05 13:16:02 -0700113 }
Yao Chend10f7b12017-12-18 12:53:50 -0800114 // To avoid invoking callback while holding the internal lock. we get a copy of the listener
115 // list and invoke the callback. It's still possible that after we copy the list, a
116 // listener removes itself before we call it. It's then the listener's job to handle it (expect
117 // the callback to be called after listener is removed, and the listener should properly
118 // ignore it).
119 for (auto weakPtr : broadcastList) {
120 auto strongPtr = weakPtr.promote();
121 if (strongPtr != NULL) {
122 strongPtr->onUidMapReceived();
123 }
124 }
David Chende701692017-10-05 13:16:02 -0700125}
126
Dianne Hackborn3accca02013-09-20 09:32:11 -0700127void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int64_t& versionCode) {
yrob0378b02017-11-09 20:36:25 -0800128 updateApp(time(nullptr) * NS_PER_SEC, app_16, uid, versionCode);
David Chend6896892017-10-25 11:49:03 -0700129}
130
131void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
Dianne Hackborn3accca02013-09-20 09:32:11 -0700132 const int64_t& versionCode) {
Yao Chend10f7b12017-12-18 12:53:50 -0800133 vector<wp<PackageInfoListener>> broadcastList;
Yangster9df9a7f2017-12-18 13:33:05 -0800134 string appName = string(String8(app_16).string());
Yao Chend10f7b12017-12-18 12:53:50 -0800135 {
136 lock_guard<mutex> lock(mMutex);
David Chende701692017-10-05 13:16:02 -0700137
Yao Chend10f7b12017-12-18 12:53:50 -0800138 auto log = mOutput.add_changes();
139 log->set_deletion(false);
140 log->set_timestamp_nanos(timestamp);
141 log->set_app(appName);
142 log->set_uid(uid);
143 log->set_version(versionCode);
144 mBytesUsed += log->ByteSize();
David Chenc0f6f632018-01-18 16:02:42 -0800145 ensureBytesUsedBelowLimit();
Yao Chend10f7b12017-12-18 12:53:50 -0800146 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
147 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
Yao Chend10f7b12017-12-18 12:53:50 -0800148
149 auto range = mMap.equal_range(int(uid));
150 bool found = false;
151 for (auto it = range.first; it != range.second; ++it) {
152 // If we find the exact same app name and uid, update the app version directly.
153 if (it->second.packageName == appName) {
154 it->second.versionCode = versionCode;
155 found = true;
156 break;
157 }
158 }
159 if (!found) {
160 // Otherwise, we need to add an app at this uid.
161 mMap.insert(make_pair(uid, AppData(appName, versionCode)));
162 }
163 getListenerListCopyLocked(&broadcastList);
David Chende701692017-10-05 13:16:02 -0700164 }
165
Yao Chend10f7b12017-12-18 12:53:50 -0800166 for (auto weakPtr : broadcastList) {
167 auto strongPtr = weakPtr.promote();
168 if (strongPtr != NULL) {
169 strongPtr->notifyAppUpgrade(appName, uid, versionCode);
David Chende701692017-10-05 13:16:02 -0700170 }
David Chende701692017-10-05 13:16:02 -0700171 }
David Chende701692017-10-05 13:16:02 -0700172}
173
David Chenc136f452017-11-27 11:52:26 -0800174void UidMap::ensureBytesUsedBelowLimit() {
175 size_t limit;
176 if (maxBytesOverride <= 0) {
177 limit = StatsdStats::kMaxBytesUsedUidMap;
178 } else {
179 limit = maxBytesOverride;
180 }
181 while (mBytesUsed > limit) {
182 VLOG("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
183 if (mOutput.snapshots_size() > 0) {
184 auto snapshots = mOutput.mutable_snapshots();
185 snapshots->erase(snapshots->begin()); // Remove first snapshot.
186 StatsdStats::getInstance().noteUidMapDropped(1, 0);
187 } else if (mOutput.changes_size() > 0) {
188 auto changes = mOutput.mutable_changes();
189 changes->DeleteSubrange(0, 1);
190 StatsdStats::getInstance().noteUidMapDropped(0, 1);
191 }
192 mBytesUsed = mOutput.ByteSize();
193 }
194}
195
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700196void UidMap::removeApp(const String16& app_16, const int32_t& uid) {
yrob0378b02017-11-09 20:36:25 -0800197 removeApp(time(nullptr) * NS_PER_SEC, app_16, uid);
David Chend6896892017-10-25 11:49:03 -0700198}
Yangster9df9a7f2017-12-18 13:33:05 -0800199
Yao Chend10f7b12017-12-18 12:53:50 -0800200void UidMap::getListenerListCopyLocked(vector<wp<PackageInfoListener>>* output) {
201 for (auto weakIt = mSubscribers.begin(); weakIt != mSubscribers.end();) {
202 auto strongPtr = weakIt->promote();
203 if (strongPtr != NULL) {
204 output->push_back(*weakIt);
205 weakIt++;
206 } else {
207 weakIt = mSubscribers.erase(weakIt);
208 VLOG("The UidMap listener is gone, remove it now");
David Chende701692017-10-05 13:16:02 -0700209 }
210 }
David Chende701692017-10-05 13:16:02 -0700211}
212
Yao Chend10f7b12017-12-18 12:53:50 -0800213void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid) {
214 vector<wp<PackageInfoListener>> broadcastList;
215 string app = string(String8(app_16).string());
216 {
217 lock_guard<mutex> lock(mMutex);
218
219 auto log = mOutput.add_changes();
220 log->set_deletion(true);
221 log->set_timestamp_nanos(timestamp);
222 log->set_app(app);
223 log->set_uid(uid);
224 mBytesUsed += log->ByteSize();
David Chenc0f6f632018-01-18 16:02:42 -0800225 ensureBytesUsedBelowLimit();
Yao Chend10f7b12017-12-18 12:53:50 -0800226 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
227 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
Yao Chend10f7b12017-12-18 12:53:50 -0800228
229 auto range = mMap.equal_range(int(uid));
230 for (auto it = range.first; it != range.second; ++it) {
231 if (it->second.packageName == app) {
232 mMap.erase(it);
233 break;
234 }
235 }
236 getListenerListCopyLocked(&broadcastList);
237 }
238
239 for (auto weakPtr : broadcastList) {
240 auto strongPtr = weakPtr.promote();
241 if (strongPtr != NULL) {
242 strongPtr->notifyAppRemoved(app, uid);
243 }
244 }
245}
246
247void UidMap::addListener(wp<PackageInfoListener> producer) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700248 lock_guard<mutex> lock(mMutex); // Lock for updates
David Chende701692017-10-05 13:16:02 -0700249 mSubscribers.insert(producer);
250}
251
Yao Chend10f7b12017-12-18 12:53:50 -0800252void UidMap::removeListener(wp<PackageInfoListener> producer) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700253 lock_guard<mutex> lock(mMutex); // Lock for updates
David Chende701692017-10-05 13:16:02 -0700254 mSubscribers.erase(producer);
255}
256
David Chen21582962017-11-01 17:32:46 -0700257void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) {
258 lock_guard<mutex> lock(mIsolatedMutex);
259
260 mIsolatedUidMap[isolatedUid] = parentUid;
261}
262
263void UidMap::removeIsolatedUid(int isolatedUid, int parentUid) {
264 lock_guard<mutex> lock(mIsolatedMutex);
265
266 auto it = mIsolatedUidMap.find(isolatedUid);
267 if (it != mIsolatedUidMap.end()) {
268 mIsolatedUidMap.erase(it);
269 }
270}
271
Yangster-macd40053e2018-01-09 16:29:22 -0800272int UidMap::getHostUidOrSelf(int uid) const {
David Chen21582962017-11-01 17:32:46 -0700273 lock_guard<mutex> lock(mIsolatedMutex);
274
275 auto it = mIsolatedUidMap.find(uid);
276 if (it != mIsolatedUidMap.end()) {
277 return it->second;
278 }
279 return uid;
280}
281
David Chend6896892017-10-25 11:49:03 -0700282void UidMap::clearOutput() {
David Chende701692017-10-05 13:16:02 -0700283 mOutput.Clear();
David Chenc136f452017-11-27 11:52:26 -0800284 // Also update the guardrail trackers.
285 StatsdStats::getInstance().setUidMapChanges(0);
286 StatsdStats::getInstance().setUidMapSnapshots(1);
David Chencfc311d2018-01-23 17:55:54 -0800287 mBytesUsed = 0;
David Chenc136f452017-11-27 11:52:26 -0800288 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
David Chend6896892017-10-25 11:49:03 -0700289}
David Chende701692017-10-05 13:16:02 -0700290
David Chend6896892017-10-25 11:49:03 -0700291int64_t UidMap::getMinimumTimestampNs() {
292 int64_t m = 0;
293 for (auto it : mLastUpdatePerConfigKey) {
294 if (m == 0) {
295 m = it.second;
296 } else if (it.second < m) {
297 m = it.second;
298 }
299 }
300 return m;
301}
302
Yao Chend10f7b12017-12-18 12:53:50 -0800303size_t UidMap::getBytesUsed() const {
David Chenc136f452017-11-27 11:52:26 -0800304 return mBytesUsed;
305}
306
David Chend6896892017-10-25 11:49:03 -0700307UidMapping UidMap::getOutput(const ConfigKey& key) {
yrob0378b02017-11-09 20:36:25 -0800308 return getOutput(time(nullptr) * NS_PER_SEC, key);
David Chend6896892017-10-25 11:49:03 -0700309}
310
311UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) {
312 lock_guard<mutex> lock(mMutex); // Lock for updates
313
314 auto ret = UidMapping(mOutput); // Copy that will be returned.
315 int64_t prevMin = getMinimumTimestampNs();
316 mLastUpdatePerConfigKey[key] = timestamp;
317 int64_t newMin = getMinimumTimestampNs();
318
319 if (newMin > prevMin) {
320 int64_t cutoff_nanos = newMin;
321 auto snapshots = mOutput.mutable_snapshots();
322 auto it_snapshots = snapshots->cbegin();
323 while (it_snapshots != snapshots->cend()) {
324 if (it_snapshots->timestamp_nanos() < cutoff_nanos) {
325 // it_snapshots now points to the following element.
326 it_snapshots = snapshots->erase(it_snapshots);
327 } else {
328 ++it_snapshots;
329 }
330 }
331 auto deltas = mOutput.mutable_changes();
332 auto it_deltas = deltas->cbegin();
333 while (it_deltas != deltas->cend()) {
334 if (it_deltas->timestamp_nanos() < cutoff_nanos) {
335 // it_deltas now points to the following element.
336 it_deltas = deltas->erase(it_deltas);
337 } else {
338 ++it_deltas;
339 }
340 }
David Chencfc311d2018-01-23 17:55:54 -0800341
342 if (mOutput.snapshots_size() == 0) {
343 // Produce another snapshot. This results in extra data being uploaded but helps
344 // ensure we can re-construct the UID->app name, versionCode mapping in server.
345 auto snapshot = mOutput.add_snapshots();
346 snapshot->set_timestamp_nanos(timestamp);
347 for (auto it : mMap) {
348 auto t = snapshot->add_package_info();
349 t->set_name(it.second.packageName);
350 t->set_version(it.second.versionCode);
351 t->set_uid(it.first);
352 }
353 }
David Chend6896892017-10-25 11:49:03 -0700354 }
David Chenc136f452017-11-27 11:52:26 -0800355 mBytesUsed = mOutput.ByteSize(); // Compute actual size after potential deletions.
356 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
357 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
358 StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
David Chende701692017-10-05 13:16:02 -0700359 return ret;
360}
361
Yao Chend10f7b12017-12-18 12:53:50 -0800362void UidMap::printUidMap(FILE* out) const {
David Chende701692017-10-05 13:16:02 -0700363 lock_guard<mutex> lock(mMutex);
364
365 for (auto it : mMap) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700366 fprintf(out, "%s, v%" PRId64 " (%i)\n", it.second.packageName.c_str(),
367 it.second.versionCode, it.first);
David Chende701692017-10-05 13:16:02 -0700368 }
369}
370
David Chend6896892017-10-25 11:49:03 -0700371void UidMap::OnConfigUpdated(const ConfigKey& key) {
372 mLastUpdatePerConfigKey[key] = -1;
David Chenc136f452017-11-27 11:52:26 -0800373
374 // Ensure there is at least one snapshot available since this configuration also needs to know
375 // what all the uid's represent.
376 if (mOutput.snapshots_size() == 0) {
377 sp<IStatsCompanionService> statsCompanion = nullptr;
378 // Get statscompanion service from service manager
379 const sp<IServiceManager> sm(defaultServiceManager());
380 if (sm != nullptr) {
381 const String16 name("statscompanion");
382 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
383 if (statsCompanion == nullptr) {
384 ALOGW("statscompanion service unavailable!");
385 return;
386 }
387 statsCompanion->triggerUidSnapshot();
388 }
389 }
David Chend6896892017-10-25 11:49:03 -0700390}
391
392void UidMap::OnConfigRemoved(const ConfigKey& key) {
393 mLastUpdatePerConfigKey.erase(key);
394}
395
Yao Chend10f7b12017-12-18 12:53:50 -0800396set<int32_t> UidMap::getAppUid(const string& package) const {
397 lock_guard<mutex> lock(mMutex);
398
399 set<int32_t> results;
400 for (const auto& pair : mMap) {
401 if (pair.second.packageName == package) {
402 results.insert(pair.first);
403 }
404 }
405 return results;
406}
407
Yao Chen147ce602017-12-22 14:35:34 -0800408// Note not all the following AIDs are used as uids. Some are used only for gids.
409// It's ok to leave them in the map, but we won't ever see them in the log's uid field.
410// App's uid starts from 10000, and will not overlap with the following AIDs.
411const std::map<string, uint32_t> UidMap::sAidToUidMapping = {{"AID_ROOT", 0},
412 {"AID_SYSTEM", 1000},
413 {"AID_RADIO", 1001},
414 {"AID_BLUETOOTH", 1002},
415 {"AID_GRAPHICS", 1003},
416 {"AID_INPUT", 1004},
417 {"AID_AUDIO", 1005},
418 {"AID_CAMERA", 1006},
419 {"AID_LOG", 1007},
420 {"AID_COMPASS", 1008},
421 {"AID_MOUNT", 1009},
422 {"AID_WIFI", 1010},
423 {"AID_ADB", 1011},
424 {"AID_INSTALL", 1012},
425 {"AID_MEDIA", 1013},
426 {"AID_DHCP", 1014},
427 {"AID_SDCARD_RW", 1015},
428 {"AID_VPN", 1016},
429 {"AID_KEYSTORE", 1017},
430 {"AID_USB", 1018},
431 {"AID_DRM", 1019},
432 {"AID_MDNSR", 1020},
433 {"AID_GPS", 1021},
434 // {"AID_UNUSED1", 1022},
435 {"AID_MEDIA_RW", 1023},
436 {"AID_MTP", 1024},
437 // {"AID_UNUSED2", 1025},
438 {"AID_DRMRPC", 1026},
439 {"AID_NFC", 1027},
440 {"AID_SDCARD_R", 1028},
441 {"AID_CLAT", 1029},
442 {"AID_LOOP_RADIO", 1030},
443 {"AID_MEDIA_DRM", 1031},
444 {"AID_PACKAGE_INFO", 1032},
445 {"AID_SDCARD_PICS", 1033},
446 {"AID_SDCARD_AV", 1034},
447 {"AID_SDCARD_ALL", 1035},
448 {"AID_LOGD", 1036},
449 {"AID_SHARED_RELRO", 1037},
450 {"AID_DBUS", 1038},
451 {"AID_TLSDATE", 1039},
452 {"AID_MEDIA_EX", 1040},
453 {"AID_AUDIOSERVER", 1041},
454 {"AID_METRICS_COLL", 1042},
455 {"AID_METRICSD", 1043},
456 {"AID_WEBSERV", 1044},
457 {"AID_DEBUGGERD", 1045},
458 {"AID_MEDIA_CODEC", 1046},
459 {"AID_CAMERASERVER", 1047},
460 {"AID_FIREWALL", 1048},
461 {"AID_TRUNKS", 1049},
462 {"AID_NVRAM", 1050},
463 {"AID_DNS", 1051},
464 {"AID_DNS_TETHER", 1052},
465 {"AID_WEBVIEW_ZYGOTE", 1053},
466 {"AID_VEHICLE_NETWORK", 1054},
467 {"AID_MEDIA_AUDIO", 1055},
468 {"AID_MEDIA_VIDEO", 1056},
469 {"AID_MEDIA_IMAGE", 1057},
470 {"AID_TOMBSTONED", 1058},
471 {"AID_MEDIA_OBB", 1059},
472 {"AID_ESE", 1060},
473 {"AID_OTA_UPDATE", 1061},
474 {"AID_AUTOMOTIVE_EVS", 1062},
475 {"AID_LOWPAN", 1063},
476 {"AID_HSM", 1064},
Yao Chen29f79b52018-01-17 10:56:48 -0800477 {"AID_RESERVED_DISK", 1065},
478 {"AID_STATSD", 1066},
479 {"AID_INCIDENTD", 1067},
Yao Chen147ce602017-12-22 14:35:34 -0800480 {"AID_SHELL", 2000},
481 {"AID_CACHE", 2001},
482 {"AID_DIAG", 2002}};
483
David Chende701692017-10-05 13:16:02 -0700484} // namespace statsd
485} // namespace os
Yao Chen29f79b52018-01-17 10:56:48 -0800486} // namespace android