diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a85a558fa3640..8ed4a86e9b60a 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -174,6 +174,12 @@ interface IWindowManager */ int watchRotation(IRotationWatcher watcher); + /** + * Remove a rotation watcher set using watchRotation. + * @hide + */ + void removeRotationWatcher(IRotationWatcher watcher); + /** * Determine the preferred edge of the screen to pin the compact options menu against. * @return a Gravity value for the options menu panel diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java index 4df434c7895c0..965e3786439f8 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardFaceUnlockView.java @@ -18,17 +18,22 @@ package com.android.internal.policy.impl.keyguard; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.PowerManager; +import android.os.RemoteException; +import android.os.ServiceManager; import android.telephony.TelephonyManager; import android.util.AttributeSet; import android.util.Log; +import android.view.IRotationWatcher; +import android.view.IWindowManager; import android.view.View; import android.widget.ImageButton; import android.widget.LinearLayout; import com.android.internal.R; - import com.android.internal.widget.LockPatternUtils; +import java.lang.Math; + public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView { private static final String TAG = "FULKeyguardFaceUnlockView"; @@ -45,6 +50,30 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu private boolean mIsShowing = false; private final Object mIsShowingLock = new Object(); + private int mLastRotation; + private boolean mWatchingRotation; + private final IWindowManager mWindowManager = + IWindowManager.Stub.asInterface(ServiceManager.getService("window")); + + private final IRotationWatcher mRotationWatcher = new IRotationWatcher.Stub() { + public void onRotationChanged(int rotation) { + if (DEBUG) Log.d(TAG, "onRotationChanged(): " + mLastRotation + "->" + rotation); + + // If the difference between the new rotation value and the previous rotation value is + // equal to 2, the rotation change was 180 degrees. This stops the biometric unlock + // and starts it in the new position. This is not performed for 90 degree rotations + // since a 90 degree rotation is a configuration change, which takes care of this for + // us. + if (Math.abs(rotation - mLastRotation) == 2) { + if (mBiometricUnlock != null) { + mBiometricUnlock.stop(); + maybeStartBiometricUnlock(); + } + } + mLastRotation = rotation; + } + }; + public KeyguardFaceUnlockView(Context context) { this(context, null); } @@ -91,6 +120,14 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu mBiometricUnlock.stop(); } KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback); + if (mWatchingRotation) { + try { + mWindowManager.removeRotationWatcher(mRotationWatcher); + mWatchingRotation = false; + } catch (RemoteException e) { + Log.e(TAG, "Remote exception when removing rotation watcher"); + } + } } @Override @@ -100,6 +137,14 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu mBiometricUnlock.stop(); } KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mUpdateCallback); + if (mWatchingRotation) { + try { + mWindowManager.removeRotationWatcher(mRotationWatcher); + mWatchingRotation = false; + } catch (RemoteException e) { + Log.e(TAG, "Remote exception when removing rotation watcher"); + } + } } @Override @@ -108,6 +153,17 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu mIsShowing = KeyguardUpdateMonitor.getInstance(mContext).isKeyguardVisible(); maybeStartBiometricUnlock(); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateCallback); + + // Registers a callback which handles stopping the biometric unlock and restarting it in + // the new position for a 180 degree rotation change. + if (!mWatchingRotation) { + try { + mLastRotation = mWindowManager.watchRotation(mRotationWatcher); + mWatchingRotation = true; + } catch (RemoteException e) { + Log.e(TAG, "Remote exception when adding rotation watcher"); + } + } } @Override @@ -172,9 +228,15 @@ public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecu return; } - // TODO: Some of these conditions are handled in KeyguardSecurityModel and may not be - // necessary here. + // Although these same conditions are handled in KeyguardSecurityModel, they are still + // necessary here. When a tablet is rotated 90 degrees, a configuration change is + // triggered and everything is torn down and reconstructed. That means + // KeyguardSecurityModel gets a chance to take care of the logic and doesn't even + // reconstruct KeyguardFaceUnlockView if the biometric unlock should be suppressed. + // However, for a 180 degree rotation, no configuration change is triggered, so only + // the logic here is capable of suppressing Face Unlock. if (monitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE + && monitor.isAlternateUnlockEnabled() && !monitor.getMaxBiometricUnlockAttemptsReached() && !backupIsTimedOut) { mBiometricUnlock.start(); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 34052f34e18a0..cbc42ebe3a2b0 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -5803,6 +5803,19 @@ public class WindowManagerService extends IWindowManager.Stub } } + @Override + public void removeRotationWatcher(IRotationWatcher watcher) { + final IBinder watcherBinder = watcher.asBinder(); + synchronized (mWindowMap) { + for (int i=0; i