1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 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 17 #pragma once 18 19 #include <gtest/gtest_prod.h> 20 #include <src/uid_data.pb.h> 21 #include <stdio.h> 22 #include <utils/RefBase.h> 23 #include <utils/String16.h> 24 25 #include <list> 26 #include <mutex> 27 #include <set> 28 #include <string> 29 #include <unordered_map> 30 31 #include "config/ConfigKey.h" 32 #include "packages/PackageInfoListener.h" 33 #include "stats_util.h" 34 35 using namespace android; 36 using namespace std; 37 38 using android::util::ProtoOutputStream; 39 40 namespace android { 41 namespace os { 42 namespace statsd { 43 44 struct AppData { 45 int64_t versionCode; 46 string versionString; 47 string installer; 48 bool deleted; 49 string certificateHash; 50 51 // Empty constructor needed for unordered map. AppDataAppData52 AppData() { 53 } 54 AppDataAppData55 AppData(const int64_t v, const string& versionString, const string& installer, 56 const string& certificateHash) 57 : versionCode(v), 58 versionString(versionString), 59 installer(installer), 60 deleted(false), 61 certificateHash(certificateHash){}; 62 }; 63 64 // When calling appendUidMap, we retrieve all the ChangeRecords since the last 65 // timestamp we called appendUidMap for this configuration key. 66 struct ChangeRecord { 67 const bool deletion; 68 const int64_t timestampNs; 69 const string package; 70 const int32_t uid; 71 const int64_t version; 72 const int64_t prevVersion; 73 const string versionString; 74 const string prevVersionString; 75 ChangeRecordChangeRecord76 ChangeRecord(const bool isDeletion, int64_t timestampNs, const string& package, 77 const int32_t uid, int64_t version, const string& versionString, 78 const int64_t prevVersion, const string& prevVersionString) 79 : deletion(isDeletion), 80 timestampNs(timestampNs), 81 package(package), 82 uid(uid), 83 version(version), 84 prevVersion(prevVersion), 85 versionString(versionString), 86 prevVersionString(prevVersionString) { 87 } 88 }; 89 90 const unsigned int kBytesChangeRecord = sizeof(struct ChangeRecord); 91 92 // UidMap keeps track of what the corresponding app name (APK name) and version code for every uid 93 // at any given moment. This map must be updated by StatsCompanionService. 94 class UidMap : public virtual RefBase { 95 public: 96 UidMap(); 97 ~UidMap(); 98 static const std::map<std::string, uint32_t> sAidToUidMapping; 99 100 static sp<UidMap> getInstance(); 101 102 void updateMap(const int64_t timestamp, const UidData& uidData); 103 104 void updateApp(const int64_t timestamp, const string& appName, const int32_t uid, 105 const int64_t versionCode, const string& versionString, const string& installer, 106 const vector<uint8_t>& certificateHash); 107 void removeApp(const int64_t timestamp, const string& app, const int32_t uid); 108 109 // Returns true if the given uid contains the specified app (eg. com.google.android.gms). 110 bool hasApp(int uid, const string& packageName) const; 111 112 // Returns the app names from uid. 113 std::set<string> getAppNamesFromUid(int32_t uid, bool returnNormalized) const; 114 115 int64_t getAppVersion(int uid, const string& packageName) const; 116 117 // Helper for debugging contents of this uid map. Can be triggered with: 118 // adb shell cmd stats print-uid-map [--with_certificate_hash] 119 void printUidMap(int outFd, bool includeCertificateHash) const; 120 121 // Command for indicating to the map that StatsLogProcessor should be notified if an app is 122 // updated. This allows metric producers and managers to distinguish when the same uid or app 123 // represents a different version of an app. 124 void setListener(const wp<PackageInfoListener>& listener); 125 126 // Informs uid map that a config is added/updated. Used for keeping mConfigKeys up to date. 127 void OnConfigUpdated(const ConfigKey& key); 128 129 // Informs uid map that a config is removed. Used for keeping mConfigKeys up to date. 130 void OnConfigRemoved(const ConfigKey& key); 131 132 void assignIsolatedUid(int isolatedUid, int parentUid); 133 void removeIsolatedUid(int isolatedUid); 134 135 // Returns the host uid if it exists. Otherwise, returns the same uid that was passed-in. 136 virtual int getHostUidOrSelf(int uid) const; 137 138 // Gets all snapshots and changes that have occurred since the last output. 139 // If every config key has received a change or snapshot record, then this 140 // record is deleted. 141 void appendUidMap(int64_t timestamp, const ConfigKey& key, const bool includeVersionStrings, 142 const bool includeInstaller, const uint8_t truncatedCertificateHashSize, 143 const bool omitSystemUids, std::set<string>* str_set, 144 ProtoOutputStream* proto); 145 146 // Forces the output to be cleared. We still generate a snapshot based on the current state. 147 // This results in extra data uploaded but helps us reconstruct the uid mapping on the server 148 // in case we lose a previous upload. 149 void clearOutput(); 150 151 // Get currently cached value of memory used by UID map. 152 size_t getBytesUsed() const; 153 154 virtual std::set<int32_t> getAppUid(const string& package) const; 155 156 // Write current PackageInfoSnapshot to ProtoOutputStream. 157 // interestingUids: If not empty, only write the package info for these uids. If empty, write 158 // package info for all uids. 159 // str_set: if not null, add new string to the set and write str_hash to proto 160 // if null, write string to proto. 161 void writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings, bool includeInstaller, 162 const uint8_t truncatedCertificateHashSize, bool omitSystemUids, 163 const std::set<int32_t>& interestingUids, 164 std::map<string, int>* installerIndices, std::set<string>* str_set, 165 ProtoOutputStream* proto) const; 166 167 private: 168 std::set<string> getAppNamesFromUidLocked(int32_t uid, bool returnNormalized) const; 169 string normalizeAppName(const string& appName) const; 170 171 void writeUidMapSnapshotLocked(const int64_t timestamp, const bool includeVersionStrings, 172 const bool includeInstaller, 173 const uint8_t truncatedCertificateHashSize, 174 const bool omitSystemUids, 175 const std::set<int32_t>& interestingUids, 176 std::map<string, int>* installerIndices, 177 std::set<string>* str_set, ProtoOutputStream* proto) const; 178 179 mutable mutex mMutex; 180 mutable mutex mIsolatedMutex; 181 182 struct PairHash { operatorPairHash183 size_t operator()(const std::pair<int, string>& p) const noexcept { 184 std::hash<std::string> hash_fn; 185 return hash_fn(std::to_string(p.first) + p.second); 186 } 187 }; 188 // Maps uid and package name to application data. 189 std::unordered_map<std::pair<int, string>, AppData, PairHash> mMap; 190 191 // Maps isolated uid to the parent uid. Any metrics for an isolated uid will instead contribute 192 // to the parent uid. 193 std::unordered_map<int, int> mIsolatedUidMap; 194 195 // Record the changes that can be provided with the uploads. 196 std::list<ChangeRecord> mChanges; 197 198 // Store which uid and apps represent deleted ones. 199 std::list<std::pair<int, string>> mDeletedApps; 200 201 // Notify StatsLogProcessor if there's an upgrade/removal in any app. 202 wp<PackageInfoListener> mSubscriber; 203 204 // Mapping of config keys we're aware of to the epoch time they last received an update. This 205 // lets us know it's safe to delete events older than the oldest update. The value is nanosec. 206 // Value of -1 denotes this config key has never received an upload. 207 std::unordered_map<ConfigKey, int64_t> mLastUpdatePerConfigKey; 208 209 // Returns the minimum value from mConfigKeys. 210 int64_t getMinimumTimestampNs(); 211 212 // If our current used bytes is above the limit, then we clear out the earliest snapshot. If 213 // there are no more snapshots, then we clear out the earliest delta. We repeat the deletions 214 // until the memory consumed by mOutput is below the specified limit. 215 void ensureBytesUsedBelowLimit(); 216 217 // Override used for testing the max memory allowed by uid map. 0 means we use the value 218 // specified in StatsdStats.h with the rest of the guardrails. 219 size_t maxBytesOverride = 0; 220 221 // Cache the size of mOutput; 222 size_t mBytesUsed; 223 224 // Allows unit-test to access private methods. 225 FRIEND_TEST(RestrictedEventMetricE2eTest, TestRestrictedConfigUpdateDoesNotUpdateUidMap); 226 FRIEND_TEST(RestrictedEventMetricE2eTest, 227 TestRestrictedConfigUpdateAddsDelegateRemovesUidMapEntry); 228 FRIEND_TEST(UidMapTest, TestClearingOutput); 229 FRIEND_TEST(UidMapTest, TestRemovedAppRetained); 230 FRIEND_TEST(UidMapTest, TestRemovedAppOverGuardrail); 231 FRIEND_TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot); 232 FRIEND_TEST(UidMapTest, TestMemoryComputed); 233 FRIEND_TEST(UidMapTest, TestMemoryGuardrail); 234 }; 235 236 } // namespace statsd 237 } // namespace os 238 } // namespace android 239