diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-12 13:55:22 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-12 13:55:22 +0000 |
commit | 4de2bef389636303f9d4ad0f181af802fc7e7f24 (patch) | |
tree | 02120d2f84a37aadd571d579f2feba88fff16477 | |
parent | 9061fe2567f7c37992753ba08adb29d1590e59db (diff) | |
parent | 2e72e87f6068f2b0362549dc5934a2dba044676b (diff) | |
download | StatsD-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
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()); |