summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-12 13:55:22 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-12 13:55:22 +0000
commit4de2bef389636303f9d4ad0f181af802fc7e7f24 (patch)
tree02120d2f84a37aadd571d579f2feba88fff16477
parent9061fe2567f7c37992753ba08adb29d1590e59db (diff)
parent2e72e87f6068f2b0362549dc5934a2dba044676b (diff)
downloadStatsD-android12-mainline-wifi-release.tar.gz
Snap for 8441503 from 2e72e87f6068f2b0362549dc5934a2dba044676b to mainline-wifi-releaseandroid-mainline-12.0.0_r126aml_wif_311811030android12-mainline-wifi-release
Change-Id: I18e712a83e67ee9e8a012fed6b8de7b4db982af6
-rw-r--r--aidl/Android.bp1
-rw-r--r--aidl/android/os/IStatsd.aidl8
-rw-r--r--aidl/android/util/PropertyParcel.aidl9
-rw-r--r--service/java/com/android/server/stats/StatsCompanionService.java169
-rw-r--r--statsd/src/StatsLogProcessor.cpp7
-rw-r--r--statsd/src/StatsService.cpp57
-rw-r--r--statsd/src/StatsService.h10
-rw-r--r--statsd/src/metrics/MetricsManager.cpp3
-rw-r--r--statsd/src/metrics/MetricsManager.h5
-rw-r--r--statsd/src/metrics/parsing_utils/config_update_utils.cpp6
-rw-r--r--statsd/src/metrics/parsing_utils/metrics_manager_util.cpp6
-rw-r--r--statsd/src/packages/UidMap.cpp190
-rw-r--r--statsd/src/packages/UidMap.h47
-rw-r--r--statsd/src/stats_log.proto10
-rw-r--r--statsd/src/stats_log_util.cpp10
-rw-r--r--statsd/src/stats_log_util.h2
-rw-r--r--statsd/src/statsd_config.proto2
-rw-r--r--statsd/src/subscriber/IncidentdReporter.cpp4
-rw-r--r--statsd/src/uid_data.proto1
-rw-r--r--statsd/tests/LogEntryMatcher_test.cpp12
-rw-r--r--statsd/tests/StatsLogProcessor_test.cpp9
-rw-r--r--statsd/tests/UidMap_test.cpp217
-rw-r--r--statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp5
-rw-r--r--statsd/tests/e2e/Attribution_e2e_test.cpp6
-rw-r--r--statsd/tests/e2e/ConfigUpdate_e2e_ab_test.cpp28
-rw-r--r--statsd/tests/e2e/PartialBucket_e2e_test.cpp36
26 files changed, 601 insertions, 259 deletions
diff --git a/aidl/Android.bp b/aidl/Android.bp
index 54bf1a8f..cea97395 100644
--- a/aidl/Android.bp
+++ b/aidl/Android.bp
@@ -32,6 +32,7 @@ aidl_interface {
"android/os/IStatsCompanionService.aidl",
"android/os/IStatsd.aidl",
"android/os/StatsDimensionsValueParcel.aidl",
+ "android/util/PropertyParcel.aidl",
"android/util/StatsEventParcel.aidl",
],
host_supported: true,
diff --git a/aidl/android/os/IStatsd.aidl b/aidl/android/os/IStatsd.aidl
index 0d3f4208..2a0fe695 100644
--- a/aidl/android/os/IStatsd.aidl
+++ b/aidl/android/os/IStatsd.aidl
@@ -19,6 +19,7 @@ package android.os;
import android.os.IPendingIntentRef;
import android.os.IPullAtomCallback;
import android.os.ParcelFileDescriptor;
+import android.util.PropertyParcel;
/**
* Binder interface to communicate with the statistics management service.
@@ -80,7 +81,7 @@ interface IStatsd {
* updated.
*/
oneway void informOnePackage(in String app, in int uid, in long version,
- in String version_string, in String installer);
+ in String version_string, in String installer, in byte[] certificate_hash);
/**
* Inform stats that an app was removed.
@@ -234,4 +235,9 @@ interface IStatsd {
* Returns the most recently registered experiment IDs.
*/
long[] getRegisteredExperimentIds();
+
+ /**
+ * Notifies of properties in statsd_java namespace.
+ */
+ oneway void updateProperties(in PropertyParcel[] properties);
}
diff --git a/aidl/android/util/PropertyParcel.aidl b/aidl/android/util/PropertyParcel.aidl
new file mode 100644
index 00000000..38c45f34
--- /dev/null
+++ b/aidl/android/util/PropertyParcel.aidl
@@ -0,0 +1,9 @@
+package android.util;
+
+/**
+ * @hide
+ */
+parcelable PropertyParcel {
+ String property;
+ String value;
+}
diff --git a/service/java/com/android/server/stats/StatsCompanionService.java b/service/java/com/android/server/stats/StatsCompanionService.java
index 83847d81..a0460fa4 100644
--- a/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/service/java/com/android/server/stats/StatsCompanionService.java
@@ -16,6 +16,8 @@
package com.android.server.stats;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
+import static android.provider.DeviceConfig.NAMESPACE_STATSD_JAVA;
+import static android.provider.DeviceConfig.Properties;
import android.app.AlarmManager;
import android.app.AlarmManager.OnAlarmListener;
@@ -25,9 +27,12 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.InstallSourceInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.Signature;
+import android.content.pm.SigningInfo;
import android.os.Binder;
import android.os.Bundle;
import android.os.FileUtils;
@@ -44,22 +49,28 @@ import android.os.StatsFrameworkInitializer;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.util.Log;
+import android.util.PropertyParcel;
import android.util.proto.ProtoOutputStream;
-
-import com.android.modules.utils.build.SdkLevel;
import com.android.internal.annotations.GuardedBy;
+import com.android.modules.utils.build.SdkLevel;
import com.android.server.stats.StatsHelper;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.nio.ByteOrder;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -88,14 +99,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private static final int VERSION_STRING_FIELD_ID = 3;
private static final int PACKAGE_NAME_FIELD_ID = 4;
private static final int INSTALLER_FIELD_ID = 5;
+ private static final int CERTIFICATE_HASH_FIELD_ID = 6;
public static final int DEATH_THRESHOLD = 10;
- static final class CompanionHandler extends Handler {
- CompanionHandler(Looper looper) {
- super(looper);
- }
- }
+ private static final String INCLUDE_CERTIFICATE_HASH = "include_certificate_hash";
private final Context mContext;
private final AlarmManager mAlarmManager;
@@ -112,7 +120,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private final HashSet<Long> mDeathTimeMillis = new HashSet<>();
@GuardedBy("sStatsdLock")
private final HashMap<Long, String> mDeletedFiles = new HashMap<>();
- private final CompanionHandler mHandler;
+ private final Handler mHandler;
// Flag that is set when PHASE_BOOT_COMPLETED is triggered in the StatsCompanion lifecycle.
private AtomicBoolean mBootCompleted = new AtomicBoolean(false);
@@ -124,7 +132,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
if (DEBUG) Log.d(TAG, "Registered receiver for ACTION_PACKAGE_REPLACED and ADDED.");
HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
- mHandler = new CompanionHandler(handlerThread.getLooper());
+ mHandler = new Handler(handlerThread.getLooper());
mPullingAlarmListener = new PullingAlarmListener(context);
mPeriodicAlarmListener = new PeriodicAlarmListener(context);
@@ -141,6 +149,51 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
+ private static String getInstallerPackageName(PackageManager pm, String name) {
+ InstallSourceInfo installSourceInfo = null;
+ try {
+ installSourceInfo = pm.getInstallSourceInfo(name);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Could not get installer for package: " + name, e);
+ }
+
+ String installerPackageName = null;
+ if (installSourceInfo != null) {
+ installerPackageName = installSourceInfo.getInitiatingPackageName();
+ if (installerPackageName == null) {
+ installerPackageName = installSourceInfo.getInstallingPackageName();
+ }
+ }
+
+ return installerPackageName == null ? "" : installerPackageName;
+ }
+
+ private static byte[] getPackageCertificateHash(final SigningInfo si) {
+ if (si == null) {
+ return new byte[0];
+ }
+
+ final Signature[] signatures = si.getApkContentsSigners();
+ if (signatures == null || signatures.length < 1) {
+ return new byte[0];
+ }
+
+ MessageDigest messageDigest = null;
+ try {
+ messageDigest = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ Log.e(TAG, "Failed to get SHA-256 instance of MessageDigest", e);
+ return new byte[0];
+ }
+
+ Arrays.sort(signatures, Comparator.comparing(Signature::hashCode));
+ for (final Signature signature : signatures) {
+ messageDigest.update(signature.toByteArray());
+ }
+
+ return messageDigest.digest();
+ }
+
private static void informAllUids(Context context) {
ParcelFileDescriptor[] fds;
try {
@@ -179,18 +232,15 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
try {
ProtoOutputStream output = new ProtoOutputStream(fout);
int numRecords = 0;
+
// Add in all the apps for every user/profile.
for (UserHandle userHandle : users) {
List<PackageInfo> packagesPlusApex = getAllPackagesWithApex(pm, userHandle);
for (int j = 0; j < packagesPlusApex.size(); j++) {
if (packagesPlusApex.get(j).applicationInfo != null) {
- String installer;
- try {
- installer = pm.getInstallerPackageName(
- packagesPlusApex.get(j).packageName);
- } catch (IllegalArgumentException e) {
- installer = "";
- }
+ final String installer = getInstallerPackageName(
+ pm, packagesPlusApex.get(j).packageName);
+
long applicationInfoToken =
output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE
| ProtoOutputStream.FIELD_COUNT_REPEATED
@@ -212,7 +262,17 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
output.write(ProtoOutputStream.FIELD_TYPE_STRING
| ProtoOutputStream.FIELD_COUNT_SINGLE
| INSTALLER_FIELD_ID,
- installer == null ? "" : installer);
+ installer);
+ if (DeviceConfig.getBoolean(
+ NAMESPACE_STATSD_JAVA, INCLUDE_CERTIFICATE_HASH, false)) {
+ final byte[] certHash = getPackageCertificateHash(
+ packagesPlusApex.get(j).signingInfo);
+ output.write(ProtoOutputStream.FIELD_TYPE_BYTES
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
+ | CERTIFICATE_HASH_FIELD_ID,
+ certHash);
+ }
+
numRecords++;
output.end(applicationInfoToken);
}
@@ -235,7 +295,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
// We want all the uninstalled packages because uninstalled package uids can still be logged
// to statsd.
List<PackageInfo> allPackages = new ArrayList<>(
- pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
+ pm.getInstalledPackagesAsUser(PackageManager.GET_SIGNING_CERTIFICATES
+ | PackageManager.MATCH_UNINSTALLED_PACKAGES
| PackageManager.MATCH_ANY_USER,
userHandle.getIdentifier()));
// We make a second query to package manager for the apex modules because package manager
@@ -309,19 +370,25 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
Bundle b = intent.getExtras();
int uid = b.getInt(Intent.EXTRA_UID);
String app = intent.getData().getSchemeSpecificPart();
- PackageInfo pi = pm.getPackageInfo(app, PackageManager.MATCH_ANY_USER);
- String installer;
- try {
- installer = pm.getInstallerPackageName(app);
- } catch (IllegalArgumentException e) {
- installer = "";
+ PackageInfo pi = pm.getPackageInfo(app,
+ PackageManager.GET_SIGNING_CERTIFICATES
+ | PackageManager.MATCH_ANY_USER);
+ final String installer = getInstallerPackageName(pm, app);
+
+ // Get Package certificate hash.
+ byte[] certHash = new byte[0];
+ if (DeviceConfig.getBoolean(
+ NAMESPACE_STATSD_JAVA, INCLUDE_CERTIFICATE_HASH, false)) {
+ certHash = getPackageCertificateHash(pi.signingInfo);
}
+
sStatsd.informOnePackage(
app,
uid,
pi.getLongVersionCode(),
pi.versionName == null ? "" : pi.versionName,
- installer == null ? "" : installer);
+ installer,
+ certHash);
}
} catch (Exception e) {
Log.w(TAG, "Failed to inform statsd of an app update", e);
@@ -604,6 +671,49 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
mStatsManagerService = statsManagerService;
}
+ private void onPropertiesChanged(final Properties properties) {
+ updateProperties(properties);
+
+ // Re-fetch package information with package certificates if include_certificate_hash
+ // property changed.
+ final Set<String> propertyNames = properties.getKeyset();
+ if (propertyNames.contains(INCLUDE_CERTIFICATE_HASH)) {
+ informAllUids(mContext);
+ }
+ }
+
+ private void updateProperties(final Properties properties) {
+ if (DEBUG) {
+ Log.d(TAG, "statsd_java properties updated");
+ }
+
+ final Set<String> propertyNames = properties.getKeyset();
+ if (propertyNames.isEmpty()) {
+ return;
+ }
+
+ final PropertyParcel[] propertyParcels = new PropertyParcel[propertyNames.size()];
+ int index = 0;
+ for (final String propertyName : propertyNames) {
+ propertyParcels[index] = new PropertyParcel();
+ propertyParcels[index].property = propertyName;
+ propertyParcels[index].value = properties.getString(propertyName, null);
+ index++;
+ }
+
+ final IStatsd statsd = getStatsdNonblocking();
+ if (statsd == null) {
+ Log.w(TAG, "Could not access statsd to inform it of updated statsd_java properties");
+ return;
+ }
+
+ try {
+ statsd.updateProperties(propertyParcels);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to inform statsd of an include app certificate flag update", e);
+ }
+ }
+
/**
* Tells statsd that statscompanion is ready. If the binder call returns, link to
* statsd.
@@ -659,6 +769,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
filter.addAction(Intent.ACTION_SHUTDOWN);
mContext.registerReceiverForAllUsers(shutdownEventReceiver, filter, null, null);
+ // Register listener for statsd_java properties updates.
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_STATSD_JAVA,
+ mContext.getMainExecutor(), this::onPropertiesChanged);
+
+ // Get current statsd_java properties.
+ updateProperties(DeviceConfig.getProperties(NAMESPACE_STATSD_JAVA));
+
// Register death recipient.
List<BroadcastReceiver> broadcastReceivers =
List.of(appUpdateReceiver, userUpdateReceiver, shutdownEventReceiver);
diff --git a/statsd/src/StatsLogProcessor.cpp b/statsd/src/StatsLogProcessor.cpp
index 10d21121..1f0f5644 100644
--- a/statsd/src/StatsLogProcessor.cpp
+++ b/statsd/src/StatsLogProcessor.cpp
@@ -693,9 +693,10 @@ void StatsLogProcessor::onConfigMetricsReportLocked(
// This skips the uid map if it's an empty config.
if (it->second->getNumMetrics() > 0) {
uint64_t uidMapToken = tempProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_UID_MAP);
- mUidMap->appendUidMap(
- dumpTimeStampNs, key, it->second->hashStringInReport() ? &str_set : nullptr,
- it->second->versionStringsInReport(), it->second->installerInReport(), &tempProto);
+ mUidMap->appendUidMap(dumpTimeStampNs, key, it->second->versionStringsInReport(),
+ it->second->installerInReport(),
+ it->second->packageCertificateHashSizeBytes(),
+ it->second->hashStringInReport() ? &str_set : nullptr, &tempProto);
tempProto.end(uidMapToken);
}
diff --git a/statsd/src/StatsService.cpp b/statsd/src/StatsService.cpp
index 00370577..ef21a041 100644
--- a/statsd/src/StatsService.cpp
+++ b/statsd/src/StatsService.cpp
@@ -55,6 +55,8 @@ constexpr const char* kPermissionDump = "android.permission.DUMP";
constexpr const char* kPermissionRegisterPullAtom = "android.permission.REGISTER_STATS_PULL_ATOM";
+constexpr const char* kIncludeCertificateHash = "include_certificate_hash";
+
#define STATS_SERVICE_DIR "/data/misc/stats-service"
// for StatsDataDumpProto
@@ -390,9 +392,13 @@ void StatsService::print_cmd_help(int out) {
dprintf(out, "\n");
dprintf(out, "\n");
dprintf(out, "usage: adb shell cmd stats print-uid-map [PKG]\n");
+ dprintf(out, "usage: adb shell cmd stats print-uid-map --with_certificate_hash\n");
dprintf(out, "\n");
dprintf(out, " Prints the UID, app name, version mapping.\n");
- dprintf(out, " PKG Optional package name to print the uids of the package\n");
+ dprintf(out,
+ " PKG Optional package name to print the uids of the "
+ "package\n");
+ dprintf(out, " --with_certificate_hash Print package certificate hash in hex\n");
dprintf(out, "\n");
dprintf(out, "\n");
dprintf(out, "usage: adb shell cmd stats pull-source ATOM_TAG [PACKAGE] \n");
@@ -737,16 +743,20 @@ status_t StatsService::cmd_print_stats(int out, const Vector<String8>& args) {
status_t StatsService::cmd_print_uid_map(int out, const Vector<String8>& args) {
if (args.size() > 1) {
- string pkg;
- pkg.assign(args[1].c_str(), args[1].size());
- auto uids = mUidMap->getAppUid(pkg);
- dprintf(out, "%s -> [ ", pkg.c_str());
- for (const auto& uid : uids) {
- dprintf(out, "%d ", uid);
+ if (!std::strcmp("--with_certificate_hash", args[1].c_str())) {
+ mUidMap->printUidMap(out, /* includeCertificateHash */ true);
+ } else {
+ string pkg;
+ pkg.assign(args[1].c_str(), args[1].size());
+ auto uids = mUidMap->getAppUid(pkg);
+ dprintf(out, "%s -> [ ", pkg.c_str());
+ for (const auto& uid : uids) {
+ dprintf(out, "%d ", uid);
+ }
+ dprintf(out, "]\n");
}
- dprintf(out, "]\n");
} else {
- mUidMap->printUidMap(out);
+ mUidMap->printUidMap(out, /* includeCertificateHash */ false);
}
return NO_ERROR;
}
@@ -928,6 +938,7 @@ Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
vector<String16> packageNames;
vector<int32_t> uids;
vector<int64_t> versions;
+ vector<vector<uint8_t>> certificateHashes;
const auto numEntries = uidData.app_info_size();
versionStrings.reserve(numEntries);
@@ -935,6 +946,7 @@ Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
packageNames.reserve(numEntries);
uids.reserve(numEntries);
versions.reserve(numEntries);
+ certificateHashes.reserve(numEntries);
for (const auto& appInfo: uidData.app_info()) {
packageNames.emplace_back(String16(appInfo.package_name().c_str()));
@@ -942,14 +954,13 @@ Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
versions.push_back(appInfo.version());
versionStrings.emplace_back(String16(appInfo.version_string().c_str()));
installers.emplace_back(String16(appInfo.installer().c_str()));
+
+ const string& certHash = appInfo.certificate_hash();
+ certificateHashes.emplace_back(certHash.begin(), certHash.end());
}
- mUidMap->updateMap(getElapsedRealtimeNs(),
- uids,
- versions,
- versionStrings,
- packageNames,
- installers);
+ mUidMap->updateMap(getElapsedRealtimeNs(), uids, versions, versionStrings, packageNames,
+ installers, certificateHashes);
mBootCompleteTrigger.markComplete(kUidMapReceivedTag);
VLOG("StatsService::informAllUidData UidData proto parsed successfully.");
@@ -957,7 +968,8 @@ Status StatsService::informAllUidData(const ScopedFileDescriptor& fd) {
}
Status StatsService::informOnePackage(const string& app, int32_t uid, int64_t version,
- const string& versionString, const string& installer) {
+ const string& versionString, const string& installer,
+ const vector<uint8_t>& certificateHash) {
ENFORCE_UID(AID_SYSTEM);
VLOG("StatsService::informOnePackage was called");
@@ -966,7 +978,7 @@ Status StatsService::informOnePackage(const string& app, int32_t uid, int64_t ve
String16 utf16Installer = String16(installer.c_str());
mUidMap->updateApp(getElapsedRealtimeNs(), utf16App, uid, version, utf16VersionString,
- utf16Installer);
+ utf16Installer, certificateHash);
return Status::ok();
}
@@ -1292,6 +1304,17 @@ Status StatsService::getRegisteredExperimentIds(std::vector<int64_t>* experiment
return Status::ok();
}
+Status StatsService::updateProperties(const vector<PropertyParcel>& properties) {
+ ENFORCE_UID(AID_SYSTEM);
+
+ for (const auto& [property, value] : properties) {
+ if (property == kIncludeCertificateHash) {
+ mUidMap->setIncludeCertificateHash(value == "true");
+ }
+ }
+ return Status::ok();
+}
+
void StatsService::statsCompanionServiceDied(void* cookie) {
auto thiz = static_cast<StatsService*>(cookie);
thiz->statsCompanionServiceDiedImpl();
diff --git a/statsd/src/StatsService.h b/statsd/src/StatsService.h
index dce23768..790397f0 100644
--- a/statsd/src/StatsService.h
+++ b/statsd/src/StatsService.h
@@ -20,6 +20,7 @@
#include <aidl/android/os/BnStatsd.h>
#include <aidl/android/os/IPendingIntentRef.h>
#include <aidl/android/os/IPullAtomCallback.h>
+#include <aidl/android/util/PropertyParcel.h>
#include <gtest/gtest_prod.h>
#include <utils/Looper.h>
@@ -43,6 +44,7 @@ using Status = ::ndk::ScopedAStatus;
using aidl::android::os::BnStatsd;
using aidl::android::os::IPendingIntentRef;
using aidl::android::os::IPullAtomCallback;
+using aidl::android::util::PropertyParcel;
using ::ndk::ScopedAIBinder_DeathRecipient;
using ::ndk::ScopedFileDescriptor;
using std::shared_ptr;
@@ -72,7 +74,8 @@ public:
virtual Status informAllUidData(const ScopedFileDescriptor& fd);
virtual Status informOnePackage(const string& app, int32_t uid, int64_t version,
- const string& versionString, const string& installer);
+ const string& versionString, const string& installer,
+ const vector<uint8_t>& certificateHash);
virtual Status informOnePackageRemoved(const string& app, int32_t uid);
virtual Status informDeviceShutdown();
@@ -197,6 +200,11 @@ public:
*/
virtual Status getRegisteredExperimentIds(std::vector<int64_t>* expIdsOut);
+ /**
+ * Binder call to update properties in statsd_java namespace.
+ */
+ virtual Status updateProperties(const std::vector<PropertyParcel>& properties);
+
private:
/**
* Load system properties at init.
diff --git a/statsd/src/metrics/MetricsManager.cpp b/statsd/src/metrics/MetricsManager.cpp
index 7c8d9b79..4e577e15 100644
--- a/statsd/src/metrics/MetricsManager.cpp
+++ b/statsd/src/metrics/MetricsManager.cpp
@@ -66,6 +66,8 @@ MetricsManager::MetricsManager(const ConfigKey& key, const StatsdConfig& config,
const sp<AlarmMonitor>& periodicAlarmMonitor)
: mConfigKey(key),
mUidMap(uidMap),
+ mPackageCertificateHashSizeBytes(
+ static_cast<uint8_t>(config.package_certificate_hash_size_bytes())),
mTtlNs(config.has_ttl_in_seconds() ? config.ttl_in_seconds() * NS_PER_SEC : -1),
mTtlEndNs(-1),
mLastReportTimeNs(currentTimeNs),
@@ -166,6 +168,7 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
mWhitelistedAtomIds.insert(config.whitelisted_atom_ids().begin(),
config.whitelisted_atom_ids().end());
mShouldPersistHistory = config.persist_locally();
+ mPackageCertificateHashSizeBytes = config.package_certificate_hash_size_bytes();
// Store the sub-configs used.
mAnnotations.clear();
diff --git a/statsd/src/metrics/MetricsManager.h b/statsd/src/metrics/MetricsManager.h
index 98f2e61f..4600ae1e 100644
--- a/statsd/src/metrics/MetricsManager.h
+++ b/statsd/src/metrics/MetricsManager.h
@@ -106,6 +106,10 @@ public:
return mInstallerInReport;
};
+ inline uint8_t packageCertificateHashSizeBytes() const {
+ return mPackageCertificateHashSizeBytes;
+ }
+
void refreshTtl(const int64_t currentTimestampNs) {
if (mTtlNs > 0) {
mTtlEndNs = currentTimestampNs + mTtlNs;
@@ -169,6 +173,7 @@ private:
bool mHashStringsInReport = false;
bool mVersionStringsInReport = false;
bool mInstallerInReport = false;
+ uint8_t mPackageCertificateHashSizeBytes;
int64_t mTtlNs;
int64_t mTtlEndNs;
diff --git a/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index f1361244..c0a1efa9 100644
--- a/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -1126,6 +1126,12 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
+ ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
+ config.package_certificate_hash_size_bytes());
+ return false;
+ }
+
if (!updateAtomMatchingTrackers(config, uidMap, oldAtomMatchingTrackerMap,
oldAtomMatchingTrackers, allTagIds, newAtomMatchingTrackerMap,
newAtomMatchingTrackers, replacedMatchers)) {
diff --git a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index cde81015..0073c92e 100644
--- a/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -1363,6 +1363,12 @@ bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp
unordered_map<int64_t, int> stateAtomIdMap;
unordered_map<int64_t, unordered_map<int, int64_t>> allStateGroupMaps;
+ if (config.package_certificate_hash_size_bytes() > UINT8_MAX) {
+ ALOGE("Invalid value for package_certificate_hash_size_bytes: %d",
+ config.package_certificate_hash_size_bytes());
+ return false;
+ }
+
if (!initAtomMatchingTrackers(config, uidMap, atomMatchingTrackerMap, allAtomMatchingTrackers,
allTagIds)) {
ALOGE("initAtomMatchingTrackers failed");
diff --git a/statsd/src/packages/UidMap.cpp b/statsd/src/packages/UidMap.cpp
index 69584b58..6d5be2e6 100644
--- a/statsd/src/packages/UidMap.cpp
+++ b/statsd/src/packages/UidMap.cpp
@@ -28,12 +28,14 @@ using namespace android;
using android::base::StringPrintf;
using android::util::FIELD_COUNT_REPEATED;
using android::util::FIELD_TYPE_BOOL;
+using android::util::FIELD_TYPE_BYTES;
using android::util::FIELD_TYPE_FLOAT;
using android::util::FIELD_TYPE_INT32;
using android::util::FIELD_TYPE_INT64;
-using android::util::FIELD_TYPE_UINT64;
using android::util::FIELD_TYPE_MESSAGE;
using android::util::FIELD_TYPE_STRING;
+using android::util::FIELD_TYPE_UINT32;
+using android::util::FIELD_TYPE_UINT64;
using android::util::ProtoOutputStream;
namespace android {
@@ -49,10 +51,14 @@ 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_PACKAGE_INSTALLER_INDEX = 10;
+const int FIELD_ID_SNAPSHOT_PACKAGE_TRUNCATED_CERTIFICATE_HASH = 11;
const int FIELD_ID_SNAPSHOT_TIMESTAMP = 1;
const int FIELD_ID_SNAPSHOT_PACKAGE_INFO = 2;
const int FIELD_ID_SNAPSHOTS = 1;
const int FIELD_ID_CHANGES = 2;
+const int FIELD_ID_INSTALLER_HASH = 3;
+const int FIELD_ID_INSTALLER_NAME = 4;
const int FIELD_ID_CHANGE_DELETION = 1;
const int FIELD_ID_CHANGE_TIMESTAMP = 2;
const int FIELD_ID_CHANGE_PACKAGE = 3;
@@ -65,7 +71,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) {}
+UidMap::UidMap() : mBytesUsed(0), mIncludeCertificateHash(false) {
+}
UidMap::~UidMap() {}
@@ -114,7 +121,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>& versionString,
- const vector<String16>& packageName, const vector<String16>& installer) {
+ const vector<String16>& packageName, const vector<String16>& installer,
+ const vector<vector<uint8_t>>& certificateHash) {
wp<PackageInfoListener> broadcast = NULL;
{
lock_guard<mutex> lock(mMutex); // Exclusively lock for updates.
@@ -130,10 +138,11 @@ 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());
+ const string package = string(String8(packageName[j]).string());
+ const string installerName = string(String8(installer[j]).string());
mMap[std::make_pair(uid[j], package)] =
AppData(versionCode[j], string(String8(versionString[j]).string()),
- string(String8(installer[j]).string()));
+ installerName, certificateHash[j]);
}
for (const auto& kv : deletedApps) {
@@ -160,36 +169,36 @@ 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 String16& versionString,
- const String16& installer) {
+ const String16& installer, const vector<uint8_t>& certificateHash) {
wp<PackageInfoListener> broadcast = NULL;
- string appName = string(String8(app_16).string());
+ const string appName = string(String8(app_16).string());
+ const string installerName = string(String8(installer).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.installer = installerName;
it->second.deleted = false;
- }
- if (!found) {
- // Otherwise, we need to add an app at this uid.
- mMap[std::make_pair(uid, appName)] =
- AppData(versionCode, newVersionString, string(String8(installer).string()));
- } else {
+ it->second.certificateHash = certificateHash;
+
// 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.
// It's also OK to split again if we're forming a partial bucket after re-installing an
// app after deletion.
broadcast = mSubscriber;
+ } else {
+ // Otherwise, we need to add an app at this uid.
+ mMap[std::make_pair(uid, appName)] =
+ AppData(versionCode, newVersionString, installerName, certificateHash);
}
+
mChanges.emplace_back(false, timestamp, appName, uid, versionCode, newVersionString,
prevVersion, prevVersionString);
mBytesUsed += kBytesChangeRecord;
@@ -313,62 +322,108 @@ size_t UidMap::getBytesUsed() const {
}
void UidMap::writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings,
- bool includeInstaller, const std::set<int32_t>& interestingUids,
- std::set<string>* str_set, ProtoOutputStream* proto) {
+ bool includeInstaller, const uint8_t truncatedCertificateHashSize,
+ const std::set<int32_t>& interestingUids,
+ map<string, int>* installerIndices, std::set<string>* str_set,
+ ProtoOutputStream* proto) const {
lock_guard<mutex> lock(mMutex);
- writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller, interestingUids,
+ writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller,
+ truncatedCertificateHashSize, interestingUids, installerIndices,
str_set, proto);
}
-void UidMap::writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings,
- bool includeInstaller,
+void UidMap::writeUidMapSnapshotLocked(const int64_t timestamp, const bool includeVersionStrings,
+ const bool includeInstaller,
+ const uint8_t truncatedCertificateHashSize,
const std::set<int32_t>& interestingUids,
- std::set<string>* str_set, ProtoOutputStream* proto) {
+ map<string, int>* installerIndices,
+ std::set<string>* str_set, ProtoOutputStream* proto) const {
+ int curInstallerIndex = 0;
+
proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
- for (const auto& kv : mMap) {
- if (!interestingUids.empty() &&
- interestingUids.find(kv.first.first) == interestingUids.end()) {
+ for (const auto& [keyPair, appData] : mMap) {
+ const auto& [uid, packageName] = keyPair;
+ if (!interestingUids.empty() && interestingUids.find(uid) == interestingUids.end()) {
continue;
}
uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
FIELD_ID_SNAPSHOT_PACKAGE_INFO);
- if (str_set != nullptr) {
- str_set->insert(kv.first.second);
+ // Get installer index.
+ int installerIndex = -1;
+ if (includeInstaller && mIncludeCertificateHash && installerIndices != nullptr) {
+ const auto& it = installerIndices->find(appData.installer);
+ if (it == installerIndices->end()) {
+ // We have not encountered this installer yet; add it to installerIndices.
+ (*installerIndices)[appData.installer] = curInstallerIndex;
+ installerIndex = curInstallerIndex;
+ curInstallerIndex++;
+ } else {
+ installerIndex = it->second;
+ }
+ }
+
+ if (str_set != nullptr) { // Hash strings in report
+ str_set->insert(packageName);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
- (long long)Hash64(kv.first.second));
+ (long long)Hash64(packageName));
if (includeVersionStrings) {
- str_set->insert(kv.second.versionString);
+ str_set->insert(appData.versionString);
proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
- (long long)Hash64(kv.second.versionString));
+ (long long)Hash64(appData.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));
+ str_set->insert(appData.installer);
+ if (installerIndex != -1) {
+ // Write installer index.
+ proto->write(FIELD_TYPE_UINT32 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_INDEX,
+ installerIndex);
+ } else {
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
+ (long long)Hash64(appData.installer));
+ }
}
- } else {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
+ } else { // Strings not hashed in report
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, packageName);
if (includeVersionStrings) {
proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
- kv.second.versionString);
+ appData.versionString);
}
if (includeInstaller) {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
- kv.second.installer);
+ if (installerIndex != -1) {
+ proto->write(FIELD_TYPE_UINT32 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_INDEX,
+ installerIndex);
+ } else {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
+ appData.installer);
+ }
+ }
+ }
+
+ if (mIncludeCertificateHash) {
+ const size_t dumpHashSize =
+ truncatedCertificateHashSize <= appData.certificateHash.size()
+ ? truncatedCertificateHashSize
+ : appData.certificateHash.size();
+ if (dumpHashSize > 0) {
+ proto->write(
+ FIELD_TYPE_BYTES | FIELD_ID_SNAPSHOT_PACKAGE_TRUNCATED_CERTIFICATE_HASH,
+ reinterpret_cast<const char*>(appData.certificateHash.data()),
+ dumpHashSize);
}
}
proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
- (long long)kv.second.versionCode);
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
- proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
+ (long long)appData.versionCode);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, uid);
+ proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, appData.deleted);
proto->end(token);
}
}
-void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
- bool includeVersionStrings, bool includeInstaller,
+void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key,
+ const bool includeVersionStrings, const bool includeInstaller,
+ const uint8_t truncatedCertificateHashSize, std::set<string>* str_set,
ProtoOutputStream* proto) {
lock_guard<mutex> lock(mMutex); // Lock for updates
@@ -409,14 +464,36 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::s
}
}
+ map<string, int> installerIndices;
+
// Write snapshot from current uid map state.
uint64_t snapshotsToken =
proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller,
+ truncatedCertificateHashSize,
std::set<int32_t>() /*empty uid set means including every uid*/,
- str_set, proto);
+ &installerIndices, str_set, proto);
proto->end(snapshotsToken);
+ vector<string> installers(installerIndices.size(), "");
+ for (const auto& [installer, index] : installerIndices) {
+ // index is guaranteed to be < installers.size().
+ installers[index] = installer;
+ }
+
+ if (includeInstaller && mIncludeCertificateHash) {
+ // Write installer list; either strings or hashes.
+ for (const string& installerName : installers) {
+ if (str_set == nullptr) { // Strings not hashed
+ proto->write(FIELD_TYPE_STRING | FIELD_COUNT_REPEATED | FIELD_ID_INSTALLER_NAME,
+ installerName);
+ } else { // Strings are hashed
+ proto->write(FIELD_TYPE_UINT64 | FIELD_COUNT_REPEATED | FIELD_ID_INSTALLER_HASH,
+ (long long)Hash64(installerName));
+ }
+ }
+ }
+
int64_t prevMin = getMinimumTimestampNs();
mLastUpdatePerConfigKey[key] = timestamp;
int64_t newMin = getMinimumTimestampNs();
@@ -437,14 +514,22 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::s
StatsdStats::getInstance().setUidMapChanges(mChanges.size());
}
-void UidMap::printUidMap(int out) const {
+void UidMap::printUidMap(int out, bool includeCertificateHash) const {
lock_guard<mutex> lock(mMutex);
- for (const auto& kv : mMap) {
- if (!kv.second.deleted) {
- 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);
+ for (const auto& [keyPair, appData] : mMap) {
+ const auto& [uid, packageName] = keyPair;
+ if (!appData.deleted) {
+ if (includeCertificateHash) {
+ const string& certificateHashHexString = toHexString(appData.certificateHash);
+ dprintf(out, "%s, v%" PRId64 ", %s, %s (%i), %s\n", packageName.c_str(),
+ appData.versionCode, appData.versionString.c_str(),
+ appData.installer.c_str(), uid, certificateHashHexString.c_str());
+ } else {
+ dprintf(out, "%s, v%" PRId64 ", %s, %s (%i)\n", packageName.c_str(),
+ appData.versionCode, appData.versionString.c_str(),
+ appData.installer.c_str(), uid);
+ }
}
}
}
@@ -469,6 +554,11 @@ set<int32_t> UidMap::getAppUid(const string& package) const {
return results;
}
+void UidMap::setIncludeCertificateHash(const bool include) {
+ lock_guard<mutex> lock(mMutex);
+ mIncludeCertificateHash = include;
+}
+
// Note not all the following AIDs are used as uids. Some are used only for gids.
// It's ok to leave them in the map, but we won't ever see them in the log's uid field.
// App's uid starts from 10000, and will not overlap with the following AIDs.
diff --git a/statsd/src/packages/UidMap.h b/statsd/src/packages/UidMap.h
index aabbd4e8..e5cd2249 100644
--- a/statsd/src/packages/UidMap.h
+++ b/statsd/src/packages/UidMap.h
@@ -45,13 +45,19 @@ struct AppData {
string versionString;
string installer;
bool deleted;
+ vector<uint8_t> certificateHash;
// Empty constructor needed for unordered map.
AppData() {
}
- AppData(const int64_t v, const string& versionString, const string& installer)
- : versionCode(v), versionString(versionString), installer(installer), deleted(false){};
+ AppData(const int64_t v, const string& versionString, const string& installer,
+ const vector<uint8_t> certificateHash)
+ : versionCode(v),
+ versionString(versionString),
+ installer(installer),
+ deleted(false),
+ certificateHash(certificateHash){};
};
// When calling appendUidMap, we retrieve all the ChangeRecords since the last
@@ -92,16 +98,17 @@ public:
static sp<UidMap> getInstance();
/*
- * All three inputs must be the same size, and the jth element in each array refers to the same
- * tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
+ * All six inputs must be the same size, and the jth element in each array refers to the same
+ * tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j] etc.
*/
void updateMap(const int64_t& timestamp, const vector<int32_t>& uid,
const vector<int64_t>& versionCode, const vector<String16>& versionString,
- const vector<String16>& packageName, const vector<String16>& installer);
+ const vector<String16>& packageName, const vector<String16>& installer,
+ const vector<vector<uint8_t>>& certificateHash);
void updateApp(const int64_t& timestamp, const String16& packageName, const int32_t& uid,
const int64_t& versionCode, const String16& versionString,
- const String16& installer);
+ const String16& installer, const vector<uint8_t>& certificateHash);
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).
@@ -113,8 +120,8 @@ public:
int64_t getAppVersion(int uid, const string& packageName) const;
// Helper for debugging contents of this uid map. Can be triggered with:
- // adb shell cmd stats print-uid-map
- void printUidMap(int outFd) const;
+ // adb shell cmd stats print-uid-map [--with_certificate_hash]
+ void printUidMap(int outFd, bool includeCertificateHash) const;
// Command for indicating to the map that StatsLogProcessor should be notified if an app is
// updated. This allows metric producers and managers to distinguish when the same uid or app
@@ -136,8 +143,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,
- bool includeVersionStrings, bool includeInstaller,
+ void appendUidMap(const int64_t& timestamp, const ConfigKey& key,
+ const bool includeVersionStrings, const bool includeInstaller,
+ const uint8_t truncatedCertificateHashSize, std::set<string>* str_set,
ProtoOutputStream* proto);
// Forces the output to be cleared. We still generate a snapshot based on the current state.
@@ -156,16 +164,23 @@ public:
// str_set: if not null, add new string to the set and write str_hash to proto
// if null, write string to proto.
void writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings, bool includeInstaller,
- const std::set<int32_t>& interestingUids, std::set<string>* str_set,
- ProtoOutputStream* proto);
+ const uint8_t truncatedCertificateHashSize,
+ const std::set<int32_t>& interestingUids,
+ std::map<string, int>* installerIndices, std::set<string>* str_set,
+ ProtoOutputStream* proto) const;
+
+ void setIncludeCertificateHash(const bool include);
private:
std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const;
string normalizeAppName(const string& appName) const;
- void writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings,
- bool includeInstaller, const std::set<int32_t>& interestingUids,
- std::set<string>* str_set, ProtoOutputStream* proto);
+ void writeUidMapSnapshotLocked(const int64_t timestamp, const bool includeVersionStrings,
+ const bool includeInstaller,
+ const uint8_t truncatedCertificateHashSize,
+ const std::set<int32_t>& interestingUids,
+ std::map<string, int>* installerIndices,
+ std::set<string>* str_set, ProtoOutputStream* proto) const;
mutable mutex mMutex;
mutable mutex mIsolatedMutex;
@@ -212,6 +227,8 @@ private:
// Cache the size of mOutput;
size_t mBytesUsed;
+ bool mIncludeCertificateHash;
+
// Allows unit-test to access private methods.
FRIEND_TEST(UidMapTest, TestClearingOutput);
FRIEND_TEST(UidMapTest, TestRemovedAppRetained);
diff --git a/statsd/src/stats_log.proto b/statsd/src/stats_log.proto
index 2e4c737e..c64a9be4 100644
--- a/statsd/src/stats_log.proto
+++ b/statsd/src/stats_log.proto
@@ -352,6 +352,10 @@ message UidMapping {
optional string installer = 8;
optional uint64 installer_hash = 9;
+
+ optional uint32 installer_index = 10;
+
+ optional bytes truncated_certificate_hash = 11;
}
optional int64 elapsed_timestamp_nanos = 1;
@@ -375,6 +379,12 @@ message UidMapping {
optional uint64 prev_version_string_hash = 11;
}
repeated Change changes = 2;
+
+ // Populated when StatsdConfig.hash_strings_in_metric_reports = true
+ repeated uint64 installer_hash = 3;
+
+ // Populated when StatsdConfig.hash_strings_in_metric_reports = false
+ repeated string installer_name = 4;
}
message ConfigMetricsReport {
diff --git a/statsd/src/stats_log_util.cpp b/statsd/src/stats_log_util.cpp
index b743df54..801c0810 100644
--- a/statsd/src/stats_log_util.cpp
+++ b/statsd/src/stats_log_util.cpp
@@ -626,6 +626,16 @@ void mapIsolatedUidsToHostUidInLogEvent(const sp<UidMap> uidMap, LogEvent& event
}
}
+std::string toHexString(const vector<uint8_t>& bytes) {
+ static const char* kLookup = "0123456789ABCDEF";
+ string hex;
+ for (const uint8_t byte : bytes) {
+ hex.push_back(kLookup[(byte & 0xF0) >> 4]);
+ hex.push_back(kLookup[byte & 0x0F]);
+ }
+ return hex;
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/stats_log_util.h b/statsd/src/stats_log_util.h
index d6c181c5..d94c12b5 100644
--- a/statsd/src/stats_log_util.h
+++ b/statsd/src/stats_log_util.h
@@ -119,6 +119,8 @@ inline bool isPulledAtom(int atomId) {
void mapIsolatedUidsToHostUidInLogEvent(const sp<UidMap> uidMap, LogEvent& event);
+std::string toHexString(const vector<uint8_t>& bytes);
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/statsd/src/statsd_config.proto b/statsd/src/statsd_config.proto
index ad5c9bfb..be733b4b 100644
--- a/statsd/src/statsd_config.proto
+++ b/statsd/src/statsd_config.proto
@@ -561,6 +561,8 @@ message StatsdConfig {
repeated int32 whitelisted_atom_ids = 24;
+ optional uint32 package_certificate_hash_size_bytes = 26;
+
// Do not use.
reserved 1000, 1001;
}
diff --git a/statsd/src/subscriber/IncidentdReporter.cpp b/statsd/src/subscriber/IncidentdReporter.cpp
index 09ef325f..1e4e5515 100644
--- a/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/statsd/src/subscriber/IncidentdReporter.cpp
@@ -102,7 +102,9 @@ void getProtoData(const int64_t& rule_id, int64_t metricId, const MetricDimensio
if (!uids.empty()) {
uint64_t token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PACKAGE_INFO);
- UidMap::getInstance()->writeUidMapSnapshot(getElapsedRealtimeNs(), true, true, uids,
+ UidMap::getInstance()->writeUidMapSnapshot(getElapsedRealtimeNs(), true, true,
+ /*trucnatedCertificateHashSize*/ 0, uids,
+ nullptr /*installerIndices*/,
nullptr /*string set*/, &headerProto);
headerProto.end(token);
}
diff --git a/statsd/src/uid_data.proto b/statsd/src/uid_data.proto
index a6fa26cd..e72d4340 100644
--- a/statsd/src/uid_data.proto
+++ b/statsd/src/uid_data.proto
@@ -27,6 +27,7 @@ message ApplicationInfo {
optional string version_string = 3;
optional string package_name = 4;
optional string installer = 5;
+ optional bytes certificate_hash = 6;
}
// StatsServiceCompanion uses the proto to supply statsd with uid-package
diff --git a/statsd/tests/LogEntryMatcher_test.cpp b/statsd/tests/LogEntryMatcher_test.cpp
index 12ac5cc1..0dc18886 100644
--- a/statsd/tests/LogEntryMatcher_test.cpp
+++ b/statsd/tests/LogEntryMatcher_test.cpp
@@ -211,7 +211,8 @@ TEST(AtomMatcherTest, TestAttributionMatcher) {
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
+ android::String16(""), android::String16("")},
+ /* certificateHash */ {{}, {}, {}, {}, {}});
EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string(
@@ -364,7 +365,8 @@ TEST(AtomMatcherTest, TestUidFieldMatcher) {
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
+ android::String16(""), android::String16("")},
+ /* certificateHash */ {{}, {}, {}, {}, {}});
// Set up matcher
AtomMatcher matcher;
@@ -400,7 +402,8 @@ TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
+ android::String16(""), android::String16("")},
+ /* certificateHash */ {{}, {}, {}, {}, {}});
std::vector<int> attributionUids = {1111, 2222, 3333, 1066};
std::vector<string> attributionTags = {"location1", "location2", "location3", "location3"};
@@ -461,7 +464,8 @@ TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
{android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
{android::String16(""), android::String16(""), android::String16(""),
- android::String16(""), android::String16("")});
+ android::String16(""), android::String16("")},
+ /* certificateHash */ {{}, {}, {}, {}, {}});
std::vector<int> attributionUids = {1067, 2222, 3333, 1066};
std::vector<string> attributionTags = {"location1", "location2", "location3", "location3"};
diff --git a/statsd/tests/StatsLogProcessor_test.cpp b/statsd/tests/StatsLogProcessor_test.cpp
index d4e9e632..b3d518d8 100644
--- a/statsd/tests/StatsLogProcessor_test.cpp
+++ b/statsd/tests/StatsLogProcessor_test.cpp
@@ -163,7 +163,8 @@ TEST(StatsLogProcessorTest, TestUidMapHasSnapshot) {
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
- {String16("p1"), String16("p2")}, {String16(""), String16("")});
+ {String16("p1"), String16("p2")}, {String16(""), String16("")},
+ /* certificateHash */ {{}, {}});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;
@@ -194,7 +195,8 @@ TEST(StatsLogProcessorTest, TestEmptyConfigHasNoUidMap) {
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
- {String16("p1"), String16("p2")}, {String16(""), String16("")});
+ {String16("p1"), String16("p2")}, {String16(""), String16("")},
+ /* certificateHash */ {{}, {}});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
int broadcastCount = 0;
@@ -328,7 +330,8 @@ TEST(StatsLogProcessorTest, InvalidConfigRemoved) {
sp<UidMap> m = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
m->updateMap(1, {1, 2}, {1, 2}, {String16("v1"), String16("v2")},
- {String16("p1"), String16("p2")}, {String16(""), String16("")});
+ {String16("p1"), String16("p2")}, {String16(""), String16("")},
+ /* certificateHash */ {{}, {}});
sp<AlarmMonitor> anomalyAlarmMonitor;
sp<AlarmMonitor> subscriberAlarmMonitor;
StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
diff --git a/statsd/tests/UidMap_test.cpp b/statsd/tests/UidMap_test.cpp
index 33bdc643..25305f7b 100644
--- a/statsd/tests/UidMap_test.cpp
+++ b/statsd/tests/UidMap_test.cpp
@@ -64,23 +64,15 @@ TEST(UidMapTest, TestIsolatedUID) {
TEST(UidMapTest, TestMatching) {
UidMap m;
- 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, versionStrings, apps, installers);
+ const vector<int32_t> uids{1000, 1000};
+ const vector<int64_t> versions{4, 5};
+ const vector<String16> versionStrings{String16("v1"), String16("v1")};
+ const vector<String16> apps{String16(kApp1.c_str()), String16(kApp2.c_str())};
+ const vector<String16> installers{String16(""), String16("")};
+ const vector<vector<uint8_t>> certificateHashes{{}, {}};
+
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
EXPECT_TRUE(m.hasApp(1000, kApp1));
EXPECT_TRUE(m.hasApp(1000, kApp2));
EXPECT_FALSE(m.hasApp(1000, "not.app"));
@@ -96,23 +88,15 @@ TEST(UidMapTest, TestMatching) {
TEST(UidMapTest, TestAddAndRemove) {
UidMap m;
- vector<int32_t> uids;
- vector<int64_t> versions;
- vector<String16> apps;
- vector<String16> versionStrings;
- vector<String16> installers;
+ const vector<int32_t> uids{1000, 1000};
+ const vector<int64_t> versions{4, 5};
+ const vector<String16> versionStrings{String16("v1"), String16("v1")};
+ const vector<String16> apps{String16(kApp1.c_str()), String16(kApp2.c_str())};
+ const vector<String16> installers{String16(""), String16("")};
+ const vector<vector<uint8_t>> certificateHashes{{}, {}};
- 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, versionStrings, apps, installers);
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
ASSERT_EQ(name_set.size(), 2u);
@@ -120,7 +104,8 @@ 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, String16("v40"), String16(""));
+ m.updateApp(2, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""),
+ /* certificateHash */ {});
EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
@@ -147,14 +132,16 @@ TEST(UidMapTest, TestAddAndRemove) {
TEST(UidMapTest, TestUpdateApp) {
UidMap m;
m.updateMap(1, {1000, 1000}, {4, 5}, {String16("v4"), String16("v5")},
- {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")});
+ {String16(kApp1.c_str()), String16(kApp2.c_str())}, {String16(""), String16("")},
+ /* certificateHash */ {{}, {}});
std::set<string> name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
ASSERT_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, String16("v40"), String16(""));
+ m.updateApp(2, String16("NeW_aPP1_NAmE"), 1000, 40, String16("v40"), String16(""),
+ /* certificateHash */ {});
name_set = m.getAppNamesFromUid(1000, true /* returnNormalized */);
ASSERT_EQ(name_set.size(), 3u);
EXPECT_TRUE(name_set.find(kApp1) != name_set.end());
@@ -163,7 +150,8 @@ 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, String16("v1"), String16(""));
+ m.updateApp(3, String16("NeW_aPP1_NAmE"), 2000, 1, String16("v1"), String16(""),
+ /* certificateHash */ {});
name_set = m.getAppNamesFromUid(2000, true /* returnNormalized */);
ASSERT_EQ(name_set.size(), 1u);
EXPECT_TRUE(name_set.find("NeW_aPP1_NAmE") == name_set.end());
@@ -191,23 +179,23 @@ TEST(UidMapTest, TestOutputIncludesAtLeastOneSnapshot) {
// Initialize single config key.
ConfigKey config1(1, StringToId("config1"));
m.OnConfigUpdated(config1);
- 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, versionStrings, apps, installers);
+ const vector<int32_t> uids{1000};
+ const vector<int64_t> versions{5};
+ const vector<String16> versionStrings{String16("v1")};
+ const vector<String16> apps{String16(kApp2.c_str())};
+ const vector<String16> installers{String16("")};
+ const vector<vector<uint8_t>> certificateHashes{{}};
+
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
// Set the last timestamp for this config key to be newer.
m.mLastUpdatePerConfigKey[config1] = 2;
ProtoOutputStream proto;
- m.appendUidMap(3, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 3, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
// Check there's still a uidmap attached this one.
UidMapping results;
@@ -221,21 +209,21 @@ TEST(UidMapTest, TestRemovedAppRetained) {
// Initialize single config key.
ConfigKey config1(1, StringToId("config1"));
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);
- versionStrings.push_back(String16("v5"));
- installers.push_back(String16(""));
- m.updateMap(1, uids, versions, versionStrings, apps, installers);
+ const vector<int32_t> uids{1000};
+ const vector<int64_t> versions{5};
+ const vector<String16> versionStrings{String16("v5")};
+ const vector<String16> apps{String16(kApp2.c_str())};
+ const vector<String16> installers{String16("")};
+ const vector<vector<uint8_t>> certificateHashes{{}};
+
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
m.removeApp(2, String16(kApp2.c_str()), 1000);
ProtoOutputStream proto;
- m.appendUidMap(3, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 3, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
// Snapshot should still contain this item as deleted.
UidMapping results;
@@ -254,6 +242,7 @@ TEST(UidMapTest, TestRemovedAppOverGuardrail) {
vector<String16> versionStrings;
vector<String16> installers;
vector<String16> apps;
+ vector<vector<uint8_t>> certificateHashes;
const int maxDeletedApps = StatsdStats::kMaxDeletedAppsInUidMap;
for (int j = 0; j < maxDeletedApps + 10; j++) {
uids.push_back(j);
@@ -261,24 +250,31 @@ TEST(UidMapTest, TestRemovedAppOverGuardrail) {
versions.push_back(j);
versionStrings.push_back(String16("v"));
installers.push_back(String16(""));
+ certificateHashes.push_back({});
}
- m.updateMap(1, uids, versions, versionStrings, apps, installers);
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
// First, verify that we have the expected number of items.
UidMapping results;
ProtoOutputStream proto;
- m.appendUidMap(3, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 3, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_EQ(maxDeletedApps + 10, results.snapshots(0).package_info_size());
// Now remove all the apps.
- m.updateMap(1, uids, versions, versionStrings, apps, installers);
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
for (int j = 0; j < maxDeletedApps + 10; j++) {
m.removeApp(4, String16(kApp1.c_str()), j);
}
proto.clear();
- m.appendUidMap(5, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 5, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
// Snapshot drops the first nine items.
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_EQ(maxDeletedApps, results.snapshots(0).package_info_size());
@@ -292,60 +288,64 @@ TEST(UidMapTest, TestClearingOutput) {
m.OnConfigUpdated(config1);
- 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);
- apps.push_back(String16(kApp1.c_str()));
- apps.push_back(String16(kApp2.c_str()));
- versions.push_back(4);
- versions.push_back(5);
- 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);
+ const vector<int32_t> uids{1000, 1000};
+ const vector<int64_t> versions{4, 5};
+ const vector<String16> versionStrings{String16("v4"), String16("v5")};
+ const vector<String16> apps{String16(kApp1.c_str()), String16(kApp2.c_str())};
+ const vector<String16> installers{String16(""), String16("")};
+ const vector<vector<uint8_t>> certificateHashes{{}, {}};
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
ProtoOutputStream proto;
- m.appendUidMap(2, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 2, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
UidMapping results;
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_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, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 2, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_EQ(1, results.snapshots_size());
// Now add another configuration.
m.OnConfigUpdated(config2);
- m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""));
+ m.updateApp(5, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""),
+ /* certificateHash */ {});
ASSERT_EQ(1U, m.mChanges.size());
proto.clear();
- m.appendUidMap(6, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 6, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_EQ(1, results.snapshots_size());
ASSERT_EQ(1, results.changes_size());
ASSERT_EQ(1U, m.mChanges.size());
// Add another delta update.
- m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""));
+ m.updateApp(7, String16(kApp2.c_str()), 1001, 41, String16("v41"), String16(""),
+ /* certificateHash */ {});
ASSERT_EQ(2U, m.mChanges.size());
// We still can't remove anything.
proto.clear();
- m.appendUidMap(8, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 8, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_EQ(1, results.snapshots_size());
ASSERT_EQ(1, results.changes_size());
ASSERT_EQ(2U, m.mChanges.size());
proto.clear();
- m.appendUidMap(9, config2, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 9, config2, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
protoOutputStreamToUidMapping(&proto, &results);
ASSERT_EQ(1, results.snapshots_size());
ASSERT_EQ(2, results.changes_size());
@@ -360,26 +360,28 @@ TEST(UidMapTest, TestMemoryComputed) {
m.OnConfigUpdated(config1);
size_t startBytes = m.mBytesUsed;
- 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);
- 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, String16("v40"), String16(""));
+ const vector<int32_t> uids{1000};
+ const vector<int64_t> versions{1};
+ const vector<String16> versionStrings{String16("v1")};
+ const vector<String16> apps{String16(kApp1.c_str())};
+ const vector<String16> installers{String16("")};
+ const vector<vector<uint8_t>> certificateHashes{{}};
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
+
+ m.updateApp(3, String16(kApp1.c_str()), 1000, 40, String16("v40"), String16(""),
+ /* certificateHash */ {});
ProtoOutputStream proto;
vector<uint8_t> bytes;
- m.appendUidMap(2, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 2, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
size_t prevBytes = m.mBytesUsed;
- m.appendUidMap(4, config1, nullptr, true, true, &proto);
+ m.appendUidMap(/* timestamp */ 4, config1, /* includeVersionStrings */ true,
+ /* includeInstaller */ true, /* truncatedCertificateHashSize */ 0,
+ /* str_set */ nullptr, &proto);
EXPECT_TRUE(m.mBytesUsed < prevBytes);
}
@@ -396,6 +398,7 @@ TEST(UidMapTest, TestMemoryGuardrail) {
vector<String16> versionStrings;
vector<String16> installers;
vector<String16> apps;
+ vector<vector<uint8_t>> certificateHashes;
for (int i = 0; i < 100; i++) {
uids.push_back(1);
buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
@@ -403,17 +406,19 @@ TEST(UidMapTest, TestMemoryGuardrail) {
versions.push_back(1);
versionStrings.push_back(String16("v1"));
installers.push_back(String16(""));
+ certificateHashes.push_back({});
}
- m.updateMap(1, uids, versions, versionStrings, apps, installers);
+ m.updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2,
- String16("v2"), String16(""));
+ String16("v2"), String16(""), /* certificateHash */ {});
ASSERT_EQ(1U, m.mChanges.size());
// Now force deletion by limiting the memory to hold one delta change.
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(""));
+ String16("v4"), String16(""), /* certificateHash */ {});
ASSERT_EQ(1U, m.mChanges.size());
}
diff --git a/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 8b0babb8..fd6ebde1 100644
--- a/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -432,7 +432,8 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket) {
int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
service->mUidMap->updateMap(bucketStartTimeNs, {1}, {1}, {String16("v1")},
- {String16("randomApp")}, {String16("")});
+ {String16("randomApp")}, {String16("")},
+ /* certificateHash */ {{}});
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -468,7 +469,7 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_partial_bucket) {
// Partial bucket split.
int64_t appUpgradeTimeNs = bucketStartTimeNs + 500;
service->mUidMap->updateApp(appUpgradeTimeNs, String16("randomApp"), 1, 2, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns) / NS_PER_SEC + 1,
diff --git a/statsd/tests/e2e/Attribution_e2e_test.cpp b/statsd/tests/e2e/Attribution_e2e_test.cpp
index 4c2caa90..f4305bd7 100644
--- a/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -110,7 +110,8 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")},
- {String16(""), String16(""), String16(""), String16("")});
+ {String16(""), String16(""), String16(""), String16("")},
+ /* certificateHash */ {{}, {}, {}, {}});
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.
@@ -223,7 +224,8 @@ TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
{String16("v1"), String16("v1"), String16("v2"), String16("v2")},
{String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
String16("APP3")},
- {String16(""), String16(""), String16(""), String16("")});
+ {String16(""), String16(""), String16(""), String16("")},
+ /* certificateHash */ {{}, {}, {}, {}});
std::vector<std::unique_ptr<LogEvent>> events;
// Events 1~4 are in the 1st bucket.
diff --git a/statsd/tests/e2e/ConfigUpdate_e2e_ab_test.cpp b/statsd/tests/e2e/ConfigUpdate_e2e_ab_test.cpp
index 7d6d28c6..92955bb7 100644
--- a/statsd/tests/e2e/ConfigUpdate_e2e_ab_test.cpp
+++ b/statsd/tests/e2e/ConfigUpdate_e2e_ab_test.cpp
@@ -59,12 +59,14 @@ INSTANTIATE_TEST_SUITE_P(ConfigUpdateE2eAbTest, ConfigUpdateE2eAbTest, testing::
TEST_P(ConfigUpdateE2eAbTest, TestUidMapVersionStringInstaller) {
sp<UidMap> uidMap = new UidMap();
- vector<int32_t> uids({1000});
- vector<int64_t> versions({1});
- vector<String16> apps({String16("app1")});
- vector<String16> versionStrings({String16("v1")});
- vector<String16> installers({String16("installer1")});
- uidMap->updateMap(1, uids, versions, versionStrings, apps, installers);
+ const vector<int32_t> uids{1000};
+ const vector<int64_t> versions{1};
+ const vector<String16> apps{String16("app1")};
+ const vector<String16> versionStrings{String16("v1")};
+ const vector<String16> installers{String16("installer1")};
+ const vector<vector<uint8_t>> certificateHashes{{}};
+ uidMap->updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
StatsdConfig config = CreateSimpleConfig();
config.set_version_strings_in_metric_report(true);
@@ -101,12 +103,14 @@ TEST_P(ConfigUpdateE2eAbTest, TestUidMapVersionStringInstaller) {
TEST_P(ConfigUpdateE2eAbTest, TestHashStrings) {
sp<UidMap> uidMap = new UidMap();
- vector<int32_t> uids({1000});
- vector<int64_t> versions({1});
- vector<String16> apps({String16("app1")});
- vector<String16> versionStrings({String16("v1")});
- vector<String16> installers({String16("installer1")});
- uidMap->updateMap(1, uids, versions, versionStrings, apps, installers);
+ const vector<int32_t> uids{1000};
+ const vector<int64_t> versions{1};
+ const vector<String16> apps{String16("app1")};
+ const vector<String16> versionStrings{String16("v1")};
+ const vector<String16> installers{String16("installer1")};
+ const vector<vector<uint8_t>> certificateHashes{{}};
+ uidMap->updateMap(1 /* timestamp */, uids, versions, versionStrings, apps, installers,
+ certificateHashes);
StatsdConfig config = CreateSimpleConfig();
config.set_version_strings_in_metric_report(true);
diff --git a/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 80c0e377..fe2bdcfa 100644
--- a/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -147,7 +147,7 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
// 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, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
@@ -162,12 +162,12 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
- {String16("")});
+ {String16("")}, /* certificateHash */ {{}});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
// Goes into the second bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
@@ -196,7 +196,7 @@ TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
- {String16("")});
+ {String16("")}, /* certificateHash */ {{}});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
@@ -259,12 +259,12 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnUpgradeWhenDisabled) {
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
- {String16("")});
+ {String16("")}, /* certificateHash */ {{}});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
// Still goes into the first bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());
@@ -286,7 +286,8 @@ TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
- service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
+ service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
+ /* certificateHash */ {});
SendConfig(service, MakeValueMetricConfig(0));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -294,7 +295,7 @@ TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
int64_t appUpgradeTimeNs = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
service->mUidMap->updateApp(appUpgradeTimeNs, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
ConfigMetricsReport report =
GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
@@ -316,7 +317,8 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
- service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
+ service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
+ /* certificateHash */ {});
SendConfig(service, MakeValueMetricConfig(60 * NS_PER_SEC /* One minute */));
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
@@ -324,7 +326,7 @@ TEST(PartialBucketE2eTest, TestValueMetricWithMinPartialBucket) {
const int64_t endSkipped = 5 * 60 * NS_PER_SEC + start + 2 * NS_PER_SEC;
service->mProcessor->informPullAlarmFired(5 * 60 * NS_PER_SEC + start);
service->mUidMap->updateApp(endSkipped, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
ConfigMetricsReport report =
GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
@@ -380,14 +382,15 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
// Partial buckets don't occur when app is first installed.
- service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
+ service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
+ /* certificateHash */ {});
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,
- String16("v2"), String16(""));
+ String16("v2"), String16(""), /* certificateHash */ {});
ConfigMetricsReport report = GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100);
backfillStartEndTimestamp(&report);
@@ -401,7 +404,8 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket) {
TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
// Partial buckets don't occur when app is first installed.
- service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""));
+ service->mUidMap->updateApp(1, String16(kApp1.c_str()), 1, 1, String16("v1"), String16(""),
+ /* certificateHash */ {});
service->mPullerManager->RegisterPullAtomCallback(
/*uid=*/0, util::SUBSYSTEM_SLEEP_STATE, NS_PER_SEC, NS_PER_SEC * 10, {},
SharedRefBase::make<FakeSubsystemSleepCallback>());
@@ -412,7 +416,7 @@ TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket) {
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, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
ConfigMetricsReport report =
GetReports(service->mProcessor, 5 * 60 * NS_PER_SEC + start + 100 * NS_PER_SEC);
@@ -464,12 +468,12 @@ TEST(PartialBucketE2eTest, TestCountMetricNoSplitByDefault) {
int64_t start = getElapsedRealtimeNs(); // This is the start-time the metrics producers are
// initialized with.
service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
- {String16("")});
+ {String16("")}, /* certificateHash */ {{}});
// Force the uidmap to update at timestamp 2.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 1, 100).get());
service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
- String16(""));
+ String16(""), /* certificateHash */ {});
// Still goes into the first bucket.
service->mProcessor->OnLogEvent(CreateAppCrashEvent(start + 3, 100).get());