diff --git a/core/api/current.txt b/core/api/current.txt
index 84b635ae78c09..c1c4c92237dbb 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8013,6 +8013,9 @@ package android.app.admin {
field public static final int TAG_MEDIA_UNMOUNT = 210014; // 0x3345e
field public static final int TAG_OS_SHUTDOWN = 210010; // 0x3345a
field public static final int TAG_OS_STARTUP = 210009; // 0x33459
+ field public static final int TAG_PACKAGE_INSTALLED = 210041; // 0x33479
+ field public static final int TAG_PACKAGE_UNINSTALLED = 210043; // 0x3347b
+ field public static final int TAG_PACKAGE_UPDATED = 210042; // 0x3347a
field public static final int TAG_PASSWORD_CHANGED = 210036; // 0x33474
field public static final int TAG_PASSWORD_COMPLEXITY_REQUIRED = 210035; // 0x33473
field public static final int TAG_PASSWORD_COMPLEXITY_SET = 210017; // 0x33461
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 904db5f86c029..ca2e97edc4322 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -96,6 +96,9 @@ public class SecurityLog {
TAG_WIFI_DISCONNECTION,
TAG_BLUETOOTH_CONNECTION,
TAG_BLUETOOTH_DISCONNECTION,
+ TAG_PACKAGE_INSTALLED,
+ TAG_PACKAGE_UPDATED,
+ TAG_PACKAGE_UNINSTALLED,
})
public @interface SecurityLogTag {}
@@ -562,6 +565,39 @@ public class SecurityLog {
public static final int TAG_BLUETOOTH_DISCONNECTION =
SecurityLogTags.SECURITY_BLUETOOTH_DISCONNECTION;
+ /**
+ * Indicates that a package is installed.
+ * The log entry contains the following information about the
+ * event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ *
[0] Name of the package being installed ({@code String})
+ * [1] Package version code ({@code Long})
+ * [2] UserId of the user that installed this package ({@code Integer})
+ */
+ public static final int TAG_PACKAGE_INSTALLED = SecurityLogTags.SECURITY_PACKAGE_INSTALLED;
+
+ /**
+ * Indicates that a package is updated.
+ * The log entry contains the following information about the
+ * event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * [0] Name of the package being updated ({@code String})
+ * [1] Package version code ({@code Long})
+ * [2] UserId of the user that updated this package ({@code Integer})
+ */
+ public static final int TAG_PACKAGE_UPDATED = SecurityLogTags.SECURITY_PACKAGE_UPDATED;
+
+ /**
+ * Indicates that a package is uninstalled.
+ * The log entry contains the following information about the
+ * event, encapsulated in an {@link Object} array and accessible via
+ * {@link SecurityEvent#getData()}:
+ * [0] Name of the package being uninstalled ({@code String})
+ * [1] Package version code ({@code Long})
+ * [2] UserId of the user that uninstalled this package ({@code Integer})
+ */
+ public static final int TAG_PACKAGE_UNINSTALLED = SecurityLogTags.SECURITY_PACKAGE_UNINSTALLED;
+
/**
* Event severity level indicating that the event corresponds to normal workflow.
*/
@@ -772,6 +808,9 @@ public class SecurityLog {
break;
case SecurityLog.TAG_CERT_AUTHORITY_INSTALLED:
case SecurityLog.TAG_CERT_AUTHORITY_REMOVED:
+ case SecurityLog.TAG_PACKAGE_INSTALLED:
+ case SecurityLog.TAG_PACKAGE_UPDATED:
+ case SecurityLog.TAG_PACKAGE_UNINSTALLED:
try {
userId = getIntegerData(2);
} catch (Exception e) {
diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
index b06e5a5849fdb..e4af8dd915836 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -44,4 +44,7 @@ option java_package android.app.admin
210037 security_wifi_connection (bssid|3),(event_type|3),(reason|3)
210038 security_wifi_disconnection (bssid|3),(reason|3)
210039 security_bluetooth_connection (addr|3),(success|1),(reason|3)
-210040 security_bluetooth_disconnection (addr|3),(reason|3)
\ No newline at end of file
+210040 security_bluetooth_disconnection (addr|3),(reason|3)
+210041 security_package_installed (package_name|3),(version_code|1),(user_id|1)
+210042 security_package_updated (package_name|3),(version_code|1),(user_id|1)
+210043 security_package_uninstalled (package_name|3),(version_code|1),(user_id|1)
\ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index 6998db76e338f..a6def7d616378 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -261,7 +261,7 @@ final class DeletePackageHelper {
final boolean killApp = (deleteFlags & PackageManager.DELETE_DONT_KILL_APP) == 0;
info.sendPackageRemovedBroadcasts(killApp, removedBySystem);
info.sendSystemPackageUpdatedBroadcasts();
- PackageMetrics.onUninstallSucceeded(info, deleteFlags, mUserManagerInternal);
+ PackageMetrics.onUninstallSucceeded(info, deleteFlags, userId);
}
// Force a gc to clear up things.
@@ -550,6 +550,7 @@ final class DeletePackageHelper {
outInfo.mRemovedUsers = userIds;
outInfo.mBroadcastUsers = userIds;
outInfo.mIsExternal = ps.isExternalStorage();
+ outInfo.mRemovedPackageVersionCode = ps.getVersionCode();
}
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 7553370bf4c62..61052f59c93bc 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1608,6 +1608,7 @@ final class InstallPackageHelper {
ps.getUninstallReason(userId));
}
removedInfo.mIsExternal = oldPackage.isExternalStorage();
+ removedInfo.mRemovedPackageVersionCode = oldPackage.getLongVersionCode();
request.setRemovedInfo(removedInfo);
sysPkg = oldPackage.isSystem();
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index 5974a9cbab676..c6cdc4cd350d2 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -773,10 +773,10 @@ final class InstallRequest {
}
}
- public void onInstallCompleted() {
+ public void onInstallCompleted(int userId) {
if (getReturnCode() == INSTALL_SUCCEEDED) {
if (mPackageMetrics != null) {
- mPackageMetrics.onInstallSucceed();
+ mPackageMetrics.onInstallSucceed(userId);
}
}
}
diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java
index 2b6398af348e7..b600aa80b3882 100644
--- a/services/core/java/com/android/server/pm/InstallingSession.java
+++ b/services/core/java/com/android/server/pm/InstallingSession.java
@@ -535,7 +535,7 @@ class InstallingSession {
mInstallPackageHelper.installPackagesTraced(installRequests);
for (InstallRequest request : installRequests) {
- request.onInstallCompleted();
+ request.onInstallCompleted(mUser.getIdentifier());
doPostInstall(request);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cf59a1e248e04..91f7011c90c71 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3078,6 +3078,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
info.mRemovedUsers = new int[] {userId};
info.mBroadcastUsers = new int[] {userId};
info.mUid = UserHandle.getUid(userId, packageState.getAppId());
+ info.mRemovedPackageVersionCode = packageState.getVersionCode();
info.sendPackageRemovedBroadcasts(true /*killApp*/, false /*removedBySystem*/);
}
diff --git a/services/core/java/com/android/server/pm/PackageMetrics.java b/services/core/java/com/android/server/pm/PackageMetrics.java
index 81f1a987c0a4f..8252a9fa65c5f 100644
--- a/services/core/java/com/android/server/pm/PackageMetrics.java
+++ b/services/core/java/com/android/server/pm/PackageMetrics.java
@@ -19,6 +19,7 @@ package com.android.server.pm;
import static android.os.Process.INVALID_UID;
import android.annotation.IntDef;
+import android.app.admin.SecurityLog;
import android.content.pm.PackageManager;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.util.Pair;
@@ -67,8 +68,8 @@ final class PackageMetrics {
mInstallRequest = installRequest;
}
- public void onInstallSucceed() {
- // TODO(b/239722919): report to SecurityLog if on work profile or managed device
+ public void onInstallSucceed(int userId) {
+ reportInstallationToSecurityLog(userId);
reportInstallationStats(true /* success */);
}
@@ -77,8 +78,13 @@ final class PackageMetrics {
}
private void reportInstallationStats(boolean success) {
- UserManagerInternal userManagerInternal =
+ final UserManagerInternal userManagerInternal =
LocalServices.getService(UserManagerInternal.class);
+ if (userManagerInternal == null) {
+ // UserManagerService is not available. Skip metrics reporting.
+ return;
+ }
+
final long installDurationMillis =
System.currentTimeMillis() - mInstallStartTimestampMillis;
// write to stats
@@ -196,12 +202,17 @@ final class PackageMetrics {
}
}
- public static void onUninstallSucceeded(PackageRemovedInfo info, int deleteFlags,
- UserManagerInternal userManagerInternal) {
+ public static void onUninstallSucceeded(PackageRemovedInfo info, int deleteFlags, int userId) {
if (info.mIsUpdate) {
// Not logging uninstalls caused by app updates
return;
}
+ final UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ if (userManagerInternal == null) {
+ // UserManagerService is not available. Skip metrics reporting.
+ return;
+ }
final int[] removedUsers = info.mRemovedUsers;
final int[] removedUserTypes = userManagerInternal.getUserTypesForStatsd(removedUsers);
final int[] originalUsers = info.mOrigUsers;
@@ -210,6 +221,9 @@ final class PackageMetrics {
info.mUid, removedUsers, removedUserTypes, originalUsers, originalUserTypes,
deleteFlags, PackageManager.DELETE_SUCCEEDED, info.mIsRemovedPackageSystemUpdate,
!info.mRemovedForAllUsers);
+ final String packageName = info.mRemovedPackage;
+ final long versionCode = info.mRemovedPackageVersionCode;
+ reportUninstallationToSecurityLog(packageName, versionCode, userId);
}
public static void onVerificationFailed(VerifyingSession verifyingSession) {
@@ -242,4 +256,32 @@ final class PackageMetrics {
verifyingSession.isStaged() /* is_staged */
);
}
+
+ private void reportInstallationToSecurityLog(int userId) {
+ if (!SecurityLog.isLoggingEnabled()) {
+ return;
+ }
+ final PackageSetting ps = mInstallRequest.getScannedPackageSetting();
+ if (ps == null) {
+ return;
+ }
+ final String packageName = ps.getPackageName();
+ final long versionCode = ps.getVersionCode();
+ if (!mInstallRequest.isInstallReplace()) {
+ SecurityLog.writeEvent(SecurityLog.TAG_PACKAGE_INSTALLED, packageName, versionCode,
+ userId);
+ } else {
+ SecurityLog.writeEvent(SecurityLog.TAG_PACKAGE_UPDATED, packageName, versionCode,
+ userId);
+ }
+ }
+
+ private static void reportUninstallationToSecurityLog(String packageName, long versionCode,
+ int userId) {
+ if (!SecurityLog.isLoggingEnabled()) {
+ return;
+ }
+ SecurityLog.writeEvent(SecurityLog.TAG_PACKAGE_UNINSTALLED, packageName, versionCode,
+ userId);
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageRemovedInfo.java b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
index dd580a5e43aac..c762fd3f9648b 100644
--- a/services/core/java/com/android/server/pm/PackageRemovedInfo.java
+++ b/services/core/java/com/android/server/pm/PackageRemovedInfo.java
@@ -51,6 +51,7 @@ final class PackageRemovedInfo {
boolean mRemovedForAllUsers;
boolean mIsStaticSharedLib;
boolean mIsExternal;
+ long mRemovedPackageVersionCode;
// a two dimensional array mapping userId to the set of appIds that can receive notice
// of package changes
SparseArray mBroadcastAllowList;
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 8c58397fb1a1a..41985e3890feb 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -275,6 +275,7 @@ final class RemovePackageHelper {
outInfo.populateUsers(deletedPs.queryInstalledUsers(
mUserManagerInternal.getUserIds(), true), deletedPs);
outInfo.mIsExternal = deletedPs.isExternalStorage();
+ outInfo.mRemovedPackageVersionCode = deletedPs.getVersionCode();
}
removePackageLI(deletedPs.getPackageName(), (flags & PackageManager.DELETE_CHATTY) != 0);