blob: 6e7a613b05a3bd65402167b012c3b53a20a70ac3 [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
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
David Chenc136f45a2017-11-27 11:52:26 -080034UidMap::UidMap() : mBytesUsed(0) {
35}
36UidMap::~UidMap() {
37}
38
David Chende701692017-10-05 13:16:02 -070039bool UidMap::hasApp(int uid, const string& packageName) const {
40 lock_guard<mutex> lock(mMutex);
41
42 auto range = mMap.equal_range(uid);
43 for (auto it = range.first; it != range.second; ++it) {
44 if (it->second.packageName == packageName) {
45 return true;
46 }
47 }
48 return false;
49}
50
Dianne Hackborn3accca02013-09-20 09:32:11 -070051int64_t UidMap::getAppVersion(int uid, const string& packageName) const {
David Chende701692017-10-05 13:16:02 -070052 lock_guard<mutex> lock(mMutex);
53
54 auto range = mMap.equal_range(uid);
55 for (auto it = range.first; it != range.second; ++it) {
56 if (it->second.packageName == packageName) {
57 return it->second.versionCode;
58 }
59 }
60 return 0;
61}
62
Dianne Hackborn3accca02013-09-20 09:32:11 -070063void UidMap::updateMap(const vector<int32_t>& uid, const vector<int64_t>& versionCode,
Joe Onorato9fc9edf2017-10-15 20:08:52 -070064 const vector<String16>& packageName) {
yrob0378b02017-11-09 20:36:25 -080065 updateMap(time(nullptr) * NS_PER_SEC, uid, versionCode, packageName);
David Chend6896892017-10-25 11:49:03 -070066}
67
68void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
Dianne Hackborn3accca02013-09-20 09:32:11 -070069 const vector<int64_t>& versionCode, const vector<String16>& packageName) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -070070 lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
David Chende701692017-10-05 13:16:02 -070071
72 mMap.clear();
David Chend6896892017-10-25 11:49:03 -070073 for (size_t j = 0; j < uid.size(); j++) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -070074 mMap.insert(make_pair(uid[j],
75 AppData(string(String8(packageName[j]).string()), versionCode[j])));
David Chende701692017-10-05 13:16:02 -070076 }
77
David Chend6896892017-10-25 11:49:03 -070078 auto snapshot = mOutput.add_snapshots();
79 snapshot->set_timestamp_nanos(timestamp);
80 for (size_t j = 0; j < uid.size(); j++) {
81 auto t = snapshot->add_package_info();
82 t->set_name(string(String8(packageName[j]).string()));
83 t->set_version(int(versionCode[j]));
84 t->set_uid(uid[j]);
David Chende701692017-10-05 13:16:02 -070085 }
David Chenc136f45a2017-11-27 11:52:26 -080086 mBytesUsed += snapshot->ByteSize();
87 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
88 StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
89 ensureBytesUsedBelowLimit();
David Chende701692017-10-05 13:16:02 -070090}
91
Dianne Hackborn3accca02013-09-20 09:32:11 -070092void UidMap::updateApp(const String16& app_16, const int32_t& uid, const int64_t& versionCode) {
yrob0378b02017-11-09 20:36:25 -080093 updateApp(time(nullptr) * NS_PER_SEC, app_16, uid, versionCode);
David Chend6896892017-10-25 11:49:03 -070094}
95
96void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
Dianne Hackborn3accca02013-09-20 09:32:11 -070097 const int64_t& versionCode) {
David Chende701692017-10-05 13:16:02 -070098 lock_guard<mutex> lock(mMutex);
99
100 string app = string(String8(app_16).string());
101
102 // Notify any interested producers that this app has updated
103 for (auto it : mSubscribers) {
104 it->notifyAppUpgrade(app, uid, versionCode);
105 }
106
107 auto log = mOutput.add_changes();
108 log->set_deletion(false);
David Chend6896892017-10-25 11:49:03 -0700109 log->set_timestamp_nanos(timestamp);
David Chende701692017-10-05 13:16:02 -0700110 log->set_app(app);
111 log->set_uid(uid);
112 log->set_version(versionCode);
David Chenc136f45a2017-11-27 11:52:26 -0800113 mBytesUsed += log->ByteSize();
114 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
115 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
116 ensureBytesUsedBelowLimit();
David Chende701692017-10-05 13:16:02 -0700117
118 auto range = mMap.equal_range(int(uid));
119 for (auto it = range.first; it != range.second; ++it) {
120 if (it->second.packageName == app) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700121 it->second.versionCode = versionCode;
David Chende701692017-10-05 13:16:02 -0700122 return;
123 }
David Chenc136f45a2017-11-27 11:52:26 -0800124 VLOG("updateApp failed to find the app %s with uid %i to update", app.c_str(), uid);
David Chende701692017-10-05 13:16:02 -0700125 return;
126 }
127
128 // Otherwise, we need to add an app at this uid.
Dianne Hackborn3accca02013-09-20 09:32:11 -0700129 mMap.insert(make_pair(uid, AppData(app, versionCode)));
David Chende701692017-10-05 13:16:02 -0700130}
131
David Chenc136f45a2017-11-27 11:52:26 -0800132void UidMap::ensureBytesUsedBelowLimit() {
133 size_t limit;
134 if (maxBytesOverride <= 0) {
135 limit = StatsdStats::kMaxBytesUsedUidMap;
136 } else {
137 limit = maxBytesOverride;
138 }
139 while (mBytesUsed > limit) {
140 VLOG("Bytes used %zu is above limit %zu, need to delete something", mBytesUsed, limit);
141 if (mOutput.snapshots_size() > 0) {
142 auto snapshots = mOutput.mutable_snapshots();
143 snapshots->erase(snapshots->begin()); // Remove first snapshot.
144 StatsdStats::getInstance().noteUidMapDropped(1, 0);
145 } else if (mOutput.changes_size() > 0) {
146 auto changes = mOutput.mutable_changes();
147 changes->DeleteSubrange(0, 1);
148 StatsdStats::getInstance().noteUidMapDropped(0, 1);
149 }
150 mBytesUsed = mOutput.ByteSize();
151 }
152}
153
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700154void UidMap::removeApp(const String16& app_16, const int32_t& uid) {
yrob0378b02017-11-09 20:36:25 -0800155 removeApp(time(nullptr) * NS_PER_SEC, app_16, uid);
David Chend6896892017-10-25 11:49:03 -0700156}
157void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid) {
David Chende701692017-10-05 13:16:02 -0700158 lock_guard<mutex> lock(mMutex);
159
160 string app = string(String8(app_16).string());
161
David Chend6896892017-10-25 11:49:03 -0700162 for (auto it : mSubscribers) {
163 it->notifyAppRemoved(app, uid);
164 }
165
David Chende701692017-10-05 13:16:02 -0700166 auto log = mOutput.add_changes();
167 log->set_deletion(true);
David Chend6896892017-10-25 11:49:03 -0700168 log->set_timestamp_nanos(timestamp);
David Chende701692017-10-05 13:16:02 -0700169 log->set_app(app);
170 log->set_uid(uid);
David Chenc136f45a2017-11-27 11:52:26 -0800171 mBytesUsed += log->ByteSize();
172 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
173 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
174 ensureBytesUsedBelowLimit();
David Chende701692017-10-05 13:16:02 -0700175
176 auto range = mMap.equal_range(int(uid));
177 for (auto it = range.first; it != range.second; ++it) {
178 if (it->second.packageName == app) {
179 mMap.erase(it);
180 return;
181 }
182 }
David Chenc136f45a2017-11-27 11:52:26 -0800183 VLOG("removeApp failed to find the app %s with uid %i to remove", app.c_str(), uid);
David Chende701692017-10-05 13:16:02 -0700184 return;
185}
186
187void UidMap::addListener(sp<PackageInfoListener> producer) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700188 lock_guard<mutex> lock(mMutex); // Lock for updates
David Chende701692017-10-05 13:16:02 -0700189 mSubscribers.insert(producer);
190}
191
192void UidMap::removeListener(sp<PackageInfoListener> producer) {
Joe Onorato9fc9edf2017-10-15 20:08:52 -0700193 lock_guard<mutex> lock(mMutex); // Lock for updates
David Chende701692017-10-05 13:16:02 -0700194 mSubscribers.erase(producer);
195}
196
David Chen21582962017-11-01 17:32:46 -0700197void UidMap::assignIsolatedUid(int isolatedUid, int parentUid) {
198 lock_guard<mutex> lock(mIsolatedMutex);
199
200 mIsolatedUidMap[isolatedUid] = parentUid;
201}
202
203void UidMap::removeIsolatedUid(int isolatedUid, int parentUid) {
204 lock_guard<mutex> lock(mIsolatedMutex);
205
206 auto it = mIsolatedUidMap.find(isolatedUid);
207 if (it != mIsolatedUidMap.end()) {
208 mIsolatedUidMap.erase(it);
209 }
210}
211
212int UidMap::getParentUidOrSelf(int uid) {
213 lock_guard<mutex> lock(mIsolatedMutex);
214
215 auto it = mIsolatedUidMap.find(uid);
216 if (it != mIsolatedUidMap.end()) {
217 return it->second;
218 }
219 return uid;
220}
221
David Chend6896892017-10-25 11:49:03 -0700222void UidMap::clearOutput() {
David Chende701692017-10-05 13:16:02 -0700223 mOutput.Clear();
David Chende701692017-10-05 13:16:02 -0700224 // Re-initialize the initial state for the outputs. This results in extra data being uploaded
David Chend6896892017-10-25 11:49:03 -0700225 // but helps ensure we can re-construct the UID->app name, versionCode mapping in server.
226 auto snapshot = mOutput.add_snapshots();
David Chende701692017-10-05 13:16:02 -0700227 for (auto it : mMap) {
David Chend6896892017-10-25 11:49:03 -0700228 auto t = snapshot->add_package_info();
229 t->set_name(it.second.packageName);
David Chende701692017-10-05 13:16:02 -0700230 t->set_version(it.second.versionCode);
231 t->set_uid(it.first);
232 }
David Chenc136f45a2017-11-27 11:52:26 -0800233
234 // Also update the guardrail trackers.
235 StatsdStats::getInstance().setUidMapChanges(0);
236 StatsdStats::getInstance().setUidMapSnapshots(1);
237 mBytesUsed = snapshot->ByteSize();
238 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
David Chend6896892017-10-25 11:49:03 -0700239}
David Chende701692017-10-05 13:16:02 -0700240
David Chend6896892017-10-25 11:49:03 -0700241int64_t UidMap::getMinimumTimestampNs() {
242 int64_t m = 0;
243 for (auto it : mLastUpdatePerConfigKey) {
244 if (m == 0) {
245 m = it.second;
246 } else if (it.second < m) {
247 m = it.second;
248 }
249 }
250 return m;
251}
252
David Chenc136f45a2017-11-27 11:52:26 -0800253size_t UidMap::getBytesUsed() {
254 return mBytesUsed;
255}
256
David Chend6896892017-10-25 11:49:03 -0700257UidMapping UidMap::getOutput(const ConfigKey& key) {
yrob0378b02017-11-09 20:36:25 -0800258 return getOutput(time(nullptr) * NS_PER_SEC, key);
David Chend6896892017-10-25 11:49:03 -0700259}
260
261UidMapping UidMap::getOutput(const int64_t& timestamp, const ConfigKey& key) {
262 lock_guard<mutex> lock(mMutex); // Lock for updates
263
264 auto ret = UidMapping(mOutput); // Copy that will be returned.
265 int64_t prevMin = getMinimumTimestampNs();
266 mLastUpdatePerConfigKey[key] = timestamp;
267 int64_t newMin = getMinimumTimestampNs();
268
269 if (newMin > prevMin) {
270 int64_t cutoff_nanos = newMin;
271 auto snapshots = mOutput.mutable_snapshots();
272 auto it_snapshots = snapshots->cbegin();
273 while (it_snapshots != snapshots->cend()) {
274 if (it_snapshots->timestamp_nanos() < cutoff_nanos) {
275 // it_snapshots now points to the following element.
276 it_snapshots = snapshots->erase(it_snapshots);
277 } else {
278 ++it_snapshots;
279 }
280 }
281 auto deltas = mOutput.mutable_changes();
282 auto it_deltas = deltas->cbegin();
283 while (it_deltas != deltas->cend()) {
284 if (it_deltas->timestamp_nanos() < cutoff_nanos) {
285 // it_deltas now points to the following element.
286 it_deltas = deltas->erase(it_deltas);
287 } else {
288 ++it_deltas;
289 }
290 }
291 }
David Chenc136f45a2017-11-27 11:52:26 -0800292 mBytesUsed = mOutput.ByteSize(); // Compute actual size after potential deletions.
293 StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
294 StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
295 StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
David Chende701692017-10-05 13:16:02 -0700296 return ret;
297}
298
299void UidMap::printUidMap(FILE* out) {
300 lock_guard<mutex> lock(mMutex);
301
302 for (auto it : mMap) {
Dianne Hackborn3accca02013-09-20 09:32:11 -0700303 fprintf(out, "%s, v%" PRId64 " (%i)\n", it.second.packageName.c_str(),
304 it.second.versionCode, it.first);
David Chende701692017-10-05 13:16:02 -0700305 }
306}
307
David Chend6896892017-10-25 11:49:03 -0700308void UidMap::OnConfigUpdated(const ConfigKey& key) {
309 mLastUpdatePerConfigKey[key] = -1;
David Chenc136f45a2017-11-27 11:52:26 -0800310
311 // Ensure there is at least one snapshot available since this configuration also needs to know
312 // what all the uid's represent.
313 if (mOutput.snapshots_size() == 0) {
314 sp<IStatsCompanionService> statsCompanion = nullptr;
315 // Get statscompanion service from service manager
316 const sp<IServiceManager> sm(defaultServiceManager());
317 if (sm != nullptr) {
318 const String16 name("statscompanion");
319 statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name));
320 if (statsCompanion == nullptr) {
321 ALOGW("statscompanion service unavailable!");
322 return;
323 }
324 statsCompanion->triggerUidSnapshot();
325 }
326 }
David Chend6896892017-10-25 11:49:03 -0700327}
328
329void UidMap::OnConfigRemoved(const ConfigKey& key) {
330 mLastUpdatePerConfigKey.erase(key);
331}
332
David Chende701692017-10-05 13:16:02 -0700333} // namespace statsd
334} // namespace os
335} // namespace android