Merge "Add API for virtual preloads" into oc-mr1-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 38d3e2f..c8f907a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -11222,6 +11222,7 @@
method public void setDontKillApp(boolean);
method public void setGrantedRuntimePermissions(java.lang.String[]);
method public void setInstallAsInstantApp(boolean);
+ method public void setInstallAsVirtualPreload();
method public void setInstallLocation(int);
method public void setInstallReason(int);
method public void setOriginatingUid(int);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index bdf0562..ea675fb 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1186,6 +1186,16 @@
}
/**
+ * Sets the install as a virtual preload. Will only have effect when called
+ * by the verifier.
+ * {@hide}
+ */
+ @SystemApi
+ public void setInstallAsVirtualPreload() {
+ installFlags |= PackageManager.INSTALL_VIRTUAL_PRELOAD;
+ }
+
+ /**
* Set the reason for installing this package.
*/
public void setInstallReason(@InstallReason int installReason) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 040f85b..cc197a2 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -809,6 +809,14 @@
*/
public static final int INSTALL_ALLOCATE_AGGRESSIVE = 0x00008000;
+ /**
+ * Flag parameter for {@link #installPackage} to indicate that this package
+ * is a virtual preload.
+ *
+ * @hide
+ */
+ public static final int INSTALL_VIRTUAL_PRELOAD = 0x00010000;
+
/** @hide */
@IntDef(flag = true, prefix = { "DONT_KILL_APP" }, value = {
DONT_KILL_APP
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index bf64f64..bab7011 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -615,6 +615,10 @@
params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;
params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;
params.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
+ if ((params.installFlags & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0
+ && !mPm.isCallerVerifier(callingUid)) {
+ params.installFlags &= ~PackageManager.INSTALL_VIRTUAL_PRELOAD;
+ }
}
// Only system components can circumvent runtime permissions when installing.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 98b6949..b4c34b0e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1670,12 +1670,14 @@
& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
final boolean killApp = (args.installFlags
& PackageManager.INSTALL_DONT_KILL_APP) == 0;
+ final boolean virtualPreload = ((args.installFlags
+ & PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
final String[] grantedPermissions = args.installGrantPermissions;
// Handle the parent package
handlePackagePostInstall(parentRes, grantPermissions, killApp,
- grantedPermissions, didRestore, args.installerPackageName,
- args.observer);
+ virtualPreload, grantedPermissions, didRestore,
+ args.installerPackageName, args.observer);
// Handle the child packages
final int childCount = (parentRes.addedChildPackages != null)
@@ -1683,8 +1685,8 @@
for (int i = 0; i < childCount; i++) {
PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
handlePackagePostInstall(childRes, grantPermissions, killApp,
- grantedPermissions, false, args.installerPackageName,
- args.observer);
+ virtualPreload, grantedPermissions, false /*didRestore*/,
+ args.installerPackageName, args.observer);
}
// Log tracing if needed
@@ -1895,7 +1897,7 @@
}
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
- boolean killApp, String[] grantedPermissions,
+ boolean killApp, boolean virtualPreload, String[] grantedPermissions,
boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
@@ -1969,7 +1971,8 @@
// sendPackageAddedForNewUsers also deals with system apps
int appId = UserHandle.getAppId(res.uid);
boolean isSystem = res.pkg.applicationInfo.isSystemApp();
- sendPackageAddedForNewUsers(packageName, isSystem, appId, firstUsers);
+ sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
+ virtualPreload /*startReceiver*/, appId, firstUsers);
// Send added for users that don't see the package for the first time
Bundle extras = new Bundle(1);
@@ -14350,7 +14353,8 @@
private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting,
int userId) {
final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
- sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId);
+ sendPackageAddedForNewUsers(packageName, isSystem /*sendBootCompleted*/,
+ false /*startReceiver*/, pkgSetting.appId, userId);
// Send a session commit broadcast
final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
@@ -14359,7 +14363,8 @@
sendSessionCommitBroadcast(info, userId);
}
- public void sendPackageAddedForNewUsers(String packageName, boolean isSystem, int appId, int... userIds) {
+ public void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
+ boolean includeStopped, int appId, int... userIds) {
if (ArrayUtils.isEmpty(userIds)) {
return;
}
@@ -14369,10 +14374,11 @@
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
packageName, extras, 0, null, null, userIds);
- if (isSystem) {
+ if (sendBootCompleted) {
mHandler.post(() -> {
for (int userId : userIds) {
- sendBootCompletedBroadcastToSystemApp(packageName, userId);
+ sendBootCompletedBroadcastToSystemApp(
+ packageName, includeStopped, userId);
}
}
);
@@ -14384,7 +14390,8 @@
* automatically without needing an explicit launch.
* Send it a LOCKED_BOOT_COMPLETED/BOOT_COMPLETED if it would ordinarily have gotten ones.
*/
- private void sendBootCompletedBroadcastToSystemApp(String packageName, int userId) {
+ private void sendBootCompletedBroadcastToSystemApp(String packageName, boolean includeStopped,
+ int userId) {
// If user is not running, the app didn't miss any broadcast
if (!mUserManagerInternal.isUserRunning(userId)) {
return;
@@ -14394,6 +14401,9 @@
// Deliver LOCKED_BOOT_COMPLETED first
Intent lockedBcIntent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED)
.setPackage(packageName);
+ if (includeStopped) {
+ lockedBcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ }
final String[] requiredPermissions = {Manifest.permission.RECEIVE_BOOT_COMPLETED};
am.broadcastIntent(null, lockedBcIntent, null, null, 0, null, null, requiredPermissions,
android.app.AppOpsManager.OP_NONE, null, false, false, userId);
@@ -14401,6 +14411,9 @@
// Deliver BOOT_COMPLETED only if user is unlocked
if (mUserManagerInternal.isUserUnlockingOrUnlocked(userId)) {
Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED).setPackage(packageName);
+ if (includeStopped) {
+ bcIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
+ }
am.broadcastIntent(null, bcIntent, null, null, 0, null, null, requiredPermissions,
android.app.AppOpsManager.OP_NONE, null, false, false, userId);
}
@@ -18724,6 +18737,12 @@
return packageName;
}
+ boolean isCallerVerifier(int callingUid) {
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ return mRequiredVerifierPackage != null &&
+ callingUid == getPackageUid(mRequiredVerifierPackage, 0, callingUserId);
+ }
+
private boolean isCallerAllowedToSilentlyUninstall(int callingUid, String pkgName) {
if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID
|| UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
@@ -18997,8 +19016,8 @@
for (int i = 0; i < packageCount; i++) {
PackageInstalledInfo installedInfo = appearedChildPackages.valueAt(i);
packageSender.sendPackageAddedForNewUsers(installedInfo.name,
- true, UserHandle.getAppId(installedInfo.uid),
- installedInfo.newUsers);
+ true /*sendBootCompleted*/, false /*startReceiver*/,
+ UserHandle.getAppId(installedInfo.uid), installedInfo.newUsers);
}
}
@@ -25086,6 +25105,6 @@
void sendPackageBroadcast(final String action, final String pkg,
final Bundle extras, final int flags, final String targetPkg,
final IIntentReceiver finishedReceiver, final int[] userIds);
- void sendPackageAddedForNewUsers(String packageName, boolean isSystem,
- int appId, int... userIds);
+ void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
+ boolean includeStopped, int appId, int... userIds);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 6d6611f..faeb05b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1221,6 +1221,9 @@
case "--full":
sessionParams.setInstallAsInstantApp(false /*isInstantApp*/);
break;
+ case "--preload":
+ sessionParams.setInstallAsVirtualPreload();
+ break;
case "--user":
params.userId = UserHandle.parseUserArg(getNextArgRequired());
break;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 8f2f34e..beffcee 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -47,7 +47,7 @@
}
public void sendPackageAddedForNewUsers(String packageName,
- boolean isSystem, int appId, int... userIds) {
+ boolean sendBootComplete, boolean includeStopped, int appId, int... userIds) {
}
}