blob: 755b7079ec34e2fc6efb6937b17f8cf60b0594c0 [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, Version 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
Yangster9df9a7f2017-12-18 13:33:05 -080017#pragma once
David Chende701692017-10-05 13:16:02 -070018
David Chend6896892017-10-25 11:49:03 -070019#include "config/ConfigKey.h"
20#include "config/ConfigListener.h"
Joe Onorato9fc9edf2017-10-15 20:08:52 -070021#include "packages/PackageInfoListener.h"
yro4beccbe2018-03-15 19:42:05 -070022#include "stats_util.h"
David Chende701692017-10-05 13:16:02 -070023
24#include <binder/IResultReceiver.h>
25#include <binder/IShellCallback.h>
David Chend6896892017-10-25 11:49:03 -070026#include <gtest/gtest_prod.h>
David Chende701692017-10-05 13:16:02 -070027#include <log/logprint.h>
David Chende701692017-10-05 13:16:02 -070028#include <stdio.h>
David Chende701692017-10-05 13:16:02 -070029#include <utils/RefBase.h>
David Chenf384b902018-03-14 18:36:45 -070030#include <list>
Joe Onorato9fc9edf2017-10-15 20:08:52 -070031#include <mutex>
32#include <set>
33#include <string>
34#include <unordered_map>
David Chende701692017-10-05 13:16:02 -070035
yro4beccbe2018-03-15 19:42:05 -070036using namespace android;
David Chende701692017-10-05 13:16:02 -070037using namespace std;
38
yro4beccbe2018-03-15 19:42:05 -070039using android::util::ProtoOutputStream;
40
David Chende701692017-10-05 13:16:02 -070041namespace android {
42namespace os {
43namespace statsd {
44
45struct AppData {
Dianne Hackborn3accca02013-09-20 09:32:11 -070046 int64_t versionCode;
David Chenbd125272018-04-04 19:02:50 -070047 bool deleted;
David Chende701692017-10-05 13:16:02 -070048
David Chenbd125272018-04-04 19:02:50 -070049 // Empty constructor needed for unordered map.
50 AppData() {
51 }
52 AppData(const int64_t v) : versionCode(v), deleted(false){};
David Chende701692017-10-05 13:16:02 -070053};
54
yro4beccbe2018-03-15 19:42:05 -070055// When calling appendUidMap, we retrieve all the ChangeRecords since the last
56// timestamp we called appendUidMap for this configuration key.
David Chenf384b902018-03-14 18:36:45 -070057struct ChangeRecord {
58 const bool deletion;
59 const int64_t timestampNs;
60 const string package;
61 const int32_t uid;
Chenjie Yue36018b2018-04-16 15:18:30 -070062 const int64_t version;
63 const int64_t prevVersion;
David Chenf384b902018-03-14 18:36:45 -070064
65 ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
Chenjie Yue36018b2018-04-16 15:18:30 -070066 const int32_t uid, const int64_t version, const int64_t prevVersion)
David Chenf384b902018-03-14 18:36:45 -070067 : deletion(isDeletion),
68 timestampNs(timestampNs),
69 package(package),
70 uid(uid),
David Chenbd125272018-04-04 19:02:50 -070071 version(version),
72 prevVersion(prevVersion) {
David Chenf384b902018-03-14 18:36:45 -070073 }
74};
75
76const unsigned int kBytesChangeRecord = sizeof(struct ChangeRecord);
77
David Chende701692017-10-05 13:16:02 -070078// UidMap keeps track of what the corresponding app name (APK name) and version code for every uid
79// at any given moment. This map must be updated by StatsCompanionService.
Joe Onorato9fc9edf2017-10-15 20:08:52 -070080class UidMap : public virtual android::RefBase {
David Chende701692017-10-05 13:16:02 -070081public:
David Chenc136f452017-11-27 11:52:26 -080082 UidMap();
83 ~UidMap();
Yao Chen147ce602017-12-22 14:35:34 -080084 static const std::map<std::string, uint32_t> sAidToUidMapping;
David Chende701692017-10-05 13:16:02 -070085 /*
86 * All three inputs must be the same size, and the jth element in each array refers to the same
87 * tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
88 */
David Chenbd125272018-04-04 19:02:50 -070089 void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
90 const vector<int64_t>& versionCode, const vector<String16>& packageName);
David Chende701692017-10-05 13:16:02 -070091
David Chenbd125272018-04-04 19:02:50 -070092 void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
93 const int64_t& versionCode);
94 void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
David Chend6896892017-10-25 11:49:03 -070095
David Chende701692017-10-05 13:16:02 -070096 // Returns true if the given uid contains the specified app (eg. com.google.android.gms).
97 bool hasApp(int uid, const string& packageName) const;
98
Yangster9df9a7f2017-12-18 13:33:05 -080099 // Returns the app names from uid.
100 std::set<string> getAppNamesFromUid(const int32_t& uid, bool returnNormalized) const;
101
Dianne Hackborn3accca02013-09-20 09:32:11 -0700102 int64_t getAppVersion(int uid, const string& packageName) const;
David Chende701692017-10-05 13:16:02 -0700103
David Chende701692017-10-05 13:16:02 -0700104 // Helper for debugging contents of this uid map. Can be triggered with:
105 // adb shell cmd stats print-uid-map
Yao Chend10f7b12017-12-18 12:53:50 -0800106 void printUidMap(FILE* out) const;
David Chende701692017-10-05 13:16:02 -0700107
108 // Commands for indicating to the map that a producer should be notified if an app is updated.
109 // This allows the metric producer to distinguish when the same uid or app represents a
110 // different version of an app.
Yao Chend10f7b12017-12-18 12:53:50 -0800111 void addListener(wp<PackageInfoListener> producer);
David Chende701692017-10-05 13:16:02 -0700112 // Remove the listener from the set of metric producers that subscribe to updates.
Yao Chend10f7b12017-12-18 12:53:50 -0800113 void removeListener(wp<PackageInfoListener> producer);
David Chende701692017-10-05 13:16:02 -0700114
David Chend6896892017-10-25 11:49:03 -0700115 // Informs uid map that a config is added/updated. Used for keeping mConfigKeys up to date.
116 void OnConfigUpdated(const ConfigKey& key);
117
118 // Informs uid map that a config is removed. Used for keeping mConfigKeys up to date.
119 void OnConfigRemoved(const ConfigKey& key);
120
David Chen21582962017-11-01 17:32:46 -0700121 void assignIsolatedUid(int isolatedUid, int parentUid);
122 void removeIsolatedUid(int isolatedUid, int parentUid);
123
Yangster-macd40053e2018-01-09 16:29:22 -0800124 // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in.
Chenjie Yu80f91122018-01-31 20:24:50 -0800125 virtual int getHostUidOrSelf(int uid) const;
David Chen21582962017-11-01 17:32:46 -0700126
David Chenf384b902018-03-14 18:36:45 -0700127 // Gets all snapshots and changes that have occurred since the last output.
128 // If every config key has received a change or snapshot record, then this
129 // record is deleted.
David Chenbd125272018-04-04 19:02:50 -0700130 void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
131 util::ProtoOutputStream* proto);
David Chend6896892017-10-25 11:49:03 -0700132
133 // Forces the output to be cleared. We still generate a snapshot based on the current state.
134 // This results in extra data uploaded but helps us reconstruct the uid mapping on the server
135 // in case we lose a previous upload.
136 void clearOutput();
David Chende701692017-10-05 13:16:02 -0700137
David Chenc136f452017-11-27 11:52:26 -0800138 // Get currently cached value of memory used by UID map.
Yao Chend10f7b12017-12-18 12:53:50 -0800139 size_t getBytesUsed() const;
140
141 std::set<int32_t> getAppUid(const string& package) const;
David Chenc136f452017-11-27 11:52:26 -0800142
David Chende701692017-10-05 13:16:02 -0700143private:
Yangster9df9a7f2017-12-18 13:33:05 -0800144 std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const;
145 string normalizeAppName(const string& appName) const;
146
Yao Chend10f7b12017-12-18 12:53:50 -0800147 void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output);
148
David Chende701692017-10-05 13:16:02 -0700149 // TODO: Use shared_mutex for improved read-locking if a library can be found in Android.
150 mutable mutex mMutex;
David Chen21582962017-11-01 17:32:46 -0700151 mutable mutex mIsolatedMutex;
David Chende701692017-10-05 13:16:02 -0700152
David Chenbd125272018-04-04 19:02:50 -0700153 struct PairHash {
154 size_t operator()(std::pair<int, string> p) const noexcept {
155 std::hash<std::string> hash_fn;
156 return hash_fn(std::to_string(p.first) + p.second);
157 }
158 };
159 // Maps uid and package name to application data.
160 std::unordered_map<std::pair<int, string>, AppData, PairHash> mMap;
David Chende701692017-10-05 13:16:02 -0700161
David Chen21582962017-11-01 17:32:46 -0700162 // Maps isolated uid to the parent uid. Any metrics for an isolated uid will instead contribute
163 // to the parent uid.
164 std::unordered_map<int, int> mIsolatedUidMap;
165
David Chenf384b902018-03-14 18:36:45 -0700166 // Record the changes that can be provided with the uploads.
167 std::list<ChangeRecord> mChanges;
168
David Chenbd125272018-04-04 19:02:50 -0700169 // Store which uid and apps represent deleted ones.
170 std::list<std::pair<int, string>> mDeletedApps;
David Chende701692017-10-05 13:16:02 -0700171
172 // Metric producers that should be notified if there's an upgrade in any app.
Yao Chend10f7b12017-12-18 12:53:50 -0800173 set<wp<PackageInfoListener>> mSubscribers;
David Chend6896892017-10-25 11:49:03 -0700174
175 // Mapping of config keys we're aware of to the epoch time they last received an update. This
176 // lets us know it's safe to delete events older than the oldest update. The value is nanosec.
177 // Value of -1 denotes this config key has never received an upload.
178 std::unordered_map<ConfigKey, int64_t> mLastUpdatePerConfigKey;
179
180 // Returns the minimum value from mConfigKeys.
181 int64_t getMinimumTimestampNs();
182
David Chenc136f452017-11-27 11:52:26 -0800183 // If our current used bytes is above the limit, then we clear out the earliest snapshot. If
184 // there are no more snapshots, then we clear out the earliest delta. We repeat the deletions
185 // until the memory consumed by mOutput is below the specified limit.
186 void ensureBytesUsedBelowLimit();
187
David Chenc0f6f632018-01-18 16:02:42 -0800188 // Override used for testing the max memory allowed by uid map. 0 means we use the value
David Chenc136f452017-11-27 11:52:26 -0800189 // specified in StatsdStats.h with the rest of the guardrails.
David Chenc0f6f632018-01-18 16:02:42 -0800190 size_t maxBytesOverride = 0;
David Chenc136f452017-11-27 11:52:26 -0800191
192 // Cache the size of mOutput;
193 size_t mBytesUsed;
194
David Chend6896892017-10-25 11:49:03 -0700195 // Allows unit-test to access private methods.
196 FRIEND_TEST(UidMapTest, TestClearingOutput);
David Chenbd125272018-04-04 19:02:50 -0700197 FRIEND_TEST(UidMapTest, TestRemovedAppRetained);
198 FRIEND_TEST(UidMapTest, TestRemovedAppOverGuardrail);
David Chen35045cb2018-03-23 22:21:47 -0700199 FRIEND_TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot);
David Chenc136f452017-11-27 11:52:26 -0800200 FRIEND_TEST(UidMapTest, TestMemoryComputed);
201 FRIEND_TEST(UidMapTest, TestMemoryGuardrail);
David Chende701692017-10-05 13:16:02 -0700202};
203
204} // namespace statsd
205} // namespace os
206} // namespace android