Merge "Add install reason"
diff --git a/api/current.txt b/api/current.txt
index ec0faf4..afaec20 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9944,6 +9944,7 @@
method public void setAppLabel(java.lang.CharSequence);
method public void setAppPackageName(java.lang.String);
method public void setInstallLocation(int);
+ method public void setInstallReason(int);
method public void setOriginatingUid(int);
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
@@ -10177,6 +10178,8 @@
field public static final int GET_SIGNATURES = 64; // 0x40
field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+ field public static final int INSTALL_REASON_POLICY = 1; // 0x1
+ field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
field public static final int MATCH_ALL = 131072; // 0x20000
field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
diff --git a/api/system-current.txt b/api/system-current.txt
index 8827279..bb89c65 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10365,6 +10365,7 @@
method public void setGrantedRuntimePermissions(java.lang.String[]);
method public void setInstallAsInstantApp(boolean);
method public void setInstallLocation(int);
+ method public void setInstallReason(int);
method public void setOriginatingUid(int);
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
@@ -10653,6 +10654,8 @@
field public static final int INSTALL_PARSE_FAILED_NOT_APK = -100; // 0xffffff9c
field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
+ field public static final int INSTALL_REASON_POLICY = 1; // 0x1
+ field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
field public static final int INSTALL_SUCCEEDED = 1; // 0x1
field public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1; // 0xffffffff
field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index dcc693a..c0b240a 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -9972,6 +9972,7 @@
method public void setAppLabel(java.lang.CharSequence);
method public void setAppPackageName(java.lang.String);
method public void setInstallLocation(int);
+ method public void setInstallReason(int);
method public void setOriginatingUid(int);
method public void setOriginatingUri(android.net.Uri);
method public void setReferrerUri(android.net.Uri);
@@ -10044,6 +10045,7 @@
method public abstract android.graphics.drawable.Drawable getDefaultActivityIcon();
method public abstract java.lang.String getDefaultBrowserPackageNameAsUser(int);
method public abstract android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
+ method public abstract int getInstallReason(java.lang.String, android.os.UserHandle);
method public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public abstract java.lang.String getInstallerPackageName(java.lang.String);
@@ -10206,6 +10208,8 @@
field public static final int GET_SIGNATURES = 64; // 0x40
field public static final deprecated int GET_UNINSTALLED_PACKAGES = 8192; // 0x2000
field public static final int GET_URI_PERMISSION_PATTERNS = 2048; // 0x800
+ field public static final int INSTALL_REASON_POLICY = 1; // 0x1
+ field public static final int INSTALL_REASON_UNKNOWN = 0; // 0x0
field public static final int MATCH_ALL = 131072; // 0x20000
field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
field public static final int MATCH_DIRECT_BOOT_AWARE = 524288; // 0x80000
@@ -39123,6 +39127,7 @@
method public android.graphics.drawable.Drawable getDefaultActivityIcon();
method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
method public android.graphics.drawable.Drawable getDrawable(java.lang.String, int, android.content.pm.ApplicationInfo);
+ method public int getInstallReason(java.lang.String, android.os.UserHandle);
method public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
method public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
method public java.lang.String getInstallerPackageName(java.lang.String);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index aedcdce..f3185a8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1635,7 +1635,8 @@
public int installExistingPackageAsUser(String packageName, int userId)
throws NameNotFoundException {
try {
- int res = mPM.installExistingPackageAsUser(packageName, userId);
+ int res = mPM.installExistingPackageAsUser(packageName, userId,
+ PackageManager.INSTALL_REASON_UNKNOWN);
if (res == INSTALL_FAILED_INVALID_URI) {
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
}
@@ -2411,6 +2412,18 @@
return getUserManager().isManagedProfile(userId);
}
+ /**
+ * @hide
+ */
+ @Override
+ public int getInstallReason(String packageName, UserHandle user) {
+ try {
+ return mPM.getInstallReason(packageName, user.getIdentifier());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** {@hide} */
private static class MoveCallbackDelegate extends IPackageMoveObserver.Stub implements
Handler.Callback {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index eb0ca2e..19cca8e 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -523,7 +523,7 @@
boolean setInstallLocation(int loc);
int getInstallLocation();
- int installExistingPackageAsUser(String packageName, int userId);
+ int installExistingPackageAsUser(String packageName, int userId, int installReason);
void verifyPendingInstall(int id, int verificationCode);
void extendVerificationTimeout(int id, int verificationCodeAtTimeout, long millisecondsToDelay);
@@ -584,4 +584,6 @@
boolean isPackageDeviceAdminOnAnyUser(String packageName);
List<String> getPreviousCodePaths(in String packageName);
+
+ int getInstallReason(String packageName, int userId);
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 646bd3c..db3f637 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -881,6 +881,8 @@
/** {@hide} */
public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
/** {@hide} */
+ public int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
+ /** {@hide} */
public long sizeBytes = -1;
/** {@hide} */
public String appPackageName;
@@ -919,6 +921,7 @@
mode = source.readInt();
installFlags = source.readInt();
installLocation = source.readInt();
+ installReason = source.readInt();
sizeBytes = source.readLong();
appPackageName = source.readString();
appIcon = source.readParcelable(null);
@@ -1076,6 +1079,10 @@
}
}
+ public void setInstallReason(int installReason) {
+ this.installReason = installReason;
+ }
+
/** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
@@ -1104,6 +1111,7 @@
dest.writeInt(mode);
dest.writeInt(installFlags);
dest.writeInt(installLocation);
+ dest.writeInt(installReason);
dest.writeLong(sizeBytes);
dest.writeString(appPackageName);
dest.writeParcelable(appIcon, flags);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0cd67b7..04e649c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -740,6 +740,21 @@
*/
public static final int DONT_KILL_APP = 0x00000001;
+ /** @hide */
+ @IntDef({INSTALL_REASON_UNKNOWN, INSTALL_REASON_POLICY})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface InstallReason {}
+
+ /**
+ * Code indicating that the reason for installing this package is unknown.
+ */
+ public static final int INSTALL_REASON_UNKNOWN = 0;
+
+ /**
+ * Code indicating that this package was installed due to enterprise policy.
+ */
+ public static final int INSTALL_REASON_POLICY = 1;
+
/**
* Installation return code: this is passed to the
* {@link IPackageInstallObserver} on success.
@@ -5881,4 +5896,25 @@
}
}
}
+
+ /**
+ * Return the install reason that was recorded when a package was first installed for a specific
+ * user. Requesting the install reason for another user will require the permission
+ * INTERACT_ACROSS_USERS_FULL.
+ *
+ * @param packageName The package for which to retrieve the install reason
+ * @param user The user for whom to retrieve the install reason
+ *
+ * @return The install reason, currently one of {@code INSTALL_REASON_UNKNOWN} and
+ * {@code INSTALL_REASON_POLICY}. If the package is not installed for the given user,
+ * {@code INSTALL_REASON_UNKNOWN} is returned.
+ *
+ * @see #INSTALL_REASON_UNKNOWN
+ * @see #INSTALL_REASON_POLICY
+ *
+ * @hide
+ */
+ @TestApi
+ public abstract @InstallReason int getInstallReason(String packageName,
+ @NonNull UserHandle user);
}
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index eb3f275..e19aa99 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -48,6 +48,7 @@
public int domainVerificationStatus;
public int appLinkGeneration;
public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
+ public int installReason;
public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
@@ -59,6 +60,7 @@
enabled = COMPONENT_ENABLED_STATE_DEFAULT;
domainVerificationStatus =
PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+ installReason = PackageManager.INSTALL_REASON_UNKNOWN;
}
public PackageUserState(PackageUserState o) {
@@ -74,6 +76,7 @@
domainVerificationStatus = o.domainVerificationStatus;
appLinkGeneration = o.appLinkGeneration;
categoryHint = o.categoryHint;
+ installReason = o.installReason;
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
}
@@ -202,6 +205,9 @@
if (categoryHint != oldState.categoryHint) {
return false;
}
+ if (installReason != oldState.installReason) {
+ return false;
+ }
if ((disabledComponents == null && oldState.disabledComponents != null)
|| (disabledComponents != null && oldState.disabledComponents == null)) {
return false;
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
index c4aa57d..4c11197 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AppRestrictionsHelper.java
@@ -115,7 +115,8 @@
PackageManager.MATCH_ANY_USER, userId);
if (info == null || !info.enabled
|| (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
- mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier());
+ mIPm.installExistingPackageAsUser(packageName, mUser.getIdentifier(),
+ PackageManager.INSTALL_REASON_UNKNOWN);
if (DEBUG) {
Log.d(TAG, "Installing " + packageName);
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
index 3f989bd..f33362f 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/AppRestrictionsHelperTest.java
@@ -145,7 +145,8 @@
mock(AppRestrictionsHelper.OnDisableUiForPackageListener.class);
mHelper.applyUserAppsStates(mockListener);
- verify(mIpm, times(1)).installExistingPackageAsUser("app1", testUserId);
+ verify(mIpm, times(1)).installExistingPackageAsUser("app1", testUserId,
+ PackageManager.INSTALL_REASON_UNKNOWN);
verify(mIpm, times(1)).setApplicationHiddenSettingAsUser("app2", false, testUserId);
verify(mockListener).onDisableUiForPackage("app2");
verify(mPm, times(1)).deletePackageAsUser(eq("app3"), any(IPackageDeleteObserver.class),
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b29bf7b..7e47a11 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12149,7 +12149,7 @@
final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
null /*packageAbiOverride*/, null /*grantedPermissions*/,
- null /*certificates*/);
+ null /*certificates*/, PackageManager.INSTALL_REASON_UNKNOWN);
params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -12185,7 +12185,7 @@
final InstallParams params = new InstallParams(origin, null, observer,
sessionParams.installFlags, installerPackageName, sessionParams.volumeUuid,
verificationInfo, user, sessionParams.abiOverride,
- sessionParams.grantedRuntimePermissions, certificates);
+ sessionParams.grantedRuntimePermissions, certificates, sessionParams.installReason);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -12369,7 +12369,7 @@
* @hide
*/
@Override
- public int installExistingPackageAsUser(String packageName, int userId) {
+ public int installExistingPackageAsUser(String packageName, int userId, int installReason) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
null);
PackageSetting pkgSetting;
@@ -12394,6 +12394,7 @@
if (!pkgSetting.getInstalled(userId)) {
pkgSetting.setInstalled(true, userId);
pkgSetting.setHidden(false, userId);
+ pkgSetting.setInstallReason(installReason, userId);
mSettings.writePackageRestrictionsLPr(userId);
installed = true;
}
@@ -13408,11 +13409,12 @@
final String[] grantedRuntimePermissions;
final VerificationInfo verificationInfo;
final Certificate[][] certificates;
+ final int installReason;
InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, String volumeUuid,
VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
- String[] grantedPermissions, Certificate[][] certificates) {
+ String[] grantedPermissions, Certificate[][] certificates, int installReason) {
super(user);
this.origin = origin;
this.move = move;
@@ -13424,6 +13426,7 @@
this.packageAbiOverride = packageAbiOverride;
this.grantedRuntimePermissions = grantedPermissions;
this.certificates = certificates;
+ this.installReason = installReason;
}
@Override
@@ -13893,6 +13896,7 @@
final String traceMethod;
final int traceCookie;
final Certificate[][] certificates;
+ final int installReason;
// The list of instruction sets supported by this app. This is currently
// only used during the rmdex() phase to clean up resources. We can get rid of this
@@ -13903,7 +13907,8 @@
int installFlags, String installerPackageName, String volumeUuid,
UserHandle user, String[] instructionSets,
String abiOverride, String[] installGrantPermissions,
- String traceMethod, int traceCookie, Certificate[][] certificates) {
+ String traceMethod, int traceCookie, Certificate[][] certificates,
+ int installReason) {
this.origin = origin;
this.move = move;
this.installFlags = installFlags;
@@ -13917,6 +13922,7 @@
this.traceMethod = traceMethod;
this.traceCookie = traceCookie;
this.certificates = certificates;
+ this.installReason = installReason;
}
abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
@@ -14011,7 +14017,8 @@
params.installerPackageName, params.volumeUuid,
params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
params.grantedRuntimePermissions,
- params.traceMethod, params.traceCookie, params.certificates);
+ params.traceMethod, params.traceCookie, params.certificates,
+ params.installReason);
if (isFwdLocked()) {
throw new IllegalArgumentException("Forward locking only supported in ASEC");
}
@@ -14020,7 +14027,8 @@
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
super(OriginInfo.fromNothing(), null, null, 0, null, null, null, instructionSets,
- null, null, null, 0, null /*certificates*/);
+ null, null, null, 0, null /*certificates*/,
+ PackageManager.INSTALL_REASON_UNKNOWN);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
}
@@ -14245,15 +14253,17 @@
params.installerPackageName, params.volumeUuid,
params.getUser(), null /* instruction sets */, params.packageAbiOverride,
params.grantedRuntimePermissions,
- params.traceMethod, params.traceCookie, params.certificates);
+ params.traceMethod, params.traceCookie, params.certificates,
+ params.installReason);
}
/** Existing install */
AsecInstallArgs(String fullCodePath, String[] instructionSets,
boolean isExternal, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, null, (isExternal ? INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, null, null, 0, null /*certificates*/);
+ | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+ instructionSets, null, null, null, 0, null /*certificates*/,
+ PackageManager.INSTALL_REASON_UNKNOWN);
// Hackily pretend we're still looking at a full code path
if (!fullCodePath.endsWith(RES_FILE_NAME)) {
fullCodePath = new File(fullCodePath, RES_FILE_NAME).getAbsolutePath();
@@ -14269,8 +14279,9 @@
AsecInstallArgs(String cid, String[] instructionSets, boolean isForwardLocked) {
super(OriginInfo.fromNothing(), null, null, (isAsecExternal(cid) ? INSTALL_EXTERNAL : 0)
- | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
- instructionSets, null, null, null, 0, null /*certificates*/);
+ | (isForwardLocked ? INSTALL_FORWARD_LOCK : 0), null, null, null,
+ instructionSets, null, null, null, 0, null /*certificates*/,
+ PackageManager.INSTALL_REASON_UNKNOWN);
this.cid = cid;
setMountPath(PackageHelper.getSdDir(cid));
}
@@ -14539,7 +14550,8 @@
params.installerPackageName, params.volumeUuid,
params.getUser(), null /* instruction sets */, params.packageAbiOverride,
params.grantedRuntimePermissions,
- params.traceMethod, params.traceCookie, params.certificates);
+ params.traceMethod, params.traceCookie, params.certificates,
+ params.installReason);
}
int copyApk(IMediaContainerService imcs, boolean temp) {
@@ -14770,7 +14782,7 @@
*/
private void installNewPackageLIF(PackageParser.Package pkg, final int policyFlags,
int scanFlags, UserHandle user, String installerPackageName, String volumeUuid,
- PackageInstalledInfo res) {
+ PackageInstalledInfo res, int installReason) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installNewPackage");
// Remember this for later, in case we need to rollback this install
@@ -14802,7 +14814,7 @@
PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags, scanFlags,
System.currentTimeMillis(), user);
- updateSettingsLI(newPackage, installerPackageName, null, res, user);
+ updateSettingsLI(newPackage, installerPackageName, null, res, user, installReason);
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
prepareAppDataAfterInstallLIF(newPackage);
@@ -14864,7 +14876,8 @@
}
private void replacePackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags,
- UserHandle user, String installerPackageName, PackageInstalledInfo res) {
+ UserHandle user, String installerPackageName, PackageInstalledInfo res,
+ int installReason) {
final boolean isEphemeral = (policyFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0;
final PackageParser.Package oldPackage;
@@ -14964,17 +14977,26 @@
res.removedInfo.removedPackage = oldPackage.packageName;
res.removedInfo.isUpdate = true;
res.removedInfo.origUsers = installedUsers;
+ final PackageSetting ps = mSettings.getPackageLPr(pkgName);
+ res.removedInfo.installReasons = new SparseArray<>(installedUsers.length);
+ for (int i = 0; i < installedUsers.length; i++) {
+ final int userId = installedUsers[i];
+ res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
+ }
+
final int childCount = (oldPackage.childPackages != null)
? oldPackage.childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
boolean childPackageUpdated = false;
PackageParser.Package childPkg = oldPackage.childPackages.get(i);
+ final PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
if (res.addedChildPackages != null) {
PackageInstalledInfo childRes = res.addedChildPackages.get(childPkg.packageName);
if (childRes != null) {
childRes.removedInfo.uid = childPkg.applicationInfo.uid;
childRes.removedInfo.removedPackage = childPkg.packageName;
childRes.removedInfo.isUpdate = true;
+ childRes.removedInfo.installReasons = res.removedInfo.installReasons;
childPackageUpdated = true;
}
}
@@ -14984,7 +15006,6 @@
childRemovedRes.isUpdate = false;
childRemovedRes.dataRemoved = true;
synchronized (mPackages) {
- PackageSetting childPs = mSettings.getPackageLPr(childPkg.packageName);
if (childPs != null) {
childRemovedRes.origUsers = childPs.queryInstalledUsers(allUsers, true);
}
@@ -15007,10 +15028,10 @@
| (privileged ? PackageParser.PARSE_IS_PRIVILEGED : 0);
replaceSystemPackageLIF(oldPackage, pkg, systemPolicyFlags, scanFlags,
- user, allUsers, installerPackageName, res);
+ user, allUsers, installerPackageName, res, installReason);
} else {
replaceNonSystemPackageLIF(oldPackage, pkg, policyFlags, scanFlags,
- user, allUsers, installerPackageName, res);
+ user, allUsers, installerPackageName, res, installReason);
}
}
@@ -15025,7 +15046,8 @@
private void replaceNonSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
- int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
+ int[] allUsers, String installerPackageName, PackageInstalledInfo res,
+ int installReason) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceNonSystemPackageLI: new=" + pkg + ", old="
+ deletedPackage);
@@ -15068,7 +15090,8 @@
try {
final PackageParser.Package newPackage = scanPackageTracedLI(pkg, policyFlags,
scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
- updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
+ updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,
+ installReason);
// Update the in-memory copy of the previous code paths.
PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -15164,7 +15187,8 @@
private void replaceSystemPackageLIF(PackageParser.Package deletedPackage,
PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user,
- int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
+ int[] allUsers, String installerPackageName, PackageInstalledInfo res,
+ int installReason) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+ ", old=" + deletedPackage);
@@ -15237,7 +15261,8 @@
}
}
- updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
+ updateSettingsLI(newPackage, installerPackageName, allUsers, res, user,
+ installReason);
prepareAppDataAfterInstallLIF(newPackage);
}
} catch (PackageManagerException e) {
@@ -15425,10 +15450,10 @@
}
private void updateSettingsLI(PackageParser.Package newPackage, String installerPackageName,
- int[] allUsers, PackageInstalledInfo res, UserHandle user) {
+ int[] allUsers, PackageInstalledInfo res, UserHandle user, int installReason) {
// Update the parent package setting
updateSettingsInternalLI(newPackage, installerPackageName, allUsers, res.origUsers,
- res, user);
+ res, user, installReason);
// Update the child packages setting
final int childCount = (newPackage.childPackages != null)
? newPackage.childPackages.size() : 0;
@@ -15436,13 +15461,13 @@
PackageParser.Package childPackage = newPackage.childPackages.get(i);
PackageInstalledInfo childRes = res.addedChildPackages.get(childPackage.packageName);
updateSettingsInternalLI(childPackage, installerPackageName, allUsers,
- childRes.origUsers, childRes, user);
+ childRes.origUsers, childRes, user, installReason);
}
}
private void updateSettingsInternalLI(PackageParser.Package newPackage,
String installerPackageName, int[] allUsers, int[] installedForUsers,
- PackageInstalledInfo res, UserHandle user) {
+ PackageInstalledInfo res, UserHandle user, int installReason) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings");
String pkgName = newPackage.packageName;
@@ -15500,6 +15525,30 @@
ps.setInstalled(true, userId);
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);
}
+
+ // When replacing an existing package, preserve the original install reason for all
+ // users that had the package installed before.
+ final Set<Integer> previousUserIds = new ArraySet<>();
+ if (res.removedInfo != null && res.removedInfo.installReasons != null) {
+ final int installReasonCount = res.removedInfo.installReasons.size();
+ for (int i = 0; i < installReasonCount; i++) {
+ final int previousUserId = res.removedInfo.installReasons.keyAt(i);
+ final int previousInstallReason = res.removedInfo.installReasons.valueAt(i);
+ ps.setInstallReason(previousInstallReason, previousUserId);
+ previousUserIds.add(previousUserId);
+ }
+ }
+
+ // Set install reason for users that are having the package newly installed.
+ if (userId == UserHandle.USER_ALL) {
+ for (int currentUserId : sUserManager.getUserIds()) {
+ if (!previousUserIds.contains(currentUserId)) {
+ ps.setInstallReason(installReason, currentUserId);
+ }
+ }
+ } else if (!previousUserIds.contains(userId)) {
+ ps.setInstallReason(installReason, userId);
+ }
}
res.name = pkgName;
res.uid = newPackage.applicationInfo.uid;
@@ -15877,10 +15926,10 @@
"installPackageLI")) {
if (replace) {
replacePackageLIF(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user,
- installerPackageName, res);
+ installerPackageName, res, args.installReason);
} else {
installNewPackageLIF(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES,
- args.user, installerPackageName, volumeUuid, res);
+ args.user, installerPackageName, volumeUuid, res, args.installReason);
}
}
synchronized (mPackages) {
@@ -16388,6 +16437,7 @@
int removedAppId = -1;
int[] origUsers;
int[] removedUsers = null;
+ SparseArray<Integer> installReasons;
boolean isRemovedPackageSystemUpdate = false;
boolean isUpdate;
boolean dataRemoved;
@@ -17026,7 +17076,8 @@
false /*installed*/, true /*stopped*/, true /*notLaunched*/,
false /*hidden*/, false /*suspended*/, null, null, null,
false /*blockUninstall*/,
- ps.readUserState(nextUserId).domainVerificationStatus, 0);
+ ps.readUserState(nextUserId).domainVerificationStatus, 0,
+ PackageManager.INSTALL_REASON_UNKNOWN);
}
}
@@ -21045,7 +21096,8 @@
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
installerPackageName, volumeUuid, null /*verificationInfo*/, user,
- packageAbiOverride, null /*grantedPermissions*/, null /*certificates*/);
+ packageAbiOverride, null /*grantedPermissions*/, null /*certificates*/,
+ PackageManager.INSTALL_REASON_UNKNOWN);
params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -21829,4 +21881,18 @@
public void deleteCompilerPackageStats(String pkgName) {
mCompilerStats.deletePackageStats(pkgName);
}
+
+ @Override
+ public int getInstallReason(String packageName, int userId) {
+ enforceCrossUserPermission(Binder.getCallingUid(), userId,
+ true /* requireFullPermission */, false /* checkShell */,
+ "get install reason");
+ synchronized (mPackages) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps != null) {
+ return ps.getInstallReason(userId);
+ }
+ }
+ return PackageManager.INSTALL_REASON_UNKNOWN;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 9456a5c..b332fa5 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -292,6 +292,14 @@
return readUserState(userId).installed;
}
+ int getInstallReason(int userId) {
+ return readUserState(userId).installReason;
+ }
+
+ void setInstallReason(int installReason, int userId) {
+ modifyUserState(userId).installReason = installReason;
+ }
+
/** Only use for testing. Do NOT use in production code. */
@VisibleForTesting
SparseArray<PackageUserState> getUserState() {
@@ -377,7 +385,7 @@
boolean notLaunched, boolean hidden, boolean suspended,
String lastDisableAppCaller, ArraySet<String> enabledComponents,
ArraySet<String> disabledComponents, boolean blockUninstall, int domainVerifState,
- int linkGeneration) {
+ int linkGeneration, int installReason) {
PackageUserState state = modifyUserState(userId);
state.ceDataInode = ceDataInode;
state.enabled = enabled;
@@ -392,6 +400,7 @@
state.blockUninstall = blockUninstall;
state.domainVerificationStatus = domainVerifState;
state.appLinkGeneration = linkGeneration;
+ state.installReason = installReason;
}
ArraySet<String> getEnabledComponents(int userId) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 395108b..8761a6d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -216,6 +216,7 @@
private static final String ATTR_ENABLED_CALLER = "enabledCaller";
private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
+ private static final String ATTR_INSTALL_REASON = "install-reason";
private static final String ATTR_PACKAGE_NAME = "packageName";
private static final String ATTR_FINGERPRINT = "fingerprint";
@@ -736,7 +737,8 @@
false, // suspended
null, null, null,
false, // blockUninstall
- INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
+ INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
+ PackageManager.INSTALL_REASON_UNKNOWN);
}
}
}
@@ -1615,7 +1617,8 @@
false, // suspended
null, null, null,
false, // blockUninstall
- INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
+ INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0,
+ PackageManager.INSTALL_REASON_UNKNOWN);
}
return;
}
@@ -1695,6 +1698,8 @@
if (linkGeneration > maxAppLinkGeneration) {
maxAppLinkGeneration = linkGeneration;
}
+ final int installReason = XmlUtils.readIntAttribute(parser,
+ ATTR_INSTALL_REASON, PackageManager.INSTALL_REASON_UNKNOWN);
ArraySet<String> enabledComponents = null;
ArraySet<String> disabledComponents = null;
@@ -1717,7 +1722,7 @@
ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched,
hidden, suspended, enabledCaller, enabledComponents, disabledComponents,
- blockUninstall, verifState, linkGeneration);
+ blockUninstall, verifState, linkGeneration, installReason);
} else if (tagName.equals("preferred-activities")) {
readPreferredActivitiesLPw(parser, userId);
} else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
@@ -2004,6 +2009,10 @@
XmlUtils.writeIntAttribute(serializer, ATTR_APP_LINK_GENERATION,
ustate.appLinkGeneration);
}
+ if (ustate.installReason != PackageManager.INSTALL_REASON_UNKNOWN) {
+ serializer.attribute(null, ATTR_INSTALL_REASON,
+ Integer.toString(ustate.installReason));
+ }
if (!ArrayUtils.isEmpty(ustate.enabledComponents)) {
serializer.startTag(null, TAG_ENABLED_COMPONENTS);
for (final String name : ustate.enabledComponents) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f1a28e2..471acba 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7604,7 +7604,8 @@
try {
// Install the profile owner if not present.
if (!mIPackageManager.isPackageAvailable(adminPkg, userHandle)) {
- mIPackageManager.installExistingPackageAsUser(adminPkg, userHandle);
+ mIPackageManager.installExistingPackageAsUser(adminPkg, userHandle,
+ PackageManager.INSTALL_REASON_POLICY);
}
} catch (RemoteException e) {
Slog.e(LOG_TAG, "Failed to make remote calls for createAndManageUser, "
@@ -7903,7 +7904,8 @@
}
// Install the app.
- mIPackageManager.installExistingPackageAsUser(packageName, userId);
+ mIPackageManager.installExistingPackageAsUser(packageName, userId,
+ PackageManager.INSTALL_REASON_POLICY);
} catch (RemoteException re) {
// shouldn't happen
@@ -7945,7 +7947,8 @@
String packageName = info.activityInfo.packageName;
if (isSystemApp(mIPackageManager, packageName, parentUserId)) {
numberOfAppsInstalled++;
- mIPackageManager.installExistingPackageAsUser(packageName, userId);
+ mIPackageManager.installExistingPackageAsUser(packageName, userId,
+ PackageManager.INSTALL_REASON_POLICY);
} else {
Slog.d(LOG_TAG, "Not enabling " + packageName + " since is not a"
+ " system app");
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
index 2038c9e..3fa72dc 100644
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
@@ -103,7 +103,8 @@
Log.d(TAG, "installExistingPackage " + packageName + " u" + userId);
}
try {
- mPackageManager.installExistingPackageAsUser(packageName, userId);
+ mPackageManager.installExistingPackageAsUser(packageName, userId,
+ PackageManager.INSTALL_REASON_UNKNOWN);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} finally {
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
index 3eeeaf6..346dc42 100644
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
@@ -103,7 +103,8 @@
observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
null, null);
// Verify that we try to install the package in system user.
- verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM);
+ verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
+ PackageManager.INSTALL_REASON_UNKNOWN);
}
assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
"1",
@@ -139,7 +140,8 @@
observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
null, null);
// Verify that we try to install the package in system user.
- verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM);
+ verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
+ PackageManager.INSTALL_REASON_UNKNOWN);
}
assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
"1",
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 7158969..c46d4a5 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -1064,4 +1064,11 @@
public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
throw new UnsupportedOperationException();
}
+
+ /**
+ * @hide
+ */
+ public int getInstallReason(String packageName, UserHandle user) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 8835b58..bc7bc74 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -868,4 +868,9 @@
public boolean isPackageAvailable(String packageName) {
return false;
}
+
+ @Override
+ public int getInstallReason(String packageName, UserHandle user) {
+ return INSTALL_REASON_UNKNOWN;
+ }
}