Merge "Statsd uidmap includes vers string and installer"

This commit is contained in:
TreeHugger Robot
2018-11-15 08:56:28 +00:00
committed by Android (Google) Code Review
16 changed files with 271 additions and 83 deletions

View File

@@ -370,11 +370,9 @@ void StatsLogProcessor::onConfigMetricsReportLocked(const ConfigKey& key,
// This skips the uid map if it's an empty config.
if (it->second->getNumMetrics() > 0) {
uint64_t uidMapToken = proto->start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
if (it->second->hashStringInReport()) {
mUidMap->appendUidMap(dumpTimeStampNs, key, &str_set, proto);
} else {
mUidMap->appendUidMap(dumpTimeStampNs, key, nullptr, proto);
}
mUidMap->appendUidMap(
dumpTimeStampNs, key, it->second->hashStringInReport() ? &str_set : nullptr,
it->second->versionStringsInReport(), it->second->installerInReport(), proto);
proto->end(uidMapToken);
}

View File

@@ -787,21 +787,24 @@ status_t StatsService::cmd_print_logs(int out, const Vector<String8>& args) {
}
Status StatsService::informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
const vector<String16>& app) {
const vector<String16>& version_string,
const vector<String16>& app,
const vector<String16>& installer) {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informAllUidData was called");
mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, app);
mUidMap->updateMap(getElapsedRealtimeNs(), uid, version, version_string, app, installer);
VLOG("StatsService::informAllUidData succeeded");
return Status::ok();
}
Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version) {
Status StatsService::informOnePackage(const String16& app, int32_t uid, int64_t version,
const String16& version_string, const String16& installer) {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informOnePackage was called");
mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version);
mUidMap->updateApp(getElapsedRealtimeNs(), app, uid, version, version_string, installer);
return Status::ok();
}

View File

@@ -73,8 +73,10 @@ public:
virtual Status informAlarmForSubscriberTriggeringFired();
virtual Status informAllUidData(const vector<int32_t>& uid, const vector<int64_t>& version,
const vector<String16>& app);
virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version);
const vector<String16>& version_string,
const vector<String16>& app, const vector<String16>& installer);
virtual Status informOnePackage(const String16& app, int32_t uid, int64_t version,
const String16& version_string, const String16& installer);
virtual Status informOnePackageRemoved(const String16& app, int32_t uid);
virtual Status informDeviceShutdown();

View File

