Fix 5863053: Add method to lock screen immediately.

This fixes a bug where the device fails to lock when DevicePolicyManagerService
requests the device to be locked and the screen was off because the user hit
the power button.

The change allows DPMS to directly invoke screen lock, bypasssing the screen state.

Change-Id: Iecdda6fc61e9c519119de495be23c69c3b983921
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 93a9d50..c54d09e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -229,4 +229,9 @@
      * Device has a software navigation bar (separate from the status bar).
      */
     boolean hasNavigationBar();
+
+    /**
+     * Lock the device immediately.
+     */
+    void lockNow();
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 924cb53..41c225d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1023,6 +1023,11 @@
     public boolean hasNavigationBar();
 
     /**
+     * Lock the device now.
+     */
+    public void lockNow();
+
+    /**
      * Print the WindowManagerPolicy's state into the given stream.
      *
      * @param prefix Text to print at the front of each line.
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0b223c1..6e16391 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3488,6 +3488,12 @@
         }
     };
 
+    public void lockNow() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+        mHandler.removeCallbacks(mScreenLockTimeout);
+        mHandler.post(mScreenLockTimeout);
+    }
+
     private void updateLockScreenTimeout() {
         synchronized (mScreenLockTimeout) {
             boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && mKeyguardMediator.isSecure());
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index e8ca3ce..d8e3d59 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -60,6 +60,7 @@
 import android.util.Printer;
 import android.util.Slog;
 import android.util.Xml;
+import android.view.IWindowManager;
 import android.view.WindowManagerPolicy;
 
 import java.io.File;
@@ -96,6 +97,7 @@
     final PowerManager.WakeLock mWakeLock;
 
     IPowerManager mIPowerManager;
+    IWindowManager mIWindowManager;
 
     int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
     int mActivePasswordLength = 0;
@@ -506,6 +508,14 @@
         return mIPowerManager;
     }
 
+    private IWindowManager getWindowManager() {
+        if (mIWindowManager == null) {
+            IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
+            mIWindowManager = IWindowManager.Stub.asInterface(b);
+        }
+        return mIWindowManager;
+    }
+
     ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
         ActiveAdmin admin = mAdminMap.get(who);
         if (admin != null
@@ -1649,8 +1659,11 @@
                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
             long ident = Binder.clearCallingIdentity();
             try {
+                // Power off the display
                 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
                         WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
+                // Ensure the device is locked
+                getWindowManager().lockNow();
             } catch (RemoteException e) {
             } finally {
                 Binder.restoreCallingIdentity(ident);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index f5c2de9..9fb064f 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -9411,6 +9411,10 @@
         return mPolicy.hasNavigationBar();
     }
 
+    public void lockNow() {
+        mPolicy.lockNow();
+    }
+
     void dumpInput(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
         pw.println("WINDOW MANAGER INPUT (dumpsys window input)");
         mInputManager.dump(pw);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 1e66ca2..516725e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -471,4 +471,8 @@
     public boolean hasNavigationBar() {
         return false; // should this return something else?
     }
+
+    public void lockNow() {
+        // TODO Auto-generated method stub
+    }
 }