From 254cb446faa7cb13699d8150eb4cc4f44cb61a2d Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 27 Jan 2010 19:23:59 -0800 Subject: [PATCH] More device admin. - Clean up device policy manager APIs. - Implement lockNow(). For now this just turns the screen off to lock the device. --- api/current.xml | 36 +++++- core/java/android/app/DeviceAdmin.java | 13 +- core/java/android/app/DeviceAdminInfo.java | 2 +- .../java/android/app/DevicePolicyManager.java | 68 +++++++--- .../android/app/IDevicePolicyManager.aidl | 10 +- core/java/android/os/IPowerManager.aidl | 1 + .../android/view/WindowManagerPolicy.java | 11 +- .../internal/widget/LockPatternUtils.java | 4 +- .../server/DevicePolicyManagerService.java | 116 ++++++++++++------ .../android/server/PowerManagerService.java | 20 ++- 10 files changed, 202 insertions(+), 79 deletions(-) diff --git a/api/current.xml b/api/current.xml index f73d9da19ee6a..b03f826e13d98 100644 --- a/api/current.xml +++ b/api/current.xml @@ -20421,6 +20421,19 @@ visibility="public" > + + + + + + - + + + + + + + + -The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to receive @@ -117,9 +116,9 @@ public class DeviceAdmin extends BroadcastReceiver { * Action sent to a device administrator when the user has failed at * attempted to enter the password. You can at this point check the * number of failed password attempts there have been with - * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts() + * {@link DevicePolicyManager#getCurrentFailedPasswordAttempts * DevicePolicyManager.getCurrentFailedPasswordAttempts()}. You will generally - * handle this in {@link DeviceAdmin#onPasswordFailed(Context, Intent)}. + * handle this in {@link DeviceAdmin#onPasswordFailed}. * *

The calling device admin must have requested * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to receive diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java index e50db89e8ec46..50b342b6f3370 100644 --- a/core/java/android/app/DeviceAdminInfo.java +++ b/core/java/android/app/DeviceAdminInfo.java @@ -51,7 +51,7 @@ public final class DeviceAdminInfo implements Parcelable { /** * A type of policy that this device admin can use: limit the passwords * that the user can select, via {@link DevicePolicyManager#setPasswordMode} - * and {@link DevicePolicyManager#setMinimumPasswordLength}. + * and {@link DevicePolicyManager#setPasswordMinimumLength}. * *

To control this policy, the device admin must have a "limit-password" * tag in the "uses-policies" section of its meta-data. diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java index 135851f824da8..779db3ae22753 100644 --- a/core/java/android/app/DevicePolicyManager.java +++ b/core/java/android/app/DevicePolicyManager.java @@ -89,7 +89,7 @@ public class DevicePolicyManager { /** * Activity action: have the user enter a new password. This activity * should be launched after using {@link #setPasswordMode(ComponentName, int)} - * or {@link #setMinimumPasswordLength(ComponentName, int)} to have the + * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the * user enter a new password that meets the current requirements. You can * use {@link #isActivePasswordSufficient()} to determine whether you need * to have the user select a new password in order to meet the current @@ -210,13 +210,15 @@ public class DevicePolicyManager { } /** - * Retrieve the current password mode that is in effect due to all - * device admins. + * Retrieve the current minimum password mode for all admins + * or a particular one. + * @param admin The name of the admin component to check, or null to aggregate + * all admins. */ - public int getPasswordMode() { + public int getPasswordMode(ComponentName admin) { if (mService != null) { try { - return mService.getPasswordMode(); + return mService.getPasswordMode(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -244,10 +246,10 @@ public class DevicePolicyManager { * @param length The new desired minimum password length. A value of 0 * means there is no restriction. */ - public void setMinimumPasswordLength(ComponentName admin, int length) { + public void setPasswordMinimumLength(ComponentName admin, int length) { if (mService != null) { try { - mService.setMinimumPasswordLength(admin, length); + mService.setPasswordMinimumLength(admin, length); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -255,13 +257,15 @@ public class DevicePolicyManager { } /** - * Retrieve the current minimum password length that is in effect due to all - * device admins. + * Retrieve the current minimum password length for all admins + * or a particular one. + * @param admin The name of the admin component to check, or null to aggregate + * all admins. */ - public int getMinimumPasswordLength() { + public int getPasswordMinimumLength(ComponentName admin) { if (mService != null) { try { - return mService.getMinimumPasswordLength(); + return mService.getPasswordMinimumLength(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -269,6 +273,17 @@ public class DevicePolicyManager { return 0; } + /** + * Return the maximum password length that the device supports for a + * particular password mode. + * @param mode The mode being interrogated. + * @return Returns the maximum length that the user can enter. + */ + public int getPasswordMaximumLength(int mode) { + // Kind-of arbitrary. + return 16; + } + /** * Determine whether the current password the user has set is sufficient * to meet the policy requirements (mode, minimum length) that have been @@ -334,12 +349,31 @@ public class DevicePolicyManager { } } + /** + * Retrieve the current maximum number of login attempts that are allowed + * before the device wipes itself, for all admins + * or a particular one. + * @param admin The name of the admin component to check, or null to aggregate + * all admins. + */ + public int getMaximumFailedPasswordsForWipe(ComponentName admin) { + if (mService != null) { + try { + return mService.getMaximumFailedPasswordsForWipe(admin); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return 0; + } + /** * Force a new password on the user. This takes effect immediately. The * given password must meet the current password minimum length constraint * or it will be rejected. The given password will be accepted regardless * of the current password mode, automatically adjusting the password mode - * higher if needed. (The string you give here is acceptable for any mode; + * higher if needed to meet the requirements of all active administrators. + * (The string you give here is acceptable for any mode; * if it contains only digits, that is still an acceptable alphanumeric * password.) * @@ -386,13 +420,15 @@ public class DevicePolicyManager { } /** - * Retrieve the current maximum time to lock that is in effect due to all - * device admins. Returns 0 if no maximum is set. + * Retrieve the current maximum time to unlock for all admins + * or a particular one. + * @param admin The name of the admin component to check, or null to aggregate + * all admins. */ - public long getMaximumTimeToLock() { + public long getMaximumTimeToLock(ComponentName admin) { if (mService != null) { try { - return mService.getMaximumTimeToLock(); + return mService.getMaximumTimeToLock(admin); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl index a5508cd6b2f84..8d804f98026a7 100644 --- a/core/java/android/app/IDevicePolicyManager.aidl +++ b/core/java/android/app/IDevicePolicyManager.aidl @@ -26,19 +26,21 @@ import android.os.RemoteCallback; */ interface IDevicePolicyManager { void setPasswordMode(in ComponentName who, int mode); - int getPasswordMode(); + int getPasswordMode(in ComponentName who); - void setMinimumPasswordLength(in ComponentName who, int length); - int getMinimumPasswordLength(); + void setPasswordMinimumLength(in ComponentName who, int length); + int getPasswordMinimumLength(in ComponentName who); boolean isActivePasswordSufficient(); int getCurrentFailedPasswordAttempts(); + void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num); + int getMaximumFailedPasswordsForWipe(in ComponentName admin); boolean resetPassword(String password); void setMaximumTimeToLock(in ComponentName who, long timeMs); - long getMaximumTimeToLock(); + long getMaximumTimeToLock(in ComponentName who); void lockNow(); diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index b5408ae98b2a1..dedc34773c91c 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -22,6 +22,7 @@ interface IPowerManager { void acquireWakeLock(int flags, IBinder lock, String tag); void goToSleep(long time); + void goToSleepWithReason(long time, int reason); void releaseWakeLock(IBinder lock, int flags); void userActivity(long when, boolean noChangeLights); void userActivityWithForce(long when, boolean noChangeLights, boolean force); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index bbe9c1fdbfc0e..21577bf920aee 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -357,12 +357,17 @@ public interface WindowManagerPolicy { * previous activity, and both are on top of he wallpaper. */ public final int TRANSIT_WALLPAPER_INTRA_CLOSE = 15 | TRANSIT_EXIT_MASK; + // NOTE: screen off reasons are in order of significance, with more + // important ones lower than less important ones. + + /** Screen turned off because of a device admin */ + public final int OFF_BECAUSE_OF_ADMIN = 1; /** Screen turned off because of power button */ - public final int OFF_BECAUSE_OF_USER = 1; + public final int OFF_BECAUSE_OF_USER = 2; /** Screen turned off because of timeout */ - public final int OFF_BECAUSE_OF_TIMEOUT = 2; + public final int OFF_BECAUSE_OF_TIMEOUT = 3; /** Screen turned off because of proximity sensor */ - public final int OFF_BECAUSE_OF_PROX_SENSOR = 3; + public final int OFF_BECAUSE_OF_PROX_SENSOR = 4; /** * Magic constant to {@link IWindowManager#setRotation} to not actually diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index bd41a1352c508..6347146267bdf 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -122,7 +122,7 @@ public class LockPatternUtils { } public int getRequestedMinimumPasswordLength() { - return mDevicePolicyManager.getMinimumPasswordLength(); + return mDevicePolicyManager.getPasswordMinimumLength(null); } /** @@ -132,7 +132,7 @@ public class LockPatternUtils { * @return */ public int getRequestedPasswordMode() { - int policyMode = mDevicePolicyManager.getPasswordMode(); + int policyMode = mDevicePolicyManager.getPasswordMode(null); switch (policyMode) { case DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC: return MODE_PASSWORD; diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index 7b8645f7499d8..17a3ab847f81a 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -41,8 +41,10 @@ import android.os.RecoverySystem; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.util.Log; import android.util.Xml; +import android.view.WindowManagerPolicy; import java.io.File; import java.io.FileInputStream; @@ -161,30 +163,35 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return null; } - ActiveAdmin getActiveAdminForCallerLocked(ComponentName who) - throws SecurityException { - ActiveAdmin admin = mAdminMap.get(who); - if (admin != null && admin.getUid() == Binder.getCallingUid()) { - if (who != null) { - if (!who.getPackageName().equals(admin.info.getActivityInfo().packageName) - || !who.getClassName().equals(admin.info.getActivityInfo().name)) { - throw new SecurityException("Current admin is not " + who); - } - } - return admin; - } - throw new SecurityException("Current admin is not owned by uid " + Binder.getCallingUid()); - } - ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy) throws SecurityException { - ActiveAdmin admin = getActiveAdminForCallerLocked(who); - if (!admin.info.usesPolicy(reqPolicy)) { - throw new SecurityException("Admin " + admin.info.getComponent() - + " did not specify uses-policy for: " - + admin.info.getTagForPolicy(reqPolicy)); + final int callingUid = Binder.getCallingUid(); + if (who != null) { + ActiveAdmin admin = mAdminMap.get(who); + if (admin == null) { + throw new SecurityException("No active admin " + who); + } + if (admin.getUid() != callingUid) { + throw new SecurityException("Admin " + who + " is not owned by uid " + + Binder.getCallingUid()); + } + if (!admin.info.usesPolicy(reqPolicy)) { + throw new SecurityException("Admin " + admin.info.getComponent() + + " did not specify uses-policy for: " + + admin.info.getTagForPolicy(reqPolicy)); + } + return admin; + } else { + final int N = mAdminList.size(); + for (int i=0; i= getPasswordMode() - && mActivePasswordLength >= getMinimumPasswordLength(); + return mActivePasswordMode >= getPasswordMode(null) + && mActivePasswordLength >= getPasswordMinimumLength(null); } } @@ -521,10 +539,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public int getMaximumFailedPasswordsForWipe() { + public int getMaximumFailedPasswordsForWipe(ComponentName who) { synchronized (this) { - final int N = mAdminList.size(); int count = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.maximumFailedPasswordsForWipe : count; + } + + final int N = mAdminList.size(); for (int i=0; i 0 && mFailedPasswordAttempts >= max) { wipeDataLocked(0); } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index f106fc360f09e..cefd3124f80d2 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -1101,11 +1101,10 @@ class PowerManagerService extends IPowerManager.Stub // 0 was to turn it off, and we can't strip that, because keyguard needs to come // on, so have to run the queue then. if (index == 2) { - // Also, while we're collapsing them, if it's going to be an "off," and one - // is off because of user, then use that, regardless of whether it's the first - // or second one. - if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) { - mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER; + // While we're collapsing them, if it's going off, and the new reason + // is more significant than the first, then use the new one. + if (!on && mBroadcastWhy[0] > why) { + mBroadcastWhy[0] = why; } mBroadcastQueue[0] = on ? 1 : 0; mBroadcastQueue[1] = -1; @@ -2135,10 +2134,19 @@ class PowerManagerService extends IPowerManager.Stub * This overrides all wake locks that are held. */ public void goToSleep(long time) + { + goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER); + } + + /** + * The user requested that we go to sleep (probably with the power button). + * This overrides all wake locks that are held. + */ + public void goToSleepWithReason(long time, int reason) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); synchronized (mLocks) { - goToSleepLocked(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER); + goToSleepLocked(time, reason); } }