@@ -77,6 +77,8 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
mActivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, mNoReportMetricIds);
mHashStringsInReport = config.hash_strings_in_metric_report();
mVersionStringsInReport = config.version_strings_in_metric_report();
mInstallerInReport = config.installer_in_metric_report();
if (config.allowed_log_source_size() == 0) {
mConfigValid = false;

View File

@@ -83,6 +83,14 @@ public:
return mHashStringsInReport;
};
inline bool versionStringsInReport() const {
return mVersionStringsInReport;
};
inline bool installerInReport() const {
return mInstallerInReport;
};
void refreshTtl(const int64_t currentTimestampNs) {
if (mTtlNs > 0) {
mTtlEndNs = currentTimestampNs + mTtlNs;
@@ -126,6 +134,8 @@ private:
bool mConfigValid = false;
bool mHashStringsInReport = false;
bool mVersionStringsInReport = false;
bool mInstallerInReport = false;
const int64_t mTtlNs;
int64_t mTtlEndNs;

View File

@@ -49,6 +49,10 @@ const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION = 2;
const int FIELD_ID_SNAPSHOT_PACKAGE_UID = 3;
const int FIELD_ID_SNAPSHOT_PACKAGE_DELETED = 4;
const int FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH = 5;
const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING = 6;
const int FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH = 7;
const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER = 8;
const int FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH = 9;
const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
const int FIELD_ID_SNAPSHOTS = 1;
@@ -60,6 +64,10 @@ const int FIELD_ID_CHANGE_UID = 4;
const int FIELD_ID_CHANGE_NEW_VERSION = 5;
const int FIELD_ID_CHANGE_PREV_VERSION = 6;
const int FIELD_ID_CHANGE_PACKAGE_HASH = 7;
const int FIELD_ID_CHANGE_NEW_VERSION_STRING = 8;
const int FIELD_ID_CHANGE_PREV_VERSION_STRING = 9;
const int FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH = 10;
const int FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH = 11;
UidMap::UidMap() : mBytesUsed(0) {}
@@ -104,7 +112,8 @@ int64_t UidMap::getAppVersion(int uid, const string& packageName) const {
}
void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
const vector<int64_t>& versionCode, const vector<String16>& packageName) {
const vector<int64_t>& versionCode, const vector<String16>& versionString,
const vector<String16>& packageName, const vector<String16>& installer) {
vector<wp<PackageInfoListener>> broadcastList;
{
lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
@@ -121,7 +130,9 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
mMap.clear();
for (size_t j = 0; j < uid.size(); j++) {
string package = string(String8(packageName[j]).string());
mMap[std::make_pair(uid[j], package)] = AppData(versionCode[j]);
mMap[std::make_pair(uid[j], package)] =
AppData(versionCode[j], string(String8(versionString[j]).string()),
string(String8(installer[j]).string()));
}
for (const auto& kv : deletedApps) {
@@ -150,23 +161,30 @@ void UidMap::updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
}
void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const int32_t& uid,
const int64_t& versionCode) {
const int64_t& versionCode, const String16& versionString,
const String16& installer) {
vector<wp<PackageInfoListener>> broadcastList;
string appName = string(String8(app_16).string());
{
lock_guard<mutex> lock(mMutex);
int32_t prevVersion = 0;
string prevVersionString = "";
string newVersionString = string(String8(versionString).string());
bool found = false;
auto it = mMap.find(std::make_pair(uid, appName));
if (it != mMap.end()) {
found = true;
prevVersion = it->second.versionCode;
prevVersionString = it->second.versionString;
it->second.versionCode = versionCode;
it->second.versionString = newVersionString;
it->second.installer = string(String8(installer).string());
it->second.deleted = false;
}
if (!found) {
// Otherwise, we need to add an app at this uid.
mMap[std::make_pair(uid, appName)] = AppData(versionCode);
mMap[std::make_pair(uid, appName)] =
AppData(versionCode, newVersionString, string(String8(installer).string()));
} else {
// Only notify the listeners if this is an app upgrade. If this app is being installed
// for the first time, then we don't notify the listeners.
@@ -174,7 +192,8 @@ void UidMap::updateApp(const int64_t& timestamp, const String16& app_16, const i
// app after deletion.
getListenerListCopyLocked(&broadcastList);
}
mChanges.emplace_back(false, timestamp, appName, uid, versionCode, prevVersion);
mChanges.emplace_back(false, timestamp, appName, uid, versionCode, newVersionString,
prevVersion, prevVersionString);
mBytesUsed += kBytesChangeRecord;
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -226,10 +245,12 @@ void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const i
lock_guard<mutex> lock(mMutex);
int64_t prevVersion = 0;
string prevVersionString = "";
auto key = std::make_pair(uid, app);
auto it = mMap.find(key);
if (it != mMap.end() && !it->second.deleted) {
prevVersion = it->second.versionCode;
prevVersionString = it->second.versionString;
it->second.deleted = true;
mDeletedApps.push_back(key);
}
@@ -240,7 +261,7 @@ void UidMap::removeApp(const int64_t& timestamp, const String16& app_16, const i
mMap.erase(oldest);
StatsdStats::getInstance().noteUidMapAppDeletionDropped();
}
mChanges.emplace_back(true, timestamp, app, uid, 0, prevVersion);
mChanges.emplace_back(true, timestamp, app, uid, 0, "", prevVersion, prevVersionString);
mBytesUsed += kBytesChangeRecord;
ensureBytesUsedBelowLimit();
StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
@@ -315,8 +336,9 @@ size_t UidMap::getBytesUsed() const {
return mBytesUsed;
}
void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
std::set<string> *str_set, ProtoOutputStream* proto) {
void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
bool includeVersionStrings, bool includeInstaller,
ProtoOutputStream* proto) {
lock_guard<mutex> lock(mMutex); // Lock for updates
for (const ChangeRecord& record : mChanges) {
@@ -330,8 +352,22 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
str_set->insert(record.package);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PACKAGE_HASH,
(long long)Hash64(record.package));
if (includeVersionStrings) {
str_set->insert(record.versionString);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_NEW_VERSION_STRING_HASH,
(long long)Hash64(record.versionString));
str_set->insert(record.prevVersionString);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_CHANGE_PREV_VERSION_STRING_HASH,
(long long)Hash64(record.prevVersionString));
}
} else {
proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PACKAGE, record.package);
if (includeVersionStrings) {
proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_NEW_VERSION_STRING,
record.versionString);
proto->write(FIELD_TYPE_STRING | FIELD_ID_CHANGE_PREV_VERSION_STRING,
record.prevVersionString);
}
}
proto->write(FIELD_TYPE_INT32 | FIELD_ID_CHANGE_UID, (int)record.uid);
@@ -354,8 +390,26 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
str_set->insert(kv.first.second);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
(long long)Hash64(kv.first.second));
if (includeVersionStrings) {
str_set->insert(kv.second.versionString);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
(long long)Hash64(kv.second.versionString));
}
if (includeInstaller) {
str_set->insert(kv.second.installer);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
(long long)Hash64(kv.second.installer));
}
} else {
proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
if (includeVersionStrings) {
proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
kv.second.versionString);
}
if (includeInstaller) {
proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
kv.second.installer);
}
}
proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
@@ -391,8 +445,9 @@ void UidMap::printUidMap(int out) const {
for (const auto& kv : mMap) {
if (!kv.second.deleted) {
dprintf(out, "%s, v%" PRId64 " (%i)\n", kv.first.second.c_str(), kv.second.versionCode,
kv.first.first);
dprintf(out, "%s, v%" PRId64 ", %s, %s (%i)\n", kv.first.second.c_str(),
kv.second.versionCode, kv.second.versionString.c_str(),
kv.second.installer.c_str(), kv.first.first);
}
}
}

