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