diff --git a/api/current.xml b/api/current.xml index 5cb4c818daf98..a33d30f6fdbd9 100644 --- a/api/current.xml +++ b/api/current.xml @@ -36937,6 +36937,21 @@ + + + + + + You can optionally include the {@link #EXTRA_ADD_EXPLANATION} * field to provide the user with additional explanation (in addition * to your component's description) about what is being added. + * + *

If your administrator is already active, this will ordinarily return immediately (without + * user intervention). However, if your administrator has been updated and is requesting + * additional uses-policy flags, the user will be presented with the new list. New policies + * will not be available to the updated administrator until the user has accepted the new list. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_ADD_DEVICE_ADMIN @@ -178,6 +178,26 @@ public class DevicePolicyManager { } } + /** + * Returns true if an administrator has been granted a particular device policy. This can + * be used to check if the administrator was activated under an earlier set of policies, + * but requires additional policies after an upgrade. + * + * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be + * an active administrator, or an exception will be thrown. + * @param usesPolicy Which uses-policy to check, as defined in {@link DeviceAdminInfo}. + */ + public boolean hasGrantedPolicy(ComponentName admin, int usesPolicy) { + if (mService != null) { + try { + return mService.hasGrantedPolicy(admin, usesPolicy); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + /** * Constant for {@link #setPasswordQuality}: the policy has no requirements * for the password. Note that quality constants are ordered so that higher @@ -1075,10 +1095,10 @@ public class DevicePolicyManager { /** * @hide */ - public void setActiveAdmin(ComponentName policyReceiver) { + public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) { if (mService != null) { try { - mService.setActiveAdmin(policyReceiver); + mService.setActiveAdmin(policyReceiver, refreshing); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -1086,6 +1106,7 @@ public class DevicePolicyManager { } /** + * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data * @hide */ public DeviceAdminInfo getAdminInfo(ComponentName cn) { diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 7acc83e2d375a..7504f5bf864a6 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -75,12 +75,13 @@ interface IDevicePolicyManager { ComponentName setGlobalProxy(in ComponentName admin, String proxySpec, String exclusionList); ComponentName getGlobalProxyAdmin(); - void setActiveAdmin(in ComponentName policyReceiver); + void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing); boolean isAdminActive(in ComponentName policyReceiver); List getActiveAdmins(); boolean packageHasActiveAdmins(String packageName); void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result); void removeActiveAdmin(in ComponentName policyReceiver); + boolean hasGrantedPolicy(in ComponentName policyReceiver, int usesPolicy); void setActivePasswordState(int quality, int length, int letters, int uppercase, int lowercase, int numbers, int symbols, int nonletter); diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 0dead1cd796cb..470af6720bb01 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -816,7 +816,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public void setActiveAdmin(ComponentName adminReceiver) { + /** + * @param adminReceiver The admin to add + * @param refreshing true = update an active admin, no error + */ + public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); @@ -827,15 +831,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { long ident = Binder.clearCallingIdentity(); try { - if (getActiveAdminUncheckedLocked(adminReceiver) != null) { + if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) { throw new IllegalArgumentException("Admin is already added"); } - ActiveAdmin admin = new ActiveAdmin(info); - mAdminMap.put(adminReceiver, admin); - mAdminList.add(admin); + ActiveAdmin newAdmin = new ActiveAdmin(info); + mAdminMap.put(adminReceiver, newAdmin); + int replaceIndex = -1; + if (refreshing) { + final int N = mAdminList.size(); + for (int i=0; i < N; i++) { + ActiveAdmin oldAdmin = mAdminList.get(i); + if (oldAdmin.info.getComponent().equals(adminReceiver)) { + replaceIndex = i; + break; + } + } + } + if (replaceIndex == -1) { + mAdminList.add(newAdmin); + } else { + mAdminList.set(replaceIndex, newAdmin); + } saveSettingsLocked(); - sendAdminCommandLocked(admin, - DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED); + sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED); } finally { Binder.restoreCallingIdentity(ident); } @@ -848,6 +866,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) { + synchronized (this) { + ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver); + if (administrator == null) { + throw new SecurityException("No active admin " + adminReceiver); + } + return administrator.info.usesPolicy(policyId); + } + } + public List getActiveAdmins() { synchronized (this) { final int N = mAdminList.size();