View File

@@ -44,12 +44,16 @@ namespace statsd {
struct AppData {
int64_t versionCode;
string versionString;
string installer;
bool deleted;
// Empty constructor needed for unordered map.
AppData() {
}
AppData(const int64_t v) : versionCode(v), deleted(false){};
AppData(const int64_t v, const string& versionString, const string& installer)
: versionCode(v), versionString(versionString), installer(installer), deleted(false){};
};
// When calling appendUidMap, we retrieve all the ChangeRecords since the last
@@ -61,15 +65,20 @@ struct ChangeRecord {
const int32_t uid;
const int64_t version;
const int64_t prevVersion;
const string versionString;
const string prevVersionString;
ChangeRecord(const bool isDeletion, const int64_t timestampNs, const string& package,
const int32_t uid, const int64_t version, const int64_t prevVersion)
const int32_t uid, const int64_t version, const string versionString,
const int64_t prevVersion, const string prevVersionString)
: deletion(isDeletion),
timestampNs(timestampNs),
package(package),
uid(uid),
version(version),
prevVersion(prevVersion) {
prevVersion(prevVersion),
versionString(versionString),
prevVersionString(prevVersionString) {
}
};
@@ -87,10 +96,12 @@ public:
* tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
*/
void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
const vector<int64_t>& versionCode, const vector<String16>& packageName);
const vector<int64_t>& versionCode, const vector<String16>& versionString,
const vector<String16>& packageName, const vector<String16>& installer);
void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
const int64_t& versionCode);
const int64_t& versionCode, const String16& versionString,
const String16& installer);
void removeApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid);
// Returns true if the given uid contains the specified app (eg. com.google.android.gms).
@@ -127,8 +138,9 @@ public:
// Gets all snapshots and changes that have occurred since the last output.
// If every config key has received a change or snapshot record, then this
// record is deleted.
void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
std::set<string> *str_set, util::ProtoOutputStream* proto);
void appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
bool includeVersionStrings, bool includeInstaller,
util::ProtoOutputStream* proto);
// Forces the output to be cleared. We still generate a snapshot based on the current state.
// This results in extra data uploaded but helps us reconstruct the uid mapping on the server

