summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt4
-rw-r--r--core/java/android/content/pm/IPackageInstaller.aidl3
-rw-r--r--core/java/android/content/pm/PackageInstaller.java24
-rw-r--r--core/java/android/content/pm/PackageManager.java9
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java7
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java35
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java20
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");
}