diff options
-rw-r--r-- | api/current.xml | 11 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 2 | ||||
-rw-r--r-- | core/java/android/app/DevicePolicyManager.java | 44 | ||||
-rw-r--r-- | core/java/android/app/IDevicePolicyManager.aidl | 3 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/LockPatternUtils.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/DevicePolicyManagerService.java | 145 |
6 files changed, 135 insertions, 75 deletions
diff --git a/api/current.xml b/api/current.xml index a32c757..d79b5cc 100644 --- a/api/current.xml +++ b/api/current.xml @@ -20399,6 +20399,17 @@ deprecated="not deprecated" visibility="public" > +<method name="getActiveAdmins" + return="java.util.List<android.content.ComponentName>" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getCurrentFailedPasswordAttempts" return="int" abstract="false" diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 95142e3..05bbf3b 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -2518,7 +2518,7 @@ public class Activity extends ContextThemeWrapper * and restored for you. Note that if the dialog is already created, * {@link #onCreateDialog(int, Bundle)} will not be called with the new * arguments but {@link #onPrepareDialog(int, Dialog, Bundle)} will be. - * If you need to rebuild the dialog, call {@link #removeDialog(int)}Êfirst. + * If you need to rebuild the dialog, call {@link #removeDialog(int)} first. * @return Returns true if the Dialog was created; false is returned if * it is not created because {@link #onCreateDialog(int, Bundle)} returns false. * diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java index 9de7336..135851f 100644 --- a/core/java/android/app/DevicePolicyManager.java +++ b/core/java/android/app/DevicePolicyManager.java @@ -32,6 +32,7 @@ import android.os.ServiceManager; import android.util.Log; import java.io.IOException; +import java.util.List; /** * Public interface for managing policies enforced on a device. Most clients @@ -65,10 +66,6 @@ public class DevicePolicyManager { * <p>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. - * - * <p>Note: the current platform can only have one device administrator - * active at a time. If you make this request while there is already - * an active administrator, this new request will be canceled automatically. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String ACTION_ADD_DEVICE_ADMIN @@ -111,7 +108,7 @@ public class DevicePolicyManager { public boolean isAdminActive(ComponentName who) { if (mService != null) { try { - return who.equals(mService.getActiveAdmin()); + return mService.isAdminActive(who); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -120,6 +117,22 @@ public class DevicePolicyManager { } /** + * Return a list of all currently active device administrator's component + * names. Note that if there are no administrators than null may be + * returned. + */ + public List<ComponentName> getActiveAdmins() { + if (mService != null) { + try { + return mService.getActiveAdmins(); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return null; + } + + /** * Remove a current administration component. This can only be called * by the application that owns the administration component; if you * try to remove someone else's component, a security exception will be @@ -442,26 +455,7 @@ public class DevicePolicyManager { /** * @hide */ - public ComponentName getActiveAdmin() { - if (mService != null) { - try { - return mService.getActiveAdmin(); - } catch (RemoteException e) { - Log.w(TAG, "Failed talking with device policy service", e); - } - } - return null; - } - - /** - * @hide - */ - public DeviceAdminInfo getActiveAdminInfo() { - ComponentName cn = getActiveAdmin(); - if (cn == null) { - return null; - } - + public DeviceAdminInfo getAdminInfo(ComponentName cn) { ActivityInfo ai; try { ai = mContext.getPackageManager().getReceiverInfo(cn, diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl index edb8603..a5508cd 100644 --- a/core/java/android/app/IDevicePolicyManager.aidl +++ b/core/java/android/app/IDevicePolicyManager.aidl @@ -45,7 +45,8 @@ interface IDevicePolicyManager { void wipeData(int flags); void setActiveAdmin(in ComponentName policyReceiver); - ComponentName getActiveAdmin(); + boolean isAdminActive(in ComponentName policyReceiver); + List<ComponentName> getActiveAdmins(); void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result); void removeActiveAdmin(in ComponentName policyReceiver); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index aafe453..bd41a13 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -121,11 +121,6 @@ public class LockPatternUtils { } - public boolean isDevicePolicyActive() { - ComponentName admin = mDevicePolicyManager.getActiveAdmin(); - return admin != null ? mDevicePolicyManager.isAdminActive(admin) : false; - } - public int getRequestedMinimumPasswordLength() { return mDevicePolicyManager.getMinimumPasswordLength(); } diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index ebd6f3d..7b8645f 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -35,7 +35,6 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Binder; -import android.os.Handler; import android.os.IBinder; import android.os.IPowerManager; import android.os.RecoverySystem; @@ -49,6 +48,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; import java.util.List; /** @@ -65,7 +66,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { int mActivePasswordLength = 0; int mFailedPasswordAttempts = 0; - ActiveAdmin mActiveAdmin; + final HashMap<ComponentName, ActiveAdmin> mAdminMap + = new HashMap<ComponentName, ActiveAdmin>(); + final ArrayList<ActiveAdmin> mAdminList + = new ArrayList<ActiveAdmin>(); static class ActiveAdmin { final DeviceAdminInfo info; @@ -148,7 +152,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) { - ActiveAdmin admin = mActiveAdmin; + ActiveAdmin admin = mAdminMap.get(who); if (admin != null && who.getPackageName().equals(admin.info.getActivityInfo().packageName) && who.getClassName().equals(admin.info.getActivityInfo().name)) { @@ -159,7 +163,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { ActiveAdmin getActiveAdminForCallerLocked(ComponentName who) throws SecurityException { - ActiveAdmin admin = mActiveAdmin; + ActiveAdmin admin = mAdminMap.get(who); if (admin != null && admin.getUid() == Binder.getCallingUid()) { if (who != null) { if (!who.getPackageName().equals(admin.info.getActivityInfo().packageName) @@ -167,7 +171,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { throw new SecurityException("Current admin is not " + who); } } - return mActiveAdmin; + return admin; } throw new SecurityException("Current admin is not owned by uid " + Binder.getCallingUid()); } @@ -190,28 +194,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } void sendAdminCommandLocked(String action, int reqPolicy) { - if (mActiveAdmin != null) { - if (mActiveAdmin.info.usesPolicy(reqPolicy)) { - return; + final int N = mAdminList.size(); + if (N > 0) { + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (admin.info.usesPolicy(reqPolicy)) { + sendAdminCommandLocked(admin, action); + } } - sendAdminCommandLocked(mActiveAdmin, action); } } - ComponentName getActiveAdminLocked() { - if (mActiveAdmin != null) { - return mActiveAdmin.info.getComponent(); - } - return null; - } - void removeActiveAdminLocked(ComponentName adminReceiver) { - ComponentName cur = getActiveAdminLocked(); - if (cur != null && cur.equals(adminReceiver)) { - sendAdminCommandLocked(mActiveAdmin, + ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); + if (admin != null) { + sendAdminCommandLocked(admin, DeviceAdmin.ACTION_DEVICE_ADMIN_DISABLED); // XXX need to wait for it to complete. - mActiveAdmin = null; + mAdminList.remove(admin); + mAdminMap.remove(adminReceiver); } } @@ -251,13 +252,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { out.startTag(null, "policies"); - ActiveAdmin ap = mActiveAdmin; - if (ap != null) { - out.startTag(null, "admin"); - out.attribute(null, "name", ap.info.getComponent().flattenToString()); - ap.writeToXml(out); - out.endTag(null, "admin"); + final int N = mAdminList.size(); + for (int i=0; i<N; i++) { + ActiveAdmin ap = mAdminList.get(i); + if (ap != null) { + out.startTag(null, "admin"); + out.attribute(null, "name", ap.info.getComponent().flattenToString()); + ap.writeToXml(out); + out.endTag(null, "admin"); + } } + out.endTag(null, "policies"); if (mFailedPasswordAttempts != 0) { @@ -314,7 +319,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (dai != null) { ActiveAdmin ap = new ActiveAdmin(dai); ap.readFromXml(parser); - mActiveAdmin = ap; + mAdminMap.put(ap.info.getComponent(), ap); + mAdminList.add(ap); } } else if ("failed-password-attempts".equals(tag)) { mFailedPasswordAttempts = Integer.parseInt( @@ -369,16 +375,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { synchronized (this) { long ident = Binder.clearCallingIdentity(); try { - ComponentName cur = getActiveAdminLocked(); - if (cur != null && cur.equals(adminReceiver)) { - throw new IllegalStateException("An admin is already set"); + if (getActiveAdminUncheckedLocked(adminReceiver) != null) { + throw new IllegalArgumentException("Admin is already added"); } - if (cur != null) { - removeActiveAdminLocked(adminReceiver); - } - mActiveAdmin = new ActiveAdmin(info); + ActiveAdmin admin = new ActiveAdmin(info); + mAdminMap.put(adminReceiver, admin); + mAdminList.add(admin); saveSettingsLocked(); - sendAdminCommandLocked(mActiveAdmin, + sendAdminCommandLocked(admin, DeviceAdmin.ACTION_DEVICE_ADMIN_ENABLED); } finally { Binder.restoreCallingIdentity(ident); @@ -386,15 +390,33 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public ComponentName getActiveAdmin() { + public boolean isAdminActive(ComponentName adminReceiver) { synchronized (this) { - return getActiveAdminLocked(); + return getActiveAdminUncheckedLocked(adminReceiver) != null; + } + } + + public List<ComponentName> getActiveAdmins() { + synchronized (this) { + final int N = mAdminList.size(); + if (N <= 0) { + return null; + } + ArrayList<ComponentName> res = new ArrayList<ComponentName>(N); + for (int i=0; i<N; i++) { + res.add(mAdminList.get(i).info.getComponent()); + } + return res; } } public void removeActiveAdmin(ComponentName adminReceiver) { synchronized (this) { - if (mActiveAdmin == null || mActiveAdmin.getUid() != Binder.getCallingUid()) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver); + if (admin == null) { + return; + } + if (admin.getUid() != Binder.getCallingUid()) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.BIND_DEVICE_ADMIN, null); } @@ -423,8 +445,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public int getPasswordMode() { synchronized (this) { - return mActiveAdmin != null ? mActiveAdmin.passwordMode - : DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED; + final int N = mAdminList.size(); + int mode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED; + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (mode < admin.passwordMode) { + mode = admin.passwordMode; + } + } + return mode; } } @@ -444,7 +473,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public int getMinimumPasswordLength() { synchronized (this) { - return mActiveAdmin != null ? mActiveAdmin.minimumPasswordLength : 0; + final int N = mAdminList.size(); + int length = 0; + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (length < admin.minimumPasswordLength) { + length = admin.minimumPasswordLength; + } + } + return length; } } @@ -486,7 +523,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public int getMaximumFailedPasswordsForWipe() { synchronized (this) { - return mActiveAdmin != null ? mActiveAdmin.maximumFailedPasswordsForWipe : 0; + final int N = mAdminList.size(); + int count = 0; + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (count == 0) { + count = admin.maximumFailedPasswordsForWipe; + } else if (admin.maximumFailedPasswordsForWipe != 0 + && count > admin.maximumFailedPasswordsForWipe) { + count = admin.maximumFailedPasswordsForWipe; + } + } + return count; } } @@ -546,7 +594,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { public long getMaximumTimeToLock() { synchronized (this) { - return mActiveAdmin != null ? mActiveAdmin.maximumTimeToUnlock : 0; + final int N = mAdminList.size(); + long time = 0; + for (int i=0; i<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (time == 0) { + time = admin.maximumTimeToUnlock; + } else if (admin.maximumTimeToUnlock != 0 + && time > admin.maximumTimeToUnlock) { + time = admin.maximumTimeToUnlock; + } + } + return time; } } |