View File

@@ -233,6 +233,14 @@ message UidMapping {
optional bool deleted = 4;
optional uint64 name_hash = 5;
optional string version_string = 6;
optional uint64 version_string_hash = 7;
optional string installer = 8;
optional uint64 installer_hash = 9;
}
optional int64 elapsed_timestamp_nanos = 1;
@@ -250,6 +258,10 @@ message UidMapping {
optional int64 new_version = 5;
optional int64 prev_version = 6;
optional uint64 app_hash = 7;
optional string new_version_string = 8;
optional string prev_version_string = 9;
optional uint64 new_version_string_hash = 10;
optional uint64 prev_version_string_hash = 11;
}
repeated Change changes = 2;
}

View File

@@ -409,6 +409,10 @@ message StatsdConfig {
repeated MetricActivation metric_activation = 17;
optional bool version_strings_in_metric_report = 18;
optional bool installer_in_metric_report = 19;
// Field number 1000 is reserved for later use.
reserved 1000;
}

View File

@@ -148,8 +148,12 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
uidMap.updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
android::String16(""), android::String16("")});
EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
@@ -297,8 +301,12 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
android::String16(""), android::String16("")});
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1111);
@@ -372,8 +380,12 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
UidMap uidMap;
uidMap.updateMap(
1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
{android::String16("v1"), android::String16("v1"), android::String16("v2"),
android::String16("v1"), android::String16("v2")},
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */);
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
android::String16(""), android::String16("")});
AttributionNodeInternal attribution_node1;
attribution_node1.set_uid(1067);

View File

@@ -153,7 +153,8 @@ TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
// Setup simple config key corresponding to empty config.
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
{String16("p1"), String16("p2")}, {String16(""), String16("")});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;
@@ -182,7 +183,8 @@ TEST(StatsLogProcessorTest, TestEmptyConfigHasNoUidMap) {
// Setup simple config key corresponding to empty config.
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
m->updateMap(1, {1, 2}, {1, 2}, {String16("p1"), String16("p2")});
m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
{String16("p1"), String16("p2")}, {String16(""), String16("")});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;

View File

@@ -71,14 +71,20 @@ TEST(UidMapTest, TestMatching) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
vector<String16> versionStrings;
vector<String16> installers;
uids.push_back(1000);
uids.push_back(1000);
versionStrings.push_back(String16("v1"));
versionStrings.push_back(String16("v1"));
installers.push_back(String16(""));
installers.push_back(String16(""));
apps.push_back(String16(kApp1.c_str()));
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
m.updateMap(1, uids, versions, apps);
m.updateMap(1, uids, versions, versionStrings, apps, installers);
EXPECT_TRUE(m.hasApp(1000, kApp1));
EXPECT_TRUE(m.hasApp(1000, kApp2));
EXPECT_FALSE(m.hasApp(1000, "not.app"));
@@ -97,14 +103,20 @@ TEST(UidMapTest, TestAddAndRemove) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
vector<String16> versionStrings;
vector<String16> installers;
uids.push_back(1000);
uids.push_back(1000);
versionStrings.push_back(String16("v1"));
versionStrings.push_back(String16("v1"));
installers.push_back(String16(""));
installers.push_back(String16(""));
apps.push_back(String16(kApp1.c_str()));
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
m.updateMap(1, uids, versions, apps);
m.updateMap(1, uids, versions, versionStrings, apps, installers);
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 2u);
@@ -112,7 +124,7 @@ TEST(UidMapTest, TestAddAndRemove) {
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Update the app1 version.
m.updateApp(2, String16(kApp1.c_str()), 1000, 40);
m.updateApp(2, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -138,14 +150,15 @@ TEST(UidMapTest, TestAddAndRemove) {
TEST(UidMapTest, TestUpdateApp) {
UidMap m;
m.updateMap(1, {1000, 1000}, {4, 5}, {String16(kApp1.c_str()), String16(kApp2.c_str())});
m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
{String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")});
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 2u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
EXPECT_TRUE(name_set.find(kApp2) != name_set.end());
// Adds a new name for uid 1000.
m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40);
m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 3u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
@@ -154,7 +167,7 @@ TEST(UidMapTest, TestUpdateApp) {
EXPECT_TRUE(name_set.find("new_app1_name") != name_set.end());
// This name is also reused by another uid 2000.
m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1);
m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""));
name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
EXPECT_EQ(name_set.size(), 1u);
EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -185,21 +198,26 @@ TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
vector<String16> versionStrings;
vector<String16> installers;
uids.push_back(1000);
apps.push_back(String16(kApp2.c_str()));
versionStrings.push_back(String16("v1"));
installers.push_back(String16(""));
versions.push_back(5);
m.updateMap(1, uids, versions, apps);
m.updateMap(1, uids, versions, versionStrings, apps, installers);
// Set the last timestamp for this config key to be newer.
m.mLastUpdatePerConfigKey[config1] = 2;
ProtoOutputStream proto;
m.appendUidMap(3, config1, nullptr, &proto);
m.appendUidMap(3, config1, nullptr, true, true, &proto);
// Check there's still a uidmap attached this one.
UidMapping results;
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ("v1", results.snapshots(0).package_info(0).version_string());
}
TEST(UidMapTest, TestRemovedAppRetained) {
@@ -209,15 +227,19 @@ TEST(UidMapTest, TestRemovedAppRetained) {
m.OnConfigUpdated(config1);
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> versionStrings;
vector<String16> installers;
vector<String16> apps;
uids.push_back(1000);
apps.push_back(String16(kApp2.c_str()));
versions.push_back(5);
m.updateMap(1, uids, versions, apps);
versionStrings.push_back(String16("v5"));
installers.push_back(String16(""));
m.updateMap(1, uids, versions, versionStrings, apps, installers);
m.removeApp(2, String16(kApp2.c_str()), 1000);
ProtoOutputStream proto;
m.appendUidMap(3, config1, nullptr, &proto);
m.appendUidMap(3, config1, nullptr, true, true, &proto);
// Snapshot should still contain this item as deleted.
UidMapping results;
@@ -233,30 +255,34 @@ TEST(UidMapTest, TestRemovedAppOverGuardrail) {
m.OnConfigUpdated(config1);
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> versionStrings;
vector<String16> installers;
vector<String16> apps;
const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
for (int j = 0; j < maxDeletedApps + 10; j++) {
uids.push_back(j);
apps.push_back(String16(kApp1.c_str()));
versions.push_back(j);
versionStrings.push_back(String16("v"));
installers.push_back(String16(""));
}
m.updateMap(1, uids, versions, apps);
m.updateMap(1, uids, versions, versionStrings, apps, installers);
// First, verify that we have the expected number of items.
UidMapping results;
ProtoOutputStream proto;
m.appendUidMap(3, config1, nullptr, &proto);
m.appendUidMap(3, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
// Now remove all the apps.
m.updateMap(1, uids, versions, apps);
m.updateMap(1, uids, versions, versionStrings, apps, installers);
for (int j = 0; j < maxDeletedApps + 10; j++) {
m.removeApp(4, String16(kApp1.c_str()), j);
}
proto.clear();
m.appendUidMap(5, config1, nullptr, &proto);
m.appendUidMap(5, config1, nullptr, true, true, &proto);
// Snapshot drops the first nine items.
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
@@ -272,6 +298,8 @@ TEST(UidMapTest, TestClearingOutput) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> versionStrings;
vector<String16> installers;
vector<String16> apps;
uids.push_back(1000);
uids.push_back(1000);
@@ -279,45 +307,49 @@ TEST(UidMapTest, TestClearingOutput) {
apps.push_back(String16(kApp2.c_str()));
versions.push_back(4);
versions.push_back(5);
m.updateMap(1, uids, versions, apps);
versionStrings.push_back(String16("v4"));
versionStrings.push_back(String16("v5"));
installers.push_back(String16(""));
installers.push_back(String16(""));
m.updateMap(1, uids, versions, versionStrings, apps, installers);
ProtoOutputStream proto;
m.appendUidMap(2, config1, nullptr, &proto);
m.appendUidMap(2, config1, nullptr, true, true, &proto);
UidMapping results;
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
// We have to keep at least one snapshot in memory at all times.
proto.clear();
m.appendUidMap(2, config1, nullptr, &proto);
m.appendUidMap(2, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
// Now add another configuration.
m.OnConfigUpdated(config2);
m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
EXPECT_EQ(1U, m.mChanges.size());
proto.clear();
m.appendUidMap(6, config1, nullptr, &proto);
m.appendUidMap(6, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(1, results.changes_size());
EXPECT_EQ(1U, m.mChanges.size());
// Add another delta update.
m.updateApp(7, String16(kApp2.c_str()), 1001, 41);
m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""));
EXPECT_EQ(2U, m.mChanges.size());
// We still can't remove anything.
proto.clear();
m.appendUidMap(8, config1, nullptr, &proto);
m.appendUidMap(8, config1, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(1, results.changes_size());
EXPECT_EQ(2U, m.mChanges.size());
proto.clear();
m.appendUidMap(9, config2, nullptr, &proto);
m.appendUidMap(9, config2, nullptr, true, true, &proto);
protoOutputStreamToUidMapping(&proto, &results);
EXPECT_EQ(1, results.snapshots_size());
EXPECT_EQ(2, results.changes_size());
@@ -335,19 +367,23 @@ TEST(UidMapTest, TestMemoryComputed) {
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> apps;
vector<String16> versionStrings;
vector<String16> installers;
uids.push_back(1000);
apps.push_back(String16(kApp1.c_str()));
versions.push_back(1);
m.updateMap(1, uids, versions, apps);
versionStrings.push_back(String16("v1"));
installers.push_back(String16(""));
m.updateMap(1, uids, versions, versionStrings, apps, installers);
m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
m.updateApp(3, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
ProtoOutputStream proto;
vector<uint8_t> bytes;
m.appendUidMap(2, config1, nullptr, &proto);
m.appendUidMap(2, config1, nullptr, true, true, &proto);
size_t prevBytes = m.mBytesUsed;
m.appendUidMap(4, config1, nullptr, &proto);
m.appendUidMap(4, config1, nullptr, true, true, &proto);
EXPECT_TRUE(m.mBytesUsed < prevBytes);
}
@@ -361,21 +397,27 @@ TEST(UidMapTest, TestMemoryGuardrail) {
size_t startBytes = m.mBytesUsed;
vector<int32_t> uids;
vector<int64_t> versions;
vector<String16> versionStrings;
vector<String16> installers;
vector<String16> apps;
for (int i = 0; i < 100; i++) {
uids.push_back(1);
buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
apps.push_back(String16(buf.c_str()));
versions.push_back(1);
versionStrings.push_back(String16("v1"));
installers.push_back(String16(""));
}
m.updateMap(1, uids, versions, apps);
m.updateMap(1, uids, versions, versionStrings, apps, installers);
m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
String16("v2"), String16(""));
EXPECT_EQ(1U, m.mChanges.size());
// Now force deletion by limiting the memory to hold one delta change.
m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
m.maxBytesOverride = 120; // Since the app string alone requires >45 characters.
m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4,
String16("v4"), String16(""));
EXPECT_EQ(1U, m.mChanges.size());
}

View File

@@ -69,8 +69,10 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")});
String16("APP3")},
{String16(""), String16(""), String16(""), String16("")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
@@ -215,8 +217,10 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
// Here it assumes that GMS core has two uids.
processor->getUidMap()->updateMap(
1, {222, 444, 111, 333}, {1, 1, 2, 2},
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")});
String16("APP3")},
{String16(""), String16(""), String16(""), String16("")});
// GMS core node is in the middle.
std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),

View File

@@ -132,7 +132,8 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
// This is a new installation, so there shouldn't be a split (should be same as the without
// split case).
service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
// Goes into the second bucket.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
@@ -145,11 +146,13 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
{String16("")});
// Force the uidmap to update at timestamp 2.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2);
service.mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
// Goes into the second bucket.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
@@ -168,7 +171,8 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
SendConfig(service, MakeConfig());
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service.mUidMap->updateMap(start, {1}, {1}, {String16(kApp1.c_str())});
service.mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
{String16("")});
// Force the uidmap to update at timestamp 2.
service.mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
@@ -189,13 +193,14 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeValueMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
String16("v2"), String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -206,14 +211,15 @@ TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);
@@ -229,13 +235,14 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeGaugeMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2);
service.mUidMap->updateApp(5 * 60 * NS_PER_SEC + start + 2, String16(kApp1.c_str()), 1, 2,
String16("v2"), String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100, true);
@@ -246,14 +253,15 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
StatsService service(nullptr);
// Partial buckets don't occur when app is first installed.
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1);
service.mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
SendConfig(service, MakeGaugeMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2;
service.mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2);
service.mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
String16(""));
ConfigMetricsReport report =
GetReports(service.mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC, true);

View File

@@ -62,12 +62,15 @@ interface IStatsManager {
* Inform statsd what the version and package are for each uid. Note that each array should
* have the same number of elements, and version[i] and package[i] correspond to uid[i].
*/
oneway void informAllUidData(in int[] uid, in long[] version, in String[] app);
oneway void informAllUidData(in int[] uid, in long[] version, in String[] version_string,
in String[] app, in String[] installer);
/**
* Inform statsd what the uid and version are for one app that was updated.
* Inform statsd what the uid, version, version_string, and installer are for one app that was
* updated.
*/
oneway void informOnePackage(in String app, in int uid, in long version);
oneway void informOnePackage(in String app, in int uid, in long version,
in String version_string, in String installer);
/**
* Inform stats that an app was removed.

View File

@@ -366,6 +366,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
List<Integer> uids = new ArrayList<>();
List<Long> versions = new ArrayList<>();
List<String> apps = new ArrayList<>();
List<String> versionStrings = new ArrayList<>();
List<String> installers = new ArrayList<>();
// Add in all the apps for every user/profile.
for (UserInfo profile : users) {
@@ -373,14 +375,24 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
for (int j = 0; j < pi.size(); j++) {
if (pi.get(j).applicationInfo != null) {
String installer;
try {
installer = pm.getInstallerPackageName(pi.get(j).packageName);
} catch (IllegalArgumentException e) {
installer = "";
}
installers.add(installer == null ? "" : installer);
uids.add(pi.get(j).applicationInfo.uid);
versions.add(pi.get(j).getLongVersionCode());
versionStrings.add(pi.get(j).versionName);
apps.add(pi.get(j).packageName);
}
}
}
sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions), apps.toArray(new
String[apps.size()]));
sStatsd.informAllUidData(toIntArray(uids), toLongArray(versions),
versionStrings.toArray(new String[versionStrings.size()]),
apps.toArray(new String[apps.size()]),
installers.toArray(new String[installers.size()]));
if (DEBUG) {
Slog.d(TAG, "Sent data for " + uids.size() + " apps");
}
@@ -422,7 +434,14 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int uid = b.getInt(Intent.EXTRA_UID);
String app = intent.getData().getSchemeSpecificPart();
PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
sStatsd.informOnePackage(app, uid, pi.getLongVersionCode());
String installer;
try {
installer = pm.getInstallerPackageName(app);
} catch (IllegalArgumentException e) {
installer = "";
}
sStatsd.informOnePackage(app, uid, pi.getLongVersionCode(), pi.versionName,
installer == null ? "" : installer);
}
} catch (Exception e) {
Slog.w(TAG, "Failed to inform statsd of an app update", e);