Fix 2737842: disable keyguard API when device policy is enabled.

This fix disables KeyguardManager's enable/disable API when any
device policy admin requests a policy that enforces a password.

Change-Id: Idb1da16b14ed8963142f7b1f62d2b060d84ffa65
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 0c07553..34a43bf 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -53,6 +53,9 @@
          *
          * A good place to call this is from {@link android.app.Activity#onResume()}
          *
+         * Note: This call has no effect while any {@link DevicePolicyManager} is enabled
+         * that requires a password.
+         *
          * @see #reenableKeyguard()
          */
         public void disableKeyguard() {
@@ -66,7 +69,10 @@
          * Reenable the keyguard.  The keyguard will reappear if the previous
          * call to {@link #disableKeyguard()} caused it it to be hidden.
          *
-         * A good place to call this is from {@link android.app.Activity#onPause()} 
+         * A good place to call this is from {@link android.app.Activity#onPause()}
+         *
+         * Note: This call has no effect while any {@link DevicePolicyManager} is enabled
+         * that requires a password.
          *
          * @see #disableKeyguard()
          */
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 53de7d9..e13f0af 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -54,6 +54,7 @@
 import android.Manifest;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -86,6 +87,7 @@
 import android.provider.Settings;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseIntArray;
 import android.view.Display;
@@ -4171,13 +4173,31 @@
     // Misc IWindowSession methods
     // -------------------------------------------------------------
 
+    private boolean allowDisableKeyguard()
+    {
+        // We fail safe if this gets called before the service has started.
+        boolean allow = false;
+        DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+        if (dpm != null) {
+            allow = dpm.getPasswordQuality(null)
+                    == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+        }
+        return allow;
+    }
+
     public void disableKeyguard(IBinder token, String tag) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
             != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
-        synchronized (mKeyguardTokenWatcher) {
-            mKeyguardTokenWatcher.acquire(token, tag);
+
+        if (allowDisableKeyguard()) {
+            synchronized (mKeyguardTokenWatcher) {
+                mKeyguardTokenWatcher.acquire(token, tag);
+            }
+        } else {
+            Log.w(TAG, tag + ": disableKeyguard() ignored while DevicePolicyAmin is enabled.");
         }
     }
 
@@ -4186,25 +4206,30 @@
             != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires DISABLE_KEYGUARD permission");
         }
-        synchronized (mKeyguardTokenWatcher) {
-            mKeyguardTokenWatcher.release(token);
 
-            if (!mKeyguardTokenWatcher.isAcquired()) {
-                // If we are the last one to reenable the keyguard wait until
-                // we have actaully finished reenabling until returning.
-                // It is possible that reenableKeyguard() can be called before
-                // the previous disableKeyguard() is handled, in which case
-                // neither mKeyguardTokenWatcher.acquired() or released() would
-                // be called.  In that case mKeyguardDisabled will be false here
-                // and we have nothing to wait for.
-                while (mKeyguardDisabled) {
-                    try {
-                        mKeyguardTokenWatcher.wait();
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
+        if (allowDisableKeyguard()) {
+            synchronized (mKeyguardTokenWatcher) {
+                mKeyguardTokenWatcher.release(token);
+
+                if (!mKeyguardTokenWatcher.isAcquired()) {
+                    // If we are the last one to reenable the keyguard wait until
+                    // we have actaully finished reenabling until returning.
+                    // It is possible that reenableKeyguard() can be called before
+                    // the previous disableKeyguard() is handled, in which case
+                    // neither mKeyguardTokenWatcher.acquired() or released() would
+                    // be called.  In that case mKeyguardDisabled will be false here
+                    // and we have nothing to wait for.
+                    while (mKeyguardDisabled) {
+                        try {
+                            mKeyguardTokenWatcher.wait();
+                        } catch (InterruptedException e) {
+                            Thread.currentThread().interrupt();
+                        }
                     }
                 }
             }
+        } else {
+            Log.w(TAG, "reenableKeyguard() ignored while DevicePolicyAmin is enabled.");
         }
     }