blob: db592e2c584150243830719d1eaad9df6902f1b1 [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 Chenc136f45a2017-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 Chenc136f45a2017-11-27 11:52:26 -080019#include "guardrail/StatsdStats.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070020#include "packages/UidMap.h"
21
David Chenc136f45a2017-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
26using namespace android;
27
28namespace android {
29namespace os {
30namespace statsd {
31
David Chenc136f45a2017-11-27 11:52:26 -080032UidMap::UidMap() : mBytesUsed(0) {
33}
34UidMap::~UidMap() {
35}
36
David Chende701692017-10-05 13:16:02 -070037bool UidMap::hasApp(int uid, const string& packageName) const {
38 lock_guard<mutex> lock(mMutex);
39
40 auto range = mMap.equal_range(uid);
41 for (auto it = range.first; it != range.second; ++it) {
42 if (it->second.packageName == packageName) {
43 return true;
44 }
45 }
46 return false;
47}
48
49int UidMap::getAppVersion(int uid, const string& packageName) const {
50 lock_guard<mutex> lock(mMutex);
51
52 auto range = mMap.equal_range(uid);
53 for (auto it = range.first; it != range.second; ++it) {
54 if (it->second.packageName == packageName) {
55 return it->second.versionCode;
56 }
57 }
58 return 0;
59}
60
Joe Onorato9fc9edf2017-10-15 20:08:52 -070061void UidMap::updateMap(const vector<int32_t>& uid, const vector<int32_t>& versionCode,
62 const vector<String16>& packageName) {
yrob0378b02017-11-09 20:36:25 -080063 updateMap(time(nullptr) * NS_PER_SEC, uid, versionCode, packageName);
David Chend6896892017-10-25 11:49:03 -070064}
65
66void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
67 const vector<int32_t>& versionCode, const vector<String16>& packageName) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -070068 lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
David Chende701692017-10-05 13:16:02 -070069
70 mMap.clear();
David Chend6896892017-10-25 11:49:03 -070071 for (size_t j = 0; j < uid.size(); j++) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -070072 mMap.insert(make_pair(uid[j],
73 AppData(string(String8(packageName[j]).string()), versionCode[j])));
David Chende701692017-10-05 13:16:02 -070074 }
75
David Chend6896892017-10-25 11:49:03 -070076 auto snapshot = mOutput.add_snapshots();
77 snapshot->set_timestamp_nanos(timestamp);
78 for (size_t j = 0; j < uid.size(); j++) {
79 auto t = snapshot->add_package_info();
80 t->set_name(string(String8(packageName[j]).string()));
81 t->set_version(int(versionCode[j]));
82 t->set_uid(uid[j]);
David Chende701692017-10-05 13:16:02 -070083 }
David Chenc136f45a2017-11-27 11:52:26 -080084 mBytesUsed += snapshot->ByteSize();
85 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
86 StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
87 ensureBytesUsedBelowLimit();
David Chende701692017-10-05 13:16:02 -070088}
89
Joe Onorato9fc9edf2017-10-15 20:08:52 -070090void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int32_t& versionCode) {
yrob0378b02017-11-09 20:36:25 -080091 updateApp(time(nullptr) * NS_PER_SEC, app_16, uid, versionCode);
David Chend6896892017-10-25 11:49:03 -070092}
93
94void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
95 const int32_t& versionCode) {
David Chende701692017-10-05 13:16:02 -070096 lock_guard<mutex> lock(mMutex);
97
98 string app = string(String8(app_16).string());
99
100 // Notify any interested producers that this app has updated
101 for (auto it : mSubscribers) {
102 it->notifyAppUpgrade(app, uid, versionCode);
103 }
104
105 auto log = mOutput.add_changes();
106 log->set_deletion(false);
David Chend6896892017-10-25 11:49:03 -0700107 log->set_timestamp_nanos(timestamp);
David Chende701692017-10-05 13:16:02 -0700108 log->set_app(app);
109 log->set_uid(uid);
110 log->set_version(versionCode);
David Chenc136f45a2017-11-27 11:52:26 -0800111 mBytesUsed += log->ByteSize();
112 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
113 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
114 ensureBytesUsedBelowLimit();
David Chende701692017-10-05 13:16:02 -0700115
116 auto range = mMap.equal_range(int(uid));
117 for (auto it = range.first; it != range.second; ++it) {
118 if (it->second.packageName == app) {
119 it->second.versionCode = int(versionCode);
120 return;
121 }
David Chenc136f45a2017-11-27 11:52:26 -0800122 VLOG("updateApp failed to find the app %s with uid %i to update", app.c_str(), uid);
David Chende701692017-10-05 13:16:02 -0700123 return;
124 }
125
126 // Otherwise, we need to add an app at this uid.
127 mMap.insert(make_pair(uid, AppData(app, int(versionCode))));
128}
129
David Chenc136f45a2017-11-27 11:52:26 -0800130void UidMap::ensureBytesUsedBelowLimit() {
131 size_t limit;
132 if (maxBytesOverride <= 0) {
133 limit = StatsdStats::kMaxBytesUsedUidMap;
134 } else {
135 limit = maxBytesOverride;
136 }
137 while (mBytesUsed > limit) {
138 VLOG("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
139 if (mOutput.snapshots_size() > 0) {
140 auto snapshots = mOutput.mutable_snapshots();
141 snapshots->erase(snapshots->begin()); // Remove first snapshot.
142 StatsdStats::getInstance().noteUidMapDropped(1, 0);
143 } else if (mOutput.changes_size() > 0) {
144 auto changes = mOutput.mutable_changes();
145 changes->DeleteSubrange(0, 1);
146 StatsdStats::getInstance().noteUidMapDropped(0, 1);
147 }
148 mBytesUsed = mOutput.ByteSize();
149 }
150}
151
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700152void UidMap::removeApp(const String16& app_16, const int32_t& uid) {
yrob0378b02017-11-09 20:36:25 -0800153 removeApp(time(nullptr) * NS_PER_SEC, app_16, uid);
David Chend6896892017-10-25 11:49:03 -0700154}
155void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid) {
David Chende701692017-10-05 13:16:02 -0700156 lock_guard<mutex> lock(mMutex);
157
158 string app = string(String8(app_16).string());
159
David Chend6896892017-10-25 11:49:03 -0700160 for (auto it : mSubscribers) {
161 it->notifyAppRemoved(app, uid);
162 }
163
David Chende701692017-10-05 13:16:02 -0700164 auto log = mOutput.add_changes();
165 log->set_deletion(true);
David Chend6896892017-10-25 11:49:03 -0700166 log->set_timestamp_nanos(timestamp);
David Chende701692017-10-05 13:16:02 -0700167 log->set_app(app);
168 log->set_uid(uid);
David Chenc136f45a2017-11-27 11:52:26 -0800169 mBytesUsed += log->ByteSize();
170 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
171 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
172 ensureBytesUsedBelowLimit();
David Chende701692017-10-05 13:16:02 -0700173
174 auto range = mMap.equal_range(int(uid));
175 for (auto it = range.first; it != range.second; ++it) {
176 if (it->second.packageName == app) {
177 mMap.erase(it);
178 return;
179 }
180 }
David Chenc136f45a2017-11-27 11:52:26 -0800181 VLOG("removeApp failed to find the app %s with uid %i to remove", app.c_str(), uid);
David Chende701692017-10-05 13:16:02 -0700182 return;
183}
184
185void UidMap::addListener(sp<PackageInfoListener> producer) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700186 lock_guard<mutex> lock(mMutex); // Lock for updates
David Chende701692017-10-05 13:16:02 -0700187 mSubscribers.insert(producer);
188}
189
190void UidMap::removeListener(sp<PackageInfoListener> producer) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700191 lock_guard<mutex> lock(mMutex); // Lock for updates
David Chende701692017-10-05 13:16:02 -0700192 mSubscribers.erase(producer);
193}
194
David Chen21582962017-11-01 17:32:46 -0700195void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) {
196 lock_guard<mutex> lock(mIsolatedMutex);
197
198 mIsolatedUidMap[isolatedUid] = parentUid;
199}
200
201void UidMap::removeIsolatedUid(int isolatedUid, int parentUid) {
202 lock_guard<mutex> lock(mIsolatedMutex);
203
204 auto it = mIsolatedUidMap.find(isolatedUid);
205 if (it != mIsolatedUidMap.end()) {
206 mIsolatedUidMap.erase(it);
207 }
208}
209
210int UidMap::getParentUidOrSelf(int uid) {
211 lock_guard<mutex> lock(mIsolatedMutex);
212
213 auto it = mIsolatedUidMap.find(uid);
214 if (it != mIsolatedUidMap.end()) {
215 return it->second;
216 }
217 return uid;
218}
219
David Chend6896892017-10-25 11:49:03 -0700220void UidMap::clearOutput() {
David Chende701692017-10-05 13:16:02 -0700221 mOutput.Clear();
David Chende701692017-10-05 13:16:02 -0700222 // Re-initialize the initial state for the outputs. This results in extra data being uploaded
David Chend6896892017-10-25 11:49:03 -0700223 // but helps ensure we can re-construct the UID->app name, versionCode mapping in server.
224 auto snapshot = mOutput.add_snapshots();
David Chende701692017-10-05 13:16:02 -0700225 for (auto it : mMap) {
David Chend6896892017-10-25 11:49:03 -0700226 auto t = snapshot->add_package_info();
227 t->set_name(it.second.packageName);
David Chende701692017-10-05 13:16:02 -0700228 t->set_version(it.second.versionCode);
229 t->set_uid(it.first);
230 }
David Chenc136f45a2017-11-27 11:52:26 -0800231
232 // Also update the guardrail trackers.
233 StatsdStats::getInstance().setUidMapChanges(0);
234 StatsdStats::getInstance().setUidMapSnapshots(1);
235 mBytesUsed = snapshot->ByteSize();
236 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
David Chend6896892017-10-25 11:49:03 -0700237}
David Chende701692017-10-05 13:16:02 -0700238
David Chend6896892017-10-25 11:49:03 -0700239int64_t UidMap::getMinimumTimestampNs() {
240 int64_t m = 0;
241 for (auto it : mLastUpdatePerConfigKey) {
242 if (m == 0) {
243 m = it.second;
244 } else if (it.second < m) {
245 m = it.second;
246 }
247 }
248 return m;
249}
250
David Chenc136f45a2017-11-27 11:52:26 -0800251size_t UidMap::getBytesUsed() {
252 return mBytesUsed;
253}
254
David Chend6896892017-10-25 11:49:03 -0700255UidMapping UidMap::getOutput(const ConfigKey& key) {
yrob0378b02017-11-09 20:36:25 -0800256 return getOutput(time(nullptr) * NS_PER_SEC, key);
David Chend6896892017-10-25 11:49:03 -0700257}
258
259UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) {
260 lock_guard<mutex> lock(mMutex); // Lock for updates
261
262 auto ret = UidMapping(mOutput); // Copy that will be returned.
263 int64_t prevMin = getMinimumTimestampNs();
264 mLastUpdatePerConfigKey[key] = timestamp;
265 int64_t newMin = getMinimumTimestampNs();
266
267 if (newMin > prevMin) {
268 int64_t cutoff_nanos = newMin;
269 auto snapshots = mOutput.mutable_snapshots();
270 auto it_snapshots = snapshots->cbegin();
271 while (it_snapshots != snapshots->cend()) {
272 if (it_snapshots->timestamp_nanos() < cutoff_nanos) {
273 // it_snapshots now points to the following element.
274 it_snapshots = snapshots->erase(it_snapshots);
275 } else {
276 ++it_snapshots;
277 }
278 }
279 auto deltas = mOutput.mutable_changes();
280 auto it_deltas = deltas->cbegin();
281 while (it_deltas != deltas->cend()) {
282 if (it_deltas->timestamp_nanos() < cutoff_nanos) {
283 // it_deltas now points to the following element.
284 it_deltas = deltas->erase(it_deltas);
285 } else {
286 ++it_deltas;
287 }
288 }
289 }
David Chenc136f45a2017-11-27 11:52:26 -0800290 mBytesUsed = mOutput.ByteSize(); // Compute actual size after potential deletions.
291 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
292 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
293 StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
David Chende701692017-10-05 13:16:02 -0700294 return ret;
295}
296
297void UidMap::printUidMap(FILE* out) {
298 lock_guard<mutex> lock(mMutex);
299
300 for (auto it : mMap) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700301 fprintf(out, "%s, v%d (%i)\n", it.second.packageName.c_str(), it.second.versionCode,
302 it.first);
David Chende701692017-10-05 13:16:02 -0700303 }
304}
305
David Chend6896892017-10-25 11:49:03 -0700306void UidMap::OnConfigUpdated(const ConfigKey& key) {
307 mLastUpdatePerConfigKey[key] = -1;
David Chenc136f45a2017-11-27 11:52:26 -0800308
309 // Ensure there is at least one snapshot available since this configuration also needs to know
310 // what all the uid's represent.
311 if (mOutput.snapshots_size() == 0) {
312 sp<IStatsCompanionService> statsCompanion = nullptr;
313 // Get statscompanion service from service manager
314 const sp<IServiceManager> sm(defaultServiceManager());
315 if (sm != nullptr) {
316 const String16 name("statscompanion");
317 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
318 if (statsCompanion == nullptr) {
319 ALOGW("statscompanion service unavailable!");
320 return;
321 }
322 statsCompanion->triggerUidSnapshot();
323 }
324 }
David Chend6896892017-10-25 11:49:03 -0700325}
326
327void UidMap::OnConfigRemoved(const ConfigKey& key) {
328 mLastUpdatePerConfigKey.erase(key);
329}
330
David Chende701692017-10-05 13:16:02 -0700331} // namespace statsd
332} // namespace os
333} // namespace android