diff options
| author | 2017-12-11 22:21:12 +0000 | |
|---|---|---|
| committer | 2017-12-11 22:21:12 +0000 | |
| commit | 8c919fd93cc35db80d77a68092458e1405ba8ccf (patch) | |
| tree | 151d6cc6a99a5647edd81c01d96bf53831baa494 | |
| parent | f413d90f0db3838659e7461c50e1da8907ac2d11 (diff) | |
| parent | 5343fcb77df55d01655c9f7bad074c9c7b75ea72 (diff) | |
Merge "Introduce API to enable existing packages on shared users"
4 files changed, 81 insertions, 4 deletions
diff --git a/api/current.txt b/api/current.txt index eec7b5387886..05b2a0c6a4fb 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6344,6 +6344,7 @@ package android.app.admin { method public java.util.List<java.lang.String> getDelegatedScopes(android.content.ComponentName, java.lang.String); method public java.lang.CharSequence getDeviceOwnerLockScreenInfo(); method public java.util.List<byte[]> getInstalledCaCerts(android.content.ComponentName); + method public java.util.List<java.lang.String> getKeepUninstalledPackages(android.content.ComponentName); method public int getKeyguardDisabledFeatures(android.content.ComponentName); method public int getLockTaskFeatures(android.content.ComponentName); method public java.lang.String[] getLockTaskPackages(android.content.ComponentName); @@ -6384,6 +6385,7 @@ package android.app.admin { method public boolean hasCaCertInstalled(android.content.ComponentName, byte[]); method public boolean hasGrantedPolicy(android.content.ComponentName, int); method public boolean installCaCert(android.content.ComponentName, byte[]); + method public boolean installExistingPackage(android.content.ComponentName, java.lang.String); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, java.lang.String); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean); method public boolean installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], java.lang.String, boolean, boolean); @@ -6434,6 +6436,7 @@ package android.app.admin { method public void setDelegatedScopes(android.content.ComponentName, java.lang.String, java.util.List<java.lang.String>); method public void setDeviceOwnerLockScreenInfo(android.content.ComponentName, java.lang.CharSequence); method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String); + method public void setKeepUninstalledPackages(android.content.ComponentName, java.util.List<java.lang.String>); method public boolean setKeyguardDisabled(android.content.ComponentName, boolean); method public void setKeyguardDisabledFeatures(android.content.ComponentName, int); method public void setLockTaskFeatures(android.content.ComponentName, int); @@ -6503,6 +6506,8 @@ package android.app.admin { field public static final java.lang.String DELEGATION_BLOCK_UNINSTALL = "delegation-block-uninstall"; field public static final java.lang.String DELEGATION_CERT_INSTALL = "delegation-cert-install"; field public static final java.lang.String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app"; + field public static final java.lang.String DELEGATION_INSTALL_EXISTING_PACKAGE = "delegation-install-existing-package"; + field public static final java.lang.String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages"; field public static final java.lang.String DELEGATION_PACKAGE_ACCESS = "delegation-package-access"; field public static final java.lang.String DELEGATION_PERMISSION_GRANT = "delegation-permission-grant"; field public static final int ENCRYPTION_STATUS_ACTIVATING = 2; // 0x2 diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ad219837fdf5..34cd67e455ce 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1321,9 +1321,15 @@ public class DevicePolicyManager { public static final String DELEGATION_ENABLE_SYSTEM_APP = "delegation-enable-system-app"; /** + * Delegation for installing existing packages. This scope grants access to the + * {@link #installExistingPackage} API. + */ + public static final String DELEGATION_INSTALL_EXISTING_PACKAGE = + "delegation-install-existing-package"; + + /** * Delegation of management of uninstalled packages. This scope grants access to the * {@code #setKeepUninstalledPackages} and {@code #getKeepUninstalledPackages} APIs. - * @hide */ public static final String DELEGATION_KEEP_UNINSTALLED_PACKAGES = "delegation-keep-uninstalled-packages"; @@ -6085,7 +6091,6 @@ public class DevicePolicyManager { * @return List of package names to keep cached. * @see #setDelegatedScopes * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES - * @hide */ public @Nullable List<String> getKeepUninstalledPackages(@Nullable ComponentName admin) { throwIfParentInstance("getKeepUninstalledPackages"); @@ -6113,7 +6118,6 @@ public class DevicePolicyManager { * @throws SecurityException if {@code admin} is not a device owner. * @see #setDelegatedScopes * @see #DELEGATION_KEEP_UNINSTALLED_PACKAGES - * @hide */ public void setKeepUninstalledPackages(@Nullable ComponentName admin, @NonNull List<String> packageNames) { @@ -6591,6 +6595,37 @@ public class DevicePolicyManager { } /** + * Install an existing package that has been installed in another user, or has been kept after + * removal via {@link #setKeepUninstalledPackages}. + * This function can be called by a device owner, profile owner or a delegate given + * the {@link #DELEGATION_INSTALL_EXISTING_PACKAGE} scope via {@link #setDelegatedScopes}. + * When called in a secondary user or managed profile, the user/profile must be affiliated with + * the device owner. See {@link #setAffiliationIds}. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. + * @param packageName The package to be installed in the calling profile. + * @return {@code true} if the app is installed; {@code false} otherwise. + * @throws SecurityException if {@code admin} is not the device owner, or the profile owner of + * an affiliated user or profile. + * @see #setKeepUninstalledPackages + * @see #setDelegatedScopes + * @see #setAffiliationIds + * @see #DELEGATION_PACKAGE_ACCESS + */ + public boolean installExistingPackage(@NonNull ComponentName admin, String packageName) { + throwIfParentInstance("installExistingPackage"); + if (mService != null) { + try { + return mService.installExistingPackage(admin, mContext.getPackageName(), + packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } + + /** * Called by a device owner or profile owner to disable account management for a specific type * of account. * <p> diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index ff869d247d9a..81da197f2129 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -223,6 +223,7 @@ interface IDevicePolicyManager { void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); + boolean installExistingPackage(in ComponentName admin, in String callerPackage, in String packageName); void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled); String[] getAccountTypesWithManagementDisabled(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 91ba87e84005..b946122019f9 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -40,6 +40,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_APP_RESTRICTIONS; import static android.app.admin.DevicePolicyManager.DELEGATION_BLOCK_UNINSTALL; import static android.app.admin.DevicePolicyManager.DELEGATION_CERT_INSTALL; import static android.app.admin.DevicePolicyManager.DELEGATION_ENABLE_SYSTEM_APP; +import static android.app.admin.DevicePolicyManager.DELEGATION_INSTALL_EXISTING_PACKAGE; import static android.app.admin.DevicePolicyManager.DELEGATION_KEEP_UNINSTALLED_PACKAGES; import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS; import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT; @@ -296,7 +297,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { DELEGATION_ENABLE_SYSTEM_APP, DELEGATION_KEEP_UNINSTALLED_PACKAGES, DELEGATION_PACKAGE_ACCESS, - DELEGATION_PERMISSION_GRANT + DELEGATION_PERMISSION_GRANT, + DELEGATION_INSTALL_EXISTING_PACKAGE, + DELEGATION_KEEP_UNINSTALLED_PACKAGES }; /** @@ -8843,6 +8846,39 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public boolean installExistingPackage(ComponentName who, String callerPackage, + String packageName) { + synchronized (this) { + // Ensure the caller is a PO or an install existing package delegate + enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, + DELEGATION_INSTALL_EXISTING_PACKAGE); + final int callingUserId = mInjector.userHandleGetCallingUserId(); + if (!isUserAffiliatedWithDeviceLocked(callingUserId)) { + throw new SecurityException("Admin " + who + + " is neither the device owner or affiliated user's profile owner."); + } + + final long id = mInjector.binderClearCallingIdentity(); + try { + if (VERBOSE_LOG) { + Slog.v(LOG_TAG, "installing " + packageName + " for " + + callingUserId); + } + + // Install the package. + return mIPackageManager.installExistingPackageAsUser(packageName, callingUserId, + 0 /*installFlags*/, PackageManager.INSTALL_REASON_POLICY) + == PackageManager.INSTALL_SUCCEEDED; + } catch (RemoteException re) { + // shouldn't happen + return false; + } finally { + mInjector.binderRestoreCallingIdentity(id); + } + } + } + + @Override public void setAccountManagementDisabled(ComponentName who, String accountType, boolean disabled) { if (!mHasFeature) { |