More device admin.

- Clean up device policy manager APIs.
- Implement lockNow().  For now this just turns the screen off to lock the device.
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,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
 </method>
-<method name="getMinimumPasswordLength"
+<method name="getPasswordMaximumLength"
  return="int"
  abstract="false"
  native="false"
@@ -20442,6 +20457,21 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="mode" type="int">
+</parameter>
+</method>
+<method name="getPasswordMinimumLength"
+ 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="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 @@
     /**
      * 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 @@
      * 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 @@
     /**
      * 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 @@
     /**
      * 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 @@
     }
     
     /**
-     * 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 @@
      * @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 @@
     }
     
     /**
-     * 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 @@
     }
     
     /**
+     * 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 @@
     }
     
     /**
+     * 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 @@
     }
     
     /**
-     * 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 @@
  */
 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 @@
 {
     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 @@
      * 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 int getRequestedMinimumPasswordLength() {
-        return mDevicePolicyManager.getMinimumPasswordLength();
+        return mDevicePolicyManager.getPasswordMinimumLength(null);
     }
 
     /**
@@ -132,7 +132,7 @@
      * @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.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 @@
         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<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);
         }
-        return admin;
     }
     
     void sendAdminCommandLocked(ActiveAdmin admin, String action) {
@@ -346,7 +353,7 @@
             // Ignore
         }
 
-        long timeMs = getMaximumTimeToLock();
+        long timeMs = getMaximumTimeToLock(null);
         if (timeMs <= 0) {
             timeMs = Integer.MAX_VALUE;
         }
@@ -355,7 +362,6 @@
         } catch (RemoteException e) {
             Log.w(TAG, "Failure talking with power manager", e);
         }
-        
     }
 
     public void systemReady() {
@@ -443,10 +449,16 @@
         }
     }
     
-    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 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 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 @@
             // 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 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 @@
             // 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 @@
                 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 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 @@
             // 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 @@
             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 @@
         // 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 @@
      */
     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);
         }
     }