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.
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index e13ddc8..fd42538 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import com.android.common.FastXmlSerializer;
+import com.android.internal.widget.LockPatternUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -27,11 +28,19 @@
 import android.app.DevicePolicyManager;
 import android.app.IDevicePolicyManager;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Binder;
+import android.os.IBinder;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.RecoverySystem;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
 import android.util.Log;
 import android.util.Xml;
 
@@ -49,6 +58,8 @@
     
     private final Context mContext;
 
+    IPowerManager mIPowerManager;
+    
     int mActivePasswordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
     int mActivePasswordLength = 0;
     int mFailedPasswordAttempts = 0;
@@ -75,8 +86,16 @@
         mContext = context;
     }
 
+    private IPowerManager getIPowerManager() {
+        if (mIPowerManager == null) {
+            IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
+            mIPowerManager = IPowerManager.Stub.asInterface(b);
+        }
+        return mIPowerManager;
+    }
+    
     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who) throws SecurityException {
-        if (mActiveAdmin != null && mActiveAdmin.getUid() == Binder.getCallingPid()) {
+        if (mActiveAdmin != null && mActiveAdmin.getUid() == Binder.getCallingUid()) {
             if (who != null) {
                 if (!who.getPackageName().equals(mActiveAdmin.info.getActivityInfo().packageName)
                         || !who.getClassName().equals(mActiveAdmin.info.getActivityInfo().name)) {
@@ -258,6 +277,17 @@
         if (!success) {
             Log.w(TAG, "No valid start tag found in policies file");
         }
+        
+        long timeMs = getMaximumTimeToLock();
+        if (timeMs <= 0) {
+            timeMs = Integer.MAX_VALUE;
+        }
+        try {
+            getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failure talking with power manager", e);
+        }
+        
     }
 
     public void systemReady() {
@@ -335,15 +365,6 @@
         }
     }
     
-    public int getActivePasswordMode() {
-        synchronized (this) {
-            // This API can only be called by an active device admin,
-            // so try to retrieve it to check that the caller is one.
-            getActiveAdminForCallerLocked(null);
-            return mActivePasswordMode;
-        }
-    }
-    
     public void setMinimumPasswordLength(ComponentName who, int length) {
         synchronized (this) {
             if (who == null) {
@@ -363,12 +384,13 @@
         }
     }
     
-    public int getActiveMinimumPasswordLength() {
+    public boolean isActivePasswordSufficient() {
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null);
-            return mActivePasswordLength;
+            return mActivePasswordMode >= getPasswordMode()
+                    && mActivePasswordLength >= getMinimumPasswordLength();
         }
     }
     
@@ -381,6 +403,31 @@
         }
     }
     
+    public boolean resetPassword(String password) {
+        int mode;
+        synchronized (this) {
+            // This API can only be called by an active device admin,
+            // so try to retrieve it to check that the caller is one.
+            getActiveAdminForCallerLocked(null);
+            mode = getPasswordMode();
+            if (password.length() < getMinimumPasswordLength()) {
+                return false;
+            }
+        }
+        
+        // Don't do this with the lock held, because it is going to call
+        // back in to the service.
+        long ident = Binder.clearCallingIdentity();
+        try {
+            LockPatternUtils utils = new LockPatternUtils(mContext);
+            utils.saveLockPassword(password, mode);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
+        return true;
+    }
+    
     public void setMaximumTimeToLock(ComponentName who, long timeMs) {
         synchronized (this) {
             if (who == null) {
@@ -389,7 +436,21 @@
             ActiveAdmin ap = getActiveAdminForCallerLocked(who);
             if (ap.maximumTimeToUnlock != timeMs) {
                 ap.maximumTimeToUnlock = timeMs;
-                saveSettingsLocked();
+                
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    saveSettingsLocked();
+                    if (timeMs <= 0) {
+                        timeMs = Integer.MAX_VALUE;
+                    }
+                    try {
+                        getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failure talking with power manager", e);
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
             }
         }
     }
@@ -400,17 +461,28 @@
         }
     }
     
+    public void lockNow() {
+        synchronized (this) {
+            // This API can only be called by an active device admin,
+            // so try to retrieve it to check that the caller is one.
+            getActiveAdminForCallerLocked(null);
+            // STOPSHIP need to implement.
+        }
+    }
+    
     public void wipeData(int flags) {
         synchronized (this) {
             // This API can only be called by an active device admin,
             // so try to retrieve it to check that the caller is one.
             getActiveAdminForCallerLocked(null);
-            long ident = Binder.clearCallingIdentity();
-            try {
-                Log.w(TAG, "*************** WIPE DATA HERE");
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+        }
+        long ident = Binder.clearCallingIdentity();
+        try {
+            RecoverySystem.rebootWipeUserData(mContext);
+        } catch (IOException e) {
+            Log.w(TAG, "Failed requesting data wipe", e);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
     
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index bf6996c..f106fc3 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -169,7 +169,8 @@
     private boolean mProximitySensorActive = false;
     private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
     private long mLastProximityEventTime;
-    private int mTotalDelaySetting;
+    private int mScreenOffTimeoutSetting;
+    private int mMaximumScreenOffTimeout = Integer.MAX_VALUE;
     private int mKeylightDelay;
     private int mDimDelay;
     private int mScreenOffDelay;
@@ -378,6 +379,16 @@
                 Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
     }
 
+    public void setMaximumScreenOffTimeount(int timeMs) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
+        synchronized (mLocks) {
+            mMaximumScreenOffTimeout = timeMs;
+            // recalculate everything
+            setScreenOffTimeoutsLocked();
+        }
+    }
+
     private class SettingsObserver implements Observer {
         private int getInt(String name) {
             return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
@@ -390,7 +401,7 @@
                 updateWakeLockLocked();
 
                 // SCREEN_OFF_TIMEOUT
-                mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT);
+                mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT);
 
                  // DIM_SCREEN
                 //mDimScreen = getInt(DIM_SCREEN) != 0;
@@ -935,7 +946,8 @@
         pw.println("  mPreventScreenOn=" + mPreventScreenOn
                 + "  mScreenBrightnessOverride=" + mScreenBrightnessOverride
                 + "  mButtonBrightnessOverride=" + mButtonBrightnessOverride);
-        pw.println("  mTotalDelaySetting=" + mTotalDelaySetting);
+        pw.println("  mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting
+                + " mMaximumScreenOffTimeout=" + mMaximumScreenOffTimeout);
         pw.println("  mLastScreenOnTime=" + mLastScreenOnTime);
         pw.println("  mBroadcastWakeLock=" + mBroadcastWakeLock);
         pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
@@ -2285,7 +2297,10 @@
             mDimDelay = -1;
             mScreenOffDelay = 0;
         } else {
-            int totalDelay = mTotalDelaySetting;
+            int totalDelay = mScreenOffTimeoutSetting;
+            if (totalDelay > mMaximumScreenOffTimeout) {
+                totalDelay = mMaximumScreenOffTimeout;
+            }
             mKeylightDelay = LONG_KEYLIGHT_DELAY;
             if (totalDelay < 0) {
                 mScreenOffDelay = Integer.MAX_VALUE;