From df83afaf299666e99c519aa86e7e082b7c116e95 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 20 Jan 2010 13:37:26 -0800 Subject: More device policy manager / admin work. Update API with some new features, re-arrange how you check for valid passwords, and start hooking up the back-end implementation. --- core/java/android/app/DevicePolicyManager.java | 114 +++++++++++++-------- core/java/android/app/IDevicePolicyManager.aidl | 7 +- core/java/android/os/IPowerManager.aidl | 1 + .../android/internal/widget/LockPatternUtils.java | 58 +++++++---- 4 files changed, 115 insertions(+), 65 deletions(-) (limited to 'core') diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java index 4fdfe0a..538ba5b 100644 --- a/core/java/android/app/DevicePolicyManager.java +++ b/core/java/android/app/DevicePolicyManager.java @@ -79,9 +79,10 @@ 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 - * user enter a new password that meets the current requirements. If the - * current password is sufficient, the activity will exit immediately without - * being displayed to the user. Upon receiving a result from this activity, + * 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 + * constraints. Upon being resumed from this activity, * you can check the new password characteristics to see if they are * sufficient. */ @@ -122,21 +123,31 @@ public class DevicePolicyManager { /** * Constant for {@link #setPasswordMode}: the policy has no requirements - * for the password. + * for the password. Note that mode constants are ordered so that higher + * values are more restrictive. */ public static final int PASSWORD_MODE_UNSPECIFIED = 0; /** + * Constant for {@link #setPasswordMode}: the policy requires some kind + * of password, but doesn't care what it is. Note that mode constants + * are ordered so that higher values are more restrictive. + */ + public static final int PASSWORD_MODE_SOMETHING = 1000; + + /** * Constant for {@link #setPasswordMode}: the user must have at least a - * numeric password. + * numeric password. Note that mode constants are ordered so that higher + * values are more restrictive. */ - public static final int PASSWORD_MODE_NUMERIC = 1000; + public static final int PASSWORD_MODE_NUMERIC = 2000; /** * Constant for {@link #setPasswordMode}: the user must have at least an - * alphanumeric password. + * alphanumeric password. Note that mode constants are ordered so that higher + * values are more restrictive. */ - public static final int PASSWORD_MODE_ALPHANUMERIC = 2000; + public static final int PASSWORD_MODE_ALPHANUMERIC = 3000; /** * Called by an application that is administering the device to set the @@ -147,10 +158,15 @@ public class DevicePolicyManager { * take place immediately. To prompt the user for a new password, use * {@link #ACTION_SET_NEW_PASSWORD} after setting this value. * + *

Mode constants are ordered so that higher values are more restrictive; + * thus the highest requested mode constant (between the policy set here, + * the user's preference, and any other considerations) is the one that + * is in effect. + * * @param admin Which {@link DeviceAdmin} this request is associated with. * @param mode The new desired mode. One of - * {@link #PASSWORD_MODE_UNSPECIFIED}, {@link #PASSWORD_MODE_NUMERIC}, - * or {@link #PASSWORD_MODE_ALPHANUMERIC}. + * {@link #PASSWORD_MODE_UNSPECIFIED}, {@link #PASSWORD_MODE_SOMETHING}, + * {@link #PASSWORD_MODE_NUMERIC}, or {@link #PASSWORD_MODE_ALPHANUMERIC}. */ public void setPasswordMode(ComponentName admin, int mode) { if (mService != null) { @@ -178,21 +194,6 @@ public class DevicePolicyManager { } /** - * Retrieve the password mode associated with the last password the - * user selected. - */ - public int getActivePasswordMode() { - if (mService != null) { - try { - return mService.getActivePasswordMode(); - } catch (RemoteException e) { - Log.w(TAG, "Failed talking with device policy service", e); - } - } - return PASSWORD_MODE_UNSPECIFIED; - } - - /** * Called by an application that is administering the device to set the * minimum allowed password length. After setting this, the user * will not be able to enter a new password that is not at least as @@ -234,18 +235,22 @@ public class DevicePolicyManager { } /** - * Retrieve the password length associated with the last password the - * user selected. + * Determine whether the current password the user has set is sufficient + * to meet the policy requirements (mode, minimum length) that have been + * requested. + * + * @return Returns true if the password meets the current requirements, + * else false. */ - public int getActiveMinimumPasswordLength() { + public boolean isActivePasswordSufficient() { if (mService != null) { try { - return mService.getActiveMinimumPasswordLength(); + return mService.isActivePasswordSufficient(); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } } - return 0; + return false; } /** @@ -262,6 +267,30 @@ public class DevicePolicyManager { } return -1; } + + /** + * 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; + * if it contains only digits, that is still an acceptable alphanumeric + * password.) + * + * @param password The new password for the user. + * @return Returns true if the password was applied, or false if it is + * not acceptable for the current constraints. + */ + public boolean resetPassword(String password) { + if (mService != null) { + try { + return mService.resetPassword(password); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } /** * Called by an application that is administering the device to set the @@ -298,22 +327,25 @@ public class DevicePolicyManager { } /** - * Constant for {@link #wipeData}: perform a low-level format of data - * storage. + * Make the device lock immediately, as if the lock screen timeout has + * expired at the point of this call. */ - public static final int WIPE_LOW_LEVEL_FORMAT = 0x0001; - - /** - * Constant for {@link #wipeData}: also wipe any external storage. - */ - public static final int WIPE_EXTERNAL_STORAGE = 0x0002; + public void lockNow() { + if (mService != null) { + try { + mService.lockNow(); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + } /** * Ask the user date be wiped. This will cause the device to reboot, - * erasing all user data while next booting up. + * erasing all user data while next booting up. External storage such + * as SD cards will not be erased. * - * @param flags Bit mask of additional options: currently - * {@link #WIPE_LOW_LEVEL_FORMAT} and {@link #WIPE_EXTERNAL_STORAGE}. + * @param flags Bit mask of additional options: currently must be 0. */ public void wipeData(int flags) { if (mService != null) { diff --git a/core/java/android/app/IDevicePolicyManager.aidl b/core/java/android/app/IDevicePolicyManager.aidl index f62647f..7e38194 100644 --- a/core/java/android/app/IDevicePolicyManager.aidl +++ b/core/java/android/app/IDevicePolicyManager.aidl @@ -26,17 +26,20 @@ import android.content.ComponentName; interface IDevicePolicyManager { void setPasswordMode(in ComponentName who, int mode); int getPasswordMode(); - int getActivePasswordMode(); void setMinimumPasswordLength(in ComponentName who, int length); int getMinimumPasswordLength(); - int getActiveMinimumPasswordLength(); + boolean isActivePasswordSufficient(); int getCurrentFailedPasswordAttempts(); + boolean resetPassword(String password); + void setMaximumTimeToLock(in ComponentName who, long timeMs); long getMaximumTimeToLock(); + void lockNow(); + void wipeData(int flags); void setActiveAdmin(in ComponentName policyReceiver); diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 23762ca..b5408ae 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -28,6 +28,7 @@ interface IPowerManager void setPokeLock(int pokey, IBinder lock, String tag); int getSupportedWakeLockFlags(); void setStayOnSetting(int val); + void setMaximumScreenOffTimeount(int timeMs); void preventScreenOn(boolean prevent); boolean isScreenOn(); void reboot(String reason); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 9f7a370..66c0719 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -79,9 +79,9 @@ public class LockPatternUtils { * pin = digit-only password * password = alphanumeric password */ - public static final int MODE_PATTERN = 0; - public static final int MODE_PIN = 1; - public static final int MODE_PASSWORD = 2; + public static final int MODE_PATTERN = DevicePolicyManager.PASSWORD_MODE_SOMETHING; + public static final int MODE_PIN = DevicePolicyManager.PASSWORD_MODE_NUMERIC; + public static final int MODE_PASSWORD = DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC; /** * The minimum number of dots the user must include in a wrong pattern @@ -95,6 +95,7 @@ public class LockPatternUtils { private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen"; public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type"; + private final Context mContext; private final ContentResolver mContentResolver; private DevicePolicyManager mDevicePolicyManager; private static String sLockPatternFilename; @@ -104,6 +105,7 @@ public class LockPatternUtils { * @param contentResolver Used to look up and save settings. */ public LockPatternUtils(Context context) { + mContext = context; mContentResolver = context.getContentResolver(); mDevicePolicyManager = (DevicePolicyManager)context.getSystemService(Context.DEVICE_POLICY_SERVICE); @@ -126,10 +128,6 @@ public class LockPatternUtils { return mDevicePolicyManager.getMinimumPasswordLength(); } - public int getActiveMinimumPasswordLength() { - return mDevicePolicyManager.getActiveMinimumPasswordLength(); - } - /** * Gets the device policy password mode. If the mode is non-specific, returns * MODE_PATTERN which allows the user to choose anything. @@ -154,10 +152,6 @@ public class LockPatternUtils { * * @return */ - public int getActivePasswordMode() { - return mDevicePolicyManager.getActivePasswordMode(); - } - public void reportFailedPasswordAttempt() { mDevicePolicyManager.reportFailedPasswordAttempt(); } @@ -279,6 +273,16 @@ public class LockPatternUtils { } /** + * Clear any lock pattern or password. + */ + public void clearLock() { + saveLockPassword(null, LockPatternUtils.MODE_PATTERN); + setLockPatternEnabled(false); + saveLockPattern(null); + setLong(PASSWORD_TYPE_KEY, MODE_PATTERN); + } + + /** * Save a lock pattern. * @param pattern The new pattern to save. */ @@ -295,11 +299,13 @@ public class LockPatternUtils { raf.write(hash, 0, hash.length); } raf.close(); - setBoolean(PATTERN_EVER_CHOSEN_KEY, true); - setLong(PASSWORD_TYPE_KEY, MODE_PATTERN); - if (pattern != null && isDevicePolicyActive()) { - setActivePasswordState(DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED, - pattern.size()); + if (pattern != null) { + setBoolean(PATTERN_EVER_CHOSEN_KEY, true); + setLong(PASSWORD_TYPE_KEY, MODE_PATTERN); + DevicePolicyManager dpm = (DevicePolicyManager)mContext.getSystemService( + Context.DEVICE_POLICY_SERVICE); + dpm.setActivePasswordState( + DevicePolicyManager.PASSWORD_MODE_SOMETHING, pattern.size()); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings provider @@ -314,9 +320,8 @@ public class LockPatternUtils { * Save a lock password. * @param password The password to save */ - public void saveLockPassword(String password) { + public void saveLockPassword(String password, int mode) { // Compute the hash - boolean numericHint = password != null ? TextUtils.isDigitsOnly(password) : false; final byte[] hash = LockPatternUtils.passwordToHash(password); try { // Write the hash to file @@ -328,10 +333,15 @@ public class LockPatternUtils { raf.write(hash, 0, hash.length); } raf.close(); - setLong(PASSWORD_TYPE_KEY, numericHint ? MODE_PIN : MODE_PASSWORD); - if (password != null && isDevicePolicyActive()) { - setActivePasswordState(numericHint ? DevicePolicyManager.PASSWORD_MODE_NUMERIC - : DevicePolicyManager.PASSWORD_MODE_ALPHANUMERIC, password.length()); + if (password != null) { + int textMode = TextUtils.isDigitsOnly(password) ? MODE_PIN : MODE_PASSWORD; + if (textMode > mode) { + mode = textMode; + } + setLong(PASSWORD_TYPE_KEY, mode); + DevicePolicyManager dpm = (DevicePolicyManager)mContext.getSystemService( + Context.DEVICE_POLICY_SERVICE); + dpm.setActivePasswordState(mode, password.length()); } } catch (FileNotFoundException fnfe) { // Cant do much, unless we want to fail over to using the settings provider @@ -554,6 +564,7 @@ public class LockPatternUtils { } private boolean getBoolean(String systemSettingKey) { + // STOPSHIP: these need to be moved to secure settings! return 1 == android.provider.Settings.System.getInt( mContentResolver, @@ -561,6 +572,7 @@ public class LockPatternUtils { } private void setBoolean(String systemSettingKey, boolean enabled) { + // STOPSHIP: these need to be moved to secure settings! android.provider.Settings.System.putInt( mContentResolver, systemSettingKey, @@ -568,10 +580,12 @@ public class LockPatternUtils { } private long getLong(String systemSettingKey, long def) { + // STOPSHIP: these need to be moved to secure settings! return android.provider.Settings.System.getLong(mContentResolver, systemSettingKey, def); } private void setLong(String systemSettingKey, long value) { + // STOPSHIP: these need to be moved to secure settings! android.provider.Settings.System.putLong(mContentResolver, systemSettingKey, value); } -- cgit v1.1