diff options
-rw-r--r-- | api/current.xml | 36 | ||||
-rw-r--r-- | core/java/android/app/DeviceAdmin.java | 13 | ||||
-rw-r--r-- | core/java/android/app/DeviceAdminInfo.java | 2 | ||||
-rw-r--r-- | core/java/android/app/DevicePolicyManager.java | 68 | ||||
-rw-r--r-- | core/java/android/app/IDevicePolicyManager.aidl | 10 | ||||
-rw-r--r-- | core/java/android/os/IPowerManager.aidl | 1 | ||||
-rw-r--r-- | core/java/android/view/WindowManagerPolicy.java | 11 | ||||
-rw-r--r-- | core/java/com/android/internal/widget/LockPatternUtils.java | 4 | ||||
-rw-r--r-- | services/java/com/android/server/DevicePolicyManagerService.java | 114 | ||||
-rw-r--r-- | services/java/com/android/server/PowerManagerService.java | 20 |
10 files changed, 201 insertions, 78 deletions
diff --git a/api/current.xml b/api/current.xml index f73d9da..b03f826 100644 --- a/api/current.xml +++ b/api/current.xml @@ -20421,6 +20421,19 @@ visibility="public" > </method> +<method name="getMaximumFailedPasswordsForWipe" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="admin" type="android.content.ComponentName"> +</parameter> +</method> <method name="getMaximumTimeToLock" return="long" abstract="false" @@ -20431,8 +20444,23 @@ deprecated="not deprecated" visibility="public" > +<parameter name="admin" type="android.content.ComponentName"> +</parameter> +</method> +<method name="getPasswordMaximumLength" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="mode" type="int"> +</parameter> </method> -<method name="getMinimumPasswordLength" +<method name="getPasswordMinimumLength" return="int" abstract="false" native="false" @@ -20442,6 +20470,8 @@ deprecated="not deprecated" visibility="public" > +<parameter name="admin" type="android.content.ComponentName"> +</parameter> </method> <method name="getPasswordMode" return="int" @@ -20453,6 +20483,8 @@ deprecated="not deprecated" visibility="public" > +<parameter name="admin" type="android.content.ComponentName"> +</parameter> </method> <method name="isActivePasswordSufficient" return="boolean" @@ -20545,7 +20577,7 @@ <parameter name="timeMs" type="long"> </parameter> </method> -<method name="setMinimumPasswordLength" +<method name="setPasswordMinimumLength" return="void" abstract="false" native="false" diff --git a/core/java/android/app/DeviceAdmin.java b/core/java/android/app/DeviceAdmin.java index 88fdab2..b9a84b7 100644 --- a/core/java/android/app/DeviceAdmin.java +++ b/core/java/android/app/DeviceAdmin.java @@ -99,11 +99,10 @@ public class DeviceAdmin extends BroadcastReceiver { /** * Action sent to a device administrator when the user has changed the * password of their device. You can at this point check the characteristics - * of the new password with {@link DevicePolicyManager#getPasswordMode() - * DevicePolicyManager.getActivePasswordMode()} and - * {@link DevicePolicyManager#getMinimumPasswordLength() - * DevicePolicyManager.getMinimumPasswordLength()}. You will generally - * handle this in {@link DeviceAdmin#onPasswordChanged(Context, Intent)}. + * of the new password with {@link DevicePolicyManager#isActivePasswordSufficient() + * DevicePolicyManager.isActivePasswordSufficient()}. + * You will generally + * handle this in {@link DeviceAdmin#onPasswordChanged}. * * <p>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}. * * <p>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 e50db89..50b342b 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}. * * <p>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 135851f..779db3a 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); } @@ -270,6 +274,17 @@ public class DevicePolicyManager { } /** + * 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 * requested. @@ -335,11 +350,30 @@ 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 a5508cd..8d804f9 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 b5408ae..dedc347 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 bbe9c1f..21577bf 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 bd41a13..6347146 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 7b8645f..17a3ab8 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) + ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy) 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); - } + 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<N; i++) { + ActiveAdmin admin = mAdminList.get(i); + if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) { + return admin; + } + } + throw new SecurityException("No active admin owned by uid " + + Binder.getCallingUid() + " for policy #" + reqPolicy); } - 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)); - } - return admin; } void sendAdminCommandLocked(ActiveAdmin admin, String action) { @@ -346,7 +353,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // Ignore } - long timeMs = getMaximumTimeToLock(); + long timeMs = getMaximumTimeToLock(null); if (timeMs <= 0) { timeMs = Integer.MAX_VALUE; } @@ -355,7 +362,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } catch (RemoteException e) { Log.w(TAG, "Failure talking with power manager", e); } - } public void systemReady() { @@ -443,10 +449,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public int getPasswordMode() { + public int getPasswordMode(ComponentName who) { synchronized (this) { - final int N = mAdminList.size(); int mode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.passwordMode : mode; + } + + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); if (mode < admin.passwordMode) { @@ -457,7 +469,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public void setMinimumPasswordLength(ComponentName who, int length) { + public void setPasswordMinimumLength(ComponentName who, int length) { synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -471,10 +483,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public int getMinimumPasswordLength() { + public int getPasswordMinimumLength(ComponentName who) { synchronized (this) { - final int N = mAdminList.size(); int length = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.minimumPasswordLength : length; + } + + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); if (length < admin.minimumPasswordLength) { @@ -491,8 +509,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD); - return mActivePasswordMode >= 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<N; i++) { ActiveAdmin admin = mAdminList.get(i); if (count == 0) { @@ -545,8 +569,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD); - mode = getPasswordMode(); - if (password.length() < getMinimumPasswordLength()) { + mode = getPasswordMode(null); + if (password.length() < getPasswordMinimumLength(null)) { return false; } } @@ -577,9 +601,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long ident = Binder.clearCallingIdentity(); try { saveSettingsLocked(); + + timeMs = getMaximumTimeToLock(null); if (timeMs <= 0) { timeMs = Integer.MAX_VALUE; } + try { getIPowerManager().setMaximumScreenOffTimeount((int)timeMs); } catch (RemoteException e) { @@ -592,10 +619,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - public long getMaximumTimeToLock() { + public long getMaximumTimeToLock(ComponentName who) { synchronized (this) { - final int N = mAdminList.size(); long time = 0; + + if (who != null) { + ActiveAdmin admin = getActiveAdminUncheckedLocked(who); + return admin != null ? admin.maximumTimeToUnlock : time; + } + + final int N = mAdminList.size(); for (int i=0; i<N; i++) { ActiveAdmin admin = mAdminList.get(i); if (time == 0) { @@ -615,7 +648,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { // so try to retrieve it to check that the caller is one. getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_FORCE_LOCK); - // STOPSHIP need to implement. + long ident = Binder.clearCallingIdentity(); + try { + mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(), + WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } } @@ -702,7 +742,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { try { mFailedPasswordAttempts++; saveSettingsLocked(); - int max = getMaximumFailedPasswordsForWipe(); + int max = getMaximumFailedPasswordsForWipe(null); if (max > 0 && mFailedPasswordAttempts >= max) { wipeDataLocked(0); } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index f106fc3..cefd312 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; @@ -2136,9 +2135,18 @@ class PowerManagerService extends IPowerManager.Stub */ 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); } } |