diff options
8 files changed, 94 insertions, 9 deletions
diff --git a/api/current.txt b/api/current.txt index 9e28ada17a93..9d1c5378c141 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11375,6 +11375,7 @@ package android.content.pm { method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions(); method @Nullable public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int); method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getStagedSessions(); + method @RequiresPermission(allOf={android.Manifest.permission.INSTALL_PACKAGES, "com.android.permission.INSTALL_EXISTING_PACKAGES"}) public void installExistingPackage(@NonNull String, int, @Nullable android.content.IntentSender); method @NonNull public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException; method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback); method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback, @NonNull android.os.Handler); diff --git a/api/system-current.txt b/api/system-current.txt index c831522f1286..1fff4db52940 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1590,8 +1590,8 @@ package android.content.pm { method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle); method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] getUnsuspendablePackages(@NonNull String[]); method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle); - method public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException; - method public abstract int installExistingPackage(String, int) throws android.content.pm.PackageManager.NameNotFoundException; + method @Deprecated public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException; + method @Deprecated public abstract int installExistingPackage(String, int) throws android.content.pm.PackageManager.NameNotFoundException; method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle); method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle); diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl index a251c0036a78..0cf83fd4655b 100644 --- a/core/java/android/content/pm/IPackageInstaller.aidl +++ b/core/java/android/content/pm/IPackageInstaller.aidl @@ -50,5 +50,8 @@ interface IPackageInstaller { void uninstall(in VersionedPackage versionedPackage, String callerPackageName, int flags, in IntentSender statusReceiver, int userId); + void installExistingPackage(String packageName, int installFlags, int installReason, + in IntentSender statusReceiver, int userId); + void setPermissionsResult(int sessionId, boolean accepted); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 80954731bffb..50205192dede 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -590,6 +590,30 @@ public class PackageInstaller { } } + /** + * Install the given package, which already exists on the device, for the user for which this + * installer was created. + * + * @param packageName The package to install. + * @param installReason Reason for install. + * @param statusReceiver Where to deliver the result. + */ + @RequiresPermission(allOf = { + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.INSTALL_EXISTING_PACKAGES}) + public void installExistingPackage(@NonNull String packageName, + @InstallReason int installReason, + @Nullable IntentSender statusReceiver) { + Preconditions.checkNotNull(packageName, "packageName cannot be null"); + try { + mInstaller.installExistingPackage(packageName, 0, installReason, statusReceiver, + mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** {@hide} */ @SystemApi @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 00419212544a..11e4a45d16e1 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -5114,7 +5114,10 @@ public abstract class PackageManager { * If there is already an application with the given package name installed * on the system for other users, also install it for the calling user. * @hide + * + * @deprecated use {@link PackageInstaller#installExistingPackage()} instead. */ + @Deprecated @SystemApi public abstract int installExistingPackage(String packageName) throws NameNotFoundException; @@ -5122,7 +5125,10 @@ public abstract class PackageManager { * If there is already an application with the given package name installed * on the system for other users, also install it for the calling user. * @hide + * + * @deprecated use {@link PackageInstaller#installExistingPackage()} instead. */ + @Deprecated @SystemApi public abstract int installExistingPackage(String packageName, @InstallReason int installReason) throws NameNotFoundException; @@ -5131,7 +5137,10 @@ public abstract class PackageManager { * If there is already an application with the given package name installed * on the system for other users, also install it for the specified user. * @hide + * + * @deprecated use {@link PackageInstaller#installExistingPackage()} instead. */ + @Deprecated @RequiresPermission(anyOf = { Manifest.permission.INSTALL_EXISTING_PACKAGES, Manifest.permission.INSTALL_PACKAGES, diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index f06da49f5b94..1e77362681b9 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -821,6 +821,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements } @Override + public void installExistingPackage(String packageName, int installFlags, int installReason, + IntentSender statusReceiver, int userId) { + mPm.installExistingPackageAsUser(packageName, userId, installFlags, installReason, + statusReceiver); + } + + @Override public void setPermissionsResult(int sessionId, boolean accepted) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 07d460edb2d2..2e5539767301 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1303,12 +1303,14 @@ public class PackageManagerService extends IPackageManager.Stub // Recordkeeping of restore-after-install operations that are currently in flight // between the Package Manager and the Backup Manager static class PostInstallData { - public InstallArgs args; - public PackageInstalledInfo res; + public final InstallArgs args; + public final PackageInstalledInfo res; + public final Runnable mPostInstallRunnable; - PostInstallData(InstallArgs _a, PackageInstalledInfo _r) { + PostInstallData(InstallArgs _a, PackageInstalledInfo _r, Runnable postInstallRunnable) { args = _a; res = _r; + mPostInstallRunnable = postInstallRunnable; } } @@ -1440,7 +1442,9 @@ public class PackageManagerService extends IPackageManager.Stub final boolean didRestore = (msg.arg2 != 0); mRunningInstalls.delete(msg.arg1); - if (data != null) { + if (data != null && data.mPostInstallRunnable != null) { + data.mPostInstallRunnable.run(); + } else if (data != null) { InstallArgs args = data.args; PackageInstalledInfo parentRes = data.res; @@ -12683,6 +12687,11 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int installExistingPackageAsUser(String packageName, int userId, int installFlags, int installReason) { + return installExistingPackageAsUser(packageName, userId, installFlags, installReason, null); + } + + int installExistingPackageAsUser(String packageName, int userId, int installFlags, + int installReason, IntentSender intentSender) { if (DEBUG_INSTALL) { Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId + " installFlags=" + installFlags + " installReason=" + installReason); @@ -12762,7 +12771,11 @@ public class PackageManagerService extends IPackageManager.Stub PackageInstalledInfo res = createPackageInstalledInfo(PackageManager.INSTALL_SUCCEEDED); res.pkg = pkgSetting.pkg; - restoreAndPostInstall(userId, res, null); + res.newUsers = new int[]{ userId }; + PostInstallData postInstallData = intentSender == null ? null : + new PostInstallData(null, res, () -> onRestoreComplete(res.returnCode, + mContext, intentSender)); + restoreAndPostInstall(userId, res, postInstallData); } } finally { Binder.restoreCallingIdentity(callingId); @@ -12771,6 +12784,16 @@ public class PackageManagerService extends IPackageManager.Stub return PackageManager.INSTALL_SUCCEEDED; } + static void onRestoreComplete(int returnCode, Context context, IntentSender target) { + Intent fillIn = new Intent(); + fillIn.putExtra(PackageInstaller.EXTRA_STATUS, + PackageManager.installStatusToPublicStatus(returnCode)); + try { + target.sendIntent(context, 0, fillIn, null, null); + } catch (SendIntentException ignored) { + } + } + static void setInstantAppForUser(PackageSetting pkgSetting, int userId, boolean instantApp, boolean fullApp) { // no state specified; do nothing @@ -13727,7 +13750,7 @@ public class PackageManagerService extends IPackageManager.Stub } for (InstallRequest request : installRequests) { restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult, - new PostInstallData(request.args, request.installResult)); + new PostInstallData(request.args, request.installResult, null)); } }); } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 2eb762b59be4..52169676dab1 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1114,6 +1114,7 @@ class PackageManagerShellCommand extends ShellCommand { int userId = UserHandle.USER_SYSTEM; int installFlags = 0; String opt; + boolean waitTillComplete = false; while ((opt = getNextOption()) != null) { switch (opt) { case "--user": @@ -1128,6 +1129,9 @@ class PackageManagerShellCommand extends ShellCommand { installFlags &= ~PackageManager.INSTALL_INSTANT_APP; installFlags |= PackageManager.INSTALL_FULL_APP; break; + case "--wait": + waitTillComplete = true; + break; default: pw.println("Error: Unknown option: " + opt); return 1; @@ -1140,9 +1144,23 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } + int installReason = PackageManager.INSTALL_REASON_UNKNOWN; try { + if (waitTillComplete) { + final LocalIntentReceiver receiver = new LocalIntentReceiver(); + final IPackageInstaller installer = mInterface.getPackageInstaller(); + pw.println("Installing package " + packageName + " for user: " + userId); + installer.installExistingPackage(packageName, installFlags, installReason, + receiver.getIntentSender(), userId); + final Intent result = receiver.getResult(); + final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, + PackageInstaller.STATUS_FAILURE); + pw.println("Received intent for package install"); + return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1; + } + final int res = mInterface.installExistingPackageAsUser(packageName, userId, - installFlags, PackageManager.INSTALL_REASON_UNKNOWN); + installFlags, installReason); if (res == PackageManager.INSTALL_FAILED_INVALID_URI) { throw new NameNotFoundException("Package " + packageName + " doesn't exist"); } |