summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Colonna <bcolonna@google.com>2012-04-09 13:25:37 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-04-09 13:25:37 -0700
commit82920edd89edda7d8f706d9dce79842586dc8de5 (patch)
tree0b6b7d46056e561de27dfb509725941d6bb3f614
parentd9b2070f5c7ba14f12f1777d24dc333db7c9fd40 (diff)
parent9431366ecb4b6e4a87c0047c36548aa0bc23f2b1 (diff)
downloadframeworks_base-82920edd89edda7d8f706d9dce79842586dc8de5.zip
frameworks_base-82920edd89edda7d8f706d9dce79842586dc8de5.tar.gz
frameworks_base-82920edd89edda7d8f706d9dce79842586dc8de5.tar.bz2
Merge "Separated FUL functionality from LockPatternKeyguardView"
-rw-r--r--policy/src/com/android/internal/policy/impl/FaceUnlock.java375
-rw-r--r--policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java367
2 files changed, 401 insertions, 341 deletions
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
new file mode 100644
index 0000000..2ae99e6
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy.impl;
+
+import com.android.internal.R;
+import com.android.internal.policy.IFaceLockCallback;
+import com.android.internal.policy.IFaceLockInterface;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.View;
+
+public class FaceUnlock implements Handler.Callback {
+
+ private static final boolean DEBUG = false;
+ private static final String TAG = "FULLockscreen";
+
+ private final Context mContext;
+ private final KeyguardUpdateMonitor mUpdateMonitor;
+
+ private IFaceLockInterface mService;
+ private boolean mBoundToService = false;
+ private View mAreaView;
+
+ private Handler mHandler;
+ private final int MSG_SHOW_AREA_VIEW = 0;
+ private final int MSG_HIDE_AREA_VIEW = 1;
+
+ private boolean mServiceRunning = false;
+ private final Object mServiceRunningLock = new Object();
+
+ // Long enough to stay visible while dialer comes up
+ // Short enough to not be visible if the user goes back immediately
+ private final int VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
+
+ // Long enough to stay visible while the service starts
+ // Short enough to not have to wait long for backup if service fails to start or crashes
+ // The service can take a couple of seconds to start on the first try after boot
+ private final int VIEW_AREA_SERVICE_TIMEOUT = 3000;
+
+ // So the user has a consistent amount of time when brought to the backup method from FaceLock
+ private final int BACKUP_LOCK_TIMEOUT = 5000;
+
+ /**
+ * Used to lookup the state of the lock pattern
+ */
+ private final LockPatternUtils mLockPatternUtils;
+
+ KeyguardScreenCallback mKeyguardScreenCallback;
+
+ public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
+ LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
+ mContext = context;
+ mUpdateMonitor = updateMonitor;
+ mLockPatternUtils = lockPatternUtils;
+ mKeyguardScreenCallback = keyguardScreenCallback;
+ mHandler = new Handler(this);
+ }
+
+ public void cleanUp() {
+ if (mService != null) {
+ try {
+ mService.unregisterCallback(mFaceLockCallback);
+ } catch (RemoteException e) {
+ // Not much we can do
+ }
+ stop();
+ mService = null;
+ }
+ }
+
+ /** When screen is turned on and focused, need to bind to FaceLock service if we are using
+ * FaceLock, but only if we're not dealing with a call
+ */
+ public void activateIfAble(boolean hasOverlay) {
+ final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
+ final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
+ final boolean backupIsTimedOut =
+ (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+ if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
+ if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
+ && installedAndSelected()
+ && !hasOverlay
+ && !tooManyFaceUnlockTries
+ && !backupIsTimedOut) {
+ bind();
+
+ // Show FaceLock area, but only for a little bit so lockpattern will become visible if
+ // FaceLock fails to start or crashes
+ showAreaWithTimeout(VIEW_AREA_SERVICE_TIMEOUT);
+
+ // When switching between portrait and landscape view while FaceLock is running, the
+ // screen will eventually go dark unless we poke the wakelock when FaceLock is
+ // restarted
+ mKeyguardScreenCallback.pokeWakelock();
+ } else {
+ hideArea();
+ }
+ }
+
+ public boolean isServiceRunning() {
+ return mServiceRunning;
+ }
+
+ public int viewAreaEmergencyDialerTimeout() {
+ return VIEW_AREA_EMERGENCY_DIALER_TIMEOUT;
+ }
+
+ // Indicates whether FaceLock is in use
+ public boolean installedAndSelected() {
+ return (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled());
+ }
+
+ // Takes care of FaceLock area when layout is created
+ public void initializeAreaView(View view) {
+ if (installedAndSelected()) {
+ mAreaView = view.findViewById(R.id.faceLockAreaView);
+ if (mAreaView == null) {
+ Log.e(TAG, "Layout does not have areaView and FaceLock is enabled");
+ }
+ } else {
+ mAreaView = null; // Set to null if not using FaceLock
+ }
+ }
+
+ // Stops FaceLock if it is running and reports back whether it was running or not
+ public boolean stopIfRunning() {
+ if (installedAndSelected() && mBoundToService) {
+ stopAndUnbind();
+ return true;
+ }
+ return false;
+ }
+
+ // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
+ // This needs to be done in a handler because the call could be coming from a callback from the
+ // FaceLock service that is in a thread that can't modify the UI
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SHOW_AREA_VIEW:
+ if (mAreaView != null) {
+ mAreaView.setVisibility(View.VISIBLE);
+ }
+ break;
+ case MSG_HIDE_AREA_VIEW:
+ if (mAreaView != null) {
+ mAreaView.setVisibility(View.INVISIBLE);
+ }
+ break;
+ default:
+ Log.w(TAG, "Unhandled message");
+ return false;
+ }
+ return true;
+ }
+
+ // Removes show and hide messages from the message queue
+ private void removeAreaDisplayMessages() {
+ mHandler.removeMessages(MSG_SHOW_AREA_VIEW);
+ mHandler.removeMessages(MSG_HIDE_AREA_VIEW);
+ }
+
+ // Shows the FaceLock area immediately
+ public void showArea() {
+ // Remove messages to prevent a delayed hide message from undo-ing the show
+ removeAreaDisplayMessages();
+ mHandler.sendEmptyMessage(MSG_SHOW_AREA_VIEW);
+ }
+
+ // Hides the FaceLock area immediately
+ public void hideArea() {
+ // Remove messages to prevent a delayed show message from undo-ing the hide
+ removeAreaDisplayMessages();
+ mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW);
+ }
+
+ // Shows the FaceLock area for a period of time
+ public void showAreaWithTimeout(long timeoutMillis) {
+ showArea();
+ mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis);
+ }
+
+ // Binds to FaceLock service. This call does not tell it to start, but it causes the service
+ // to call the onServiceConnected callback, which then starts FaceLock.
+ public void bind() {
+ if (installedAndSelected()) {
+ if (!mBoundToService) {
+ if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
+ mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
+ mConnection,
+ Context.BIND_AUTO_CREATE);
+ if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
+ mBoundToService = true;
+ } else {
+ Log.w(TAG, "Attempt to bind to FaceLock when already bound");
+ }
+ }
+ }
+
+ // Tells FaceLock to stop and then unbinds from the FaceLock service
+ public void stopAndUnbind() {
+ if (installedAndSelected()) {
+ stop();
+
+ if (mBoundToService) {
+ if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
+ if (mService != null) {
+ try {
+ mService.unregisterCallback(mFaceLockCallback);
+ } catch (RemoteException e) {
+ // Not much we can do
+ }
+ }
+ mContext.unbindService(mConnection);
+ if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
+ mBoundToService = false;
+ } else {
+ // This is usually not an error when this happens. Sometimes we will tell it to
+ // unbind multiple times because it's called from both onWindowFocusChanged and
+ // onDetachedFromWindow.
+ if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
+ }
+ }
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ // Completes connection, registers callback and starts FaceLock when service is bound
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder iservice) {
+ mService = IFaceLockInterface.Stub.asInterface(iservice);
+ if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
+ try {
+ mService.registerCallback(mFaceLockCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
+ mService = null;
+ mBoundToService = false;
+ return;
+ }
+
+ if (mAreaView != null) {
+ int[] position;
+ position = new int[2];
+ mAreaView.getLocationInWindow(position);
+ start(mAreaView.getWindowToken(), position[0], position[1],
+ mAreaView.getWidth(), mAreaView.getHeight());
+ }
+ }
+
+ // Cleans up if FaceLock service unexpectedly disconnects
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ synchronized(mServiceRunningLock) {
+ mService = null;
+ mServiceRunning = false;
+ }
+ mBoundToService = false;
+ Log.w(TAG, "Unexpected disconnect from FaceLock service");
+ }
+ };
+
+ // Tells the FaceLock service to start displaying its UI and perform recognition
+ public void start(IBinder windowToken, int x, int y, int w, int h) {
+ if (installedAndSelected()) {
+ synchronized (mServiceRunningLock) {
+ if (!mServiceRunning) {
+ if (DEBUG) Log.d(TAG, "Starting FaceLock");
+ try {
+ mService.startUi(windowToken, x, y, w, h);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
+ return;
+ }
+ mServiceRunning = true;
+ } else {
+ if (DEBUG) Log.w(TAG, "start() attempted while running");
+ }
+ }
+ }
+ }
+
+ // Tells the FaceLock service to stop displaying its UI and stop recognition
+ public void stop() {
+ if (installedAndSelected()) {
+ // Note that attempting to stop FaceLock when it's not running is not an issue.
+ // FaceLock can return, which stops it and then we try to stop it when the
+ // screen is turned off. That's why we check.
+ synchronized (mServiceRunningLock) {
+ if (mServiceRunning) {
+ try {
+ if (DEBUG) Log.d(TAG, "Stopping FaceLock");
+ mService.stopUi();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
+ }
+ mServiceRunning = false;
+ }
+ }
+ }
+ }
+
+ // Implements the FaceLock service callback interface defined in AIDL
+ private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
+ // Stops the FaceLock UI and indicates that the phone should be unlocked
+ @Override
+ public void unlock() {
+ if (DEBUG) Log.d(TAG, "FaceLock unlock()");
+ showArea(); // Keep fallback covered
+ stopAndUnbind();
+
+ mKeyguardScreenCallback.keyguardDone(true);
+ mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+ }
+
+ // Stops the FaceLock UI and exposes the backup method without unlocking
+ // This means the user has cancelled out
+ @Override
+ public void cancel() {
+ if (DEBUG) Log.d(TAG, "FaceLock cancel()");
+ hideArea(); // Expose fallback
+ stopAndUnbind();
+ mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+ }
+
+ // Stops the FaceLock UI and exposes the backup method without unlocking
+ // This means FaceLock failed to recognize them
+ @Override
+ public void reportFailedAttempt() {
+ if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
+ mUpdateMonitor.reportFailedFaceUnlockAttempt();
+ hideArea(); // Expose fallback
+ stopAndUnbind();
+ mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+ }
+
+ // Removes the black area that covers the backup unlock method
+ @Override
+ public void exposeFallback() {
+ if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()");
+ hideArea(); // Expose fallback
+ }
+
+ // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
+ @Override
+ public void pokeWakelock() {
+ if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()");
+ mKeyguardScreenCallback.pokeWakelock();
+ }
+ };
+}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 404dc6f..596040c 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -20,8 +20,6 @@ import com.android.internal.R;
import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback;
import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
-import com.android.internal.policy.IFaceLockCallback;
-import com.android.internal.policy.IFaceLockInterface;
import com.android.internal.telephony.IccCard;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockScreenWidgetCallback;
@@ -36,12 +34,10 @@ import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -50,12 +46,8 @@ import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.IBinder;
import android.os.Parcelable;
import android.os.PowerManager;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.telephony.TelephonyManager;
@@ -82,7 +74,7 @@ import java.io.IOException;
* {@link com.android.internal.policy.impl.KeyguardViewManager}
* via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
*/
-public class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback {
+public class LockPatternKeyguardView extends KeyguardViewBase {
private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
@@ -110,30 +102,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private boolean mShowLockBeforeUnlock = false;
// The following were added to support FaceLock
- private IFaceLockInterface mFaceLockService;
- private boolean mBoundToFaceLockService = false;
- private View mFaceLockAreaView;
-
- private boolean mFaceLockServiceRunning = false;
- private final Object mFaceLockServiceRunningLock = new Object();
+ private FaceUnlock mFaceUnlock;
private final Object mFaceLockStartupLock = new Object();
- private Handler mHandler;
- private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0;
- private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1;
-
- // Long enough to stay visible while dialer comes up
- // Short enough to not be visible if the user goes back immediately
- private final int FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
-
- // Long enough to stay visible while the service starts
- // Short enough to not have to wait long for backup if service fails to start or crashes
- // The service can take a couple of seconds to start on the first try after boot
- private final int FACELOCK_VIEW_AREA_SERVICE_TIMEOUT = 3000;
-
- // So the user has a consistent amount of time when brought to the backup method from FaceLock
- private final int BACKUP_LOCK_TIMEOUT = 5000;
-
private boolean mRequiresSim;
//True if we have some sort of overlay on top of the Lockscreen
//Also true if we've activated a phone call, either emergency dialing or incoming
@@ -340,12 +311,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mHasOverlay = true;
// Continue showing FaceLock area until dialer comes up or call is resumed
- if (usingFaceLock() && mFaceLockServiceRunning) {
- showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
+ if (mFaceUnlock.installedAndSelected() && mFaceUnlock.isServiceRunning()) {
+ mFaceUnlock.showAreaWithTimeout(mFaceUnlock.viewAreaEmergencyDialerTimeout());
}
// FaceLock must be stopped if it is running when emergency call is pressed
- stopAndUnbindFromFaceLock();
+ mFaceUnlock.stopAndUnbind();
pokeWakelock(EMERGENCY_CALL_TIMEOUT);
if (TelephonyManager.getDefault().getCallState()
@@ -450,7 +421,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
super(context, callback);
- mHandler = new Handler(this);
+ mFaceUnlock = new FaceUnlock(context, updateMonitor, lockPatternUtils,
+ mKeyguardScreenCallback);
mConfiguration = context.getResources().getConfiguration();
mEnableFallback = false;
mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
@@ -570,36 +542,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
saveWidgetState();
// When screen is turned off, need to unbind from FaceLock service if using FaceLock
- stopAndUnbindFromFaceLock();
- }
-
- /** When screen is turned on and focused, need to bind to FaceLock service if we are using
- * FaceLock, but only if we're not dealing with a call
- */
- private void activateFaceLockIfAble() {
- final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
- final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
- final boolean backupIsTimedOut =
- (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
- if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
- if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
- && usingFaceLock()
- && !mHasOverlay
- && !tooManyFaceUnlockTries
- && !backupIsTimedOut) {
- bindToFaceLock();
-
- // Show FaceLock area, but only for a little bit so lockpattern will become visible if
- // FaceLock fails to start or crashes
- showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT);
-
- // When switching between portrait and landscape view while FaceLock is running, the
- // screen will eventually go dark unless we poke the wakelock when FaceLock is
- // restarted
- mKeyguardScreenCallback.pokeWakelock();
- } else {
- hideFaceLockArea();
- }
+ mFaceUnlock.stopAndUnbind();
}
@Override
@@ -616,7 +559,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
restoreWidgetState();
- if (runFaceLock) activateFaceLockIfAble();
+ if (runFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
}
private void saveWidgetState() {
@@ -647,13 +590,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
if(mScreenOn && !mWindowFocused) runFaceLock = hasWindowFocus;
mWindowFocused = hasWindowFocus;
}
- if(!hasWindowFocus) {
+ if (!hasWindowFocus) {
mHasOverlay = true;
- stopAndUnbindFromFaceLock();
- hideFaceLockArea();
+ mFaceUnlock.stopAndUnbind();
+ mFaceUnlock.hideArea();
} else {
mHasDialog = false;
- if (runFaceLock) activateFaceLockIfAble();
+ if (runFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
}
}
@@ -667,14 +610,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
((KeyguardScreen) mUnlockScreen).onResume();
}
- if (usingFaceLock() && !mHasOverlay) {
+ if (mFaceUnlock.installedAndSelected() && !mHasOverlay) {
// Note that show() gets called before the screen turns off to set it up for next time
// it is turned on. We don't want to set a timeout on the FaceLock area here because it
// may be gone by the time the screen is turned on again. We set the timeout when the
// screen turns on instead.
- showFaceLockArea();
+ mFaceUnlock.showArea();
} else {
- hideFaceLockArea();
+ mFaceUnlock.hideArea();
}
}
@@ -710,7 +653,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
// When view is hidden, need to unbind from FaceLock service if we are using FaceLock
// e.g., when device becomes unlocked
- stopAndUnbindFromFaceLock();
+ mFaceUnlock.stopAndUnbind();
super.onDetachedFromWindow();
}
@@ -734,9 +677,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mHasOverlay |= mPluggedIn != pluggedIn;
mPluggedIn = pluggedIn;
//If it's already running, don't close it down: the unplug didn't start it
- if (!mFaceLockServiceRunning) {
- stopAndUnbindFromFaceLock();
- hideFaceLockArea();
+ if (!mFaceUnlock.isServiceRunning()) {
+ mFaceUnlock.stopAndUnbind();
+ mFaceUnlock.hideArea();
}
}
@@ -753,8 +696,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
if(phoneState == TelephonyManager.CALL_STATE_RINGING) {
mHasOverlay = true;
- stopAndUnbindFromFaceLock();
- hideFaceLockArea();
+ mFaceUnlock.stopAndUnbind();
+ mFaceUnlock.hideArea();
}
}
@@ -822,15 +765,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mUnlockScreen = null;
}
mUpdateMonitor.removeCallback(this);
- if (mFaceLockService != null) {
- try {
- mFaceLockService.unregisterCallback(mFaceLockCallback);
- } catch (RemoteException e) {
- // Not much we can do
- }
- stopFaceLock();
- mFaceLockService = null;
- }
+ mFaceUnlock.cleanUp();
}
private boolean isSecure() {
@@ -880,9 +815,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
final UnlockMode unlockMode = getUnlockMode();
if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
- boolean restartFaceLock = stopFaceLockIfRunning();
+ boolean restartFaceLock = mFaceUnlock.stopIfRunning();
recreateUnlockScreen(unlockMode);
- if (restartFaceLock) activateFaceLockIfAble();
+ if (restartFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
}
}
@@ -995,7 +930,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
}
initializeTransportControlView(unlockView);
- initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabled
+ mFaceUnlock.initializeAreaView(unlockView); // Only shows view if FaceLock is enabled
mUnlockScreenMode = unlockMode;
return unlockView;
@@ -1177,254 +1112,4 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
return mBitmap.getHeight();
}
}
-
- // Everything below pertains to FaceLock - might want to separate this out
-
- // Indicates whether FaceLock is in use
- private boolean usingFaceLock() {
- return (mLockPatternUtils.usingBiometricWeak() &&
- mLockPatternUtils.isBiometricWeakInstalled());
- }
-
- // Takes care of FaceLock area when layout is created
- private void initializeFaceLockAreaView(View view) {
- if (usingFaceLock()) {
- mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView);
- if (mFaceLockAreaView == null) {
- Log.e(TAG, "Layout does not have faceLockAreaView and FaceLock is enabled");
- }
- } else {
- mFaceLockAreaView = null; // Set to null if not using FaceLock
- }
- }
-
- // Stops FaceLock if it is running and reports back whether it was running or not
- private boolean stopFaceLockIfRunning() {
- if (usingFaceLock() && mBoundToFaceLockService) {
- stopAndUnbindFromFaceLock();
- return true;
- }
- return false;
- }
-
- // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
- // This needs to be done in a handler because the call could be coming from a callback from the
- // FaceLock service that is in a thread that can't modify the UI
- @Override
- public boolean handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_SHOW_FACELOCK_AREA_VIEW:
- if (mFaceLockAreaView != null) {
- mFaceLockAreaView.setVisibility(View.VISIBLE);
- }
- break;
- case MSG_HIDE_FACELOCK_AREA_VIEW:
- if (mFaceLockAreaView != null) {
- mFaceLockAreaView.setVisibility(View.INVISIBLE);
- }
- break;
- default:
- Log.w(TAG, "Unhandled message");
- return false;
- }
- return true;
- }
-
- // Removes show and hide messages from the message queue
- private void removeFaceLockAreaDisplayMessages() {
- mHandler.removeMessages(MSG_SHOW_FACELOCK_AREA_VIEW);
- mHandler.removeMessages(MSG_HIDE_FACELOCK_AREA_VIEW);
- }
-
- // Shows the FaceLock area immediately
- private void showFaceLockArea() {
- // Remove messages to prevent a delayed hide message from undo-ing the show
- removeFaceLockAreaDisplayMessages();
- mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
- }
-
- // Hides the FaceLock area immediately
- private void hideFaceLockArea() {
- // Remove messages to prevent a delayed show message from undo-ing the hide
- removeFaceLockAreaDisplayMessages();
- mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
- }
-
- // Shows the FaceLock area for a period of time
- private void showFaceLockAreaWithTimeout(long timeoutMillis) {
- showFaceLockArea();
- mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, timeoutMillis);
- }
-
- // Binds to FaceLock service. This call does not tell it to start, but it causes the service
- // to call the onServiceConnected callback, which then starts FaceLock.
- public void bindToFaceLock() {
- if (usingFaceLock()) {
- if (!mBoundToFaceLockService) {
- if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
- mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
- mFaceLockConnection,
- Context.BIND_AUTO_CREATE);
- if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
- mBoundToFaceLockService = true;
- } else {
- Log.w(TAG, "Attempt to bind to FaceLock when already bound");
- }
- }
- }
-
- // Tells FaceLock to stop and then unbinds from the FaceLock service
- public void stopAndUnbindFromFaceLock() {
- if (usingFaceLock()) {
- stopFaceLock();
-
- if (mBoundToFaceLockService) {
- if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
- if (mFaceLockService != null) {
- try {
- mFaceLockService.unregisterCallback(mFaceLockCallback);
- } catch (RemoteException e) {
- // Not much we can do
- }
- }
- mContext.unbindService(mFaceLockConnection);
- if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
- mBoundToFaceLockService = false;
- } else {
- // This is usually not an error when this happens. Sometimes we will tell it to
- // unbind multiple times because it's called from both onWindowFocusChanged and
- // onDetachedFromWindow.
- if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
- }
- }
- }
-
- private ServiceConnection mFaceLockConnection = new ServiceConnection() {
- // Completes connection, registers callback and starts FaceLock when service is bound
- @Override
- public void onServiceConnected(ComponentName className, IBinder iservice) {
- mFaceLockService = IFaceLockInterface.Stub.asInterface(iservice);
- if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
- try {
- mFaceLockService.registerCallback(mFaceLockCallback);
- } catch (RemoteException e) {
- Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
- mFaceLockService = null;
- mBoundToFaceLockService = false;
- return;
- }
-
- if (mFaceLockAreaView != null) {
- int[] faceLockPosition;
- faceLockPosition = new int[2];
- mFaceLockAreaView.getLocationInWindow(faceLockPosition);
- startFaceLock(mFaceLockAreaView.getWindowToken(),
- faceLockPosition[0], faceLockPosition[1],
- mFaceLockAreaView.getWidth(), mFaceLockAreaView.getHeight());
- }
- }
-
- // Cleans up if FaceLock service unexpectedly disconnects
- @Override
- public void onServiceDisconnected(ComponentName className) {
- synchronized(mFaceLockServiceRunningLock) {
- mFaceLockService = null;
- mFaceLockServiceRunning = false;
- }
- mBoundToFaceLockService = false;
- Log.w(TAG, "Unexpected disconnect from FaceLock service");
- }
- };
-
- // Tells the FaceLock service to start displaying its UI and perform recognition
- public void startFaceLock(IBinder windowToken, int x, int y, int w, int h)
- {
- if (usingFaceLock()) {
- synchronized (mFaceLockServiceRunningLock) {
- if (!mFaceLockServiceRunning) {
- if (DEBUG) Log.d(TAG, "Starting FaceLock");
- try {
- mFaceLockService.startUi(windowToken, x, y, w, h);
- } catch (RemoteException e) {
- Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
- return;
- }
- mFaceLockServiceRunning = true;
- } else {
- if (DEBUG) Log.w(TAG, "startFaceLock() attempted while running");
- }
- }
- }
- }
-
- // Tells the FaceLock service to stop displaying its UI and stop recognition
- public void stopFaceLock()
- {
- if (usingFaceLock()) {
- // Note that attempting to stop FaceLock when it's not running is not an issue.
- // FaceLock can return, which stops it and then we try to stop it when the
- // screen is turned off. That's why we check.
- synchronized (mFaceLockServiceRunningLock) {
- if (mFaceLockServiceRunning) {
- try {
- if (DEBUG) Log.d(TAG, "Stopping FaceLock");
- mFaceLockService.stopUi();
- } catch (RemoteException e) {
- Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
- }
- mFaceLockServiceRunning = false;
- }
- }
- }
- }
-
- // Implements the FaceLock service callback interface defined in AIDL
- private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
-
- // Stops the FaceLock UI and indicates that the phone should be unlocked
- @Override
- public void unlock() {
- if (DEBUG) Log.d(TAG, "FaceLock unlock()");
- showFaceLockArea(); // Keep fallback covered
- stopAndUnbindFromFaceLock();
-
- mKeyguardScreenCallback.keyguardDone(true);
- mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
- }
-
- // Stops the FaceLock UI and exposes the backup method without unlocking
- // This means the user has cancelled out
- @Override
- public void cancel() {
- if (DEBUG) Log.d(TAG, "FaceLock cancel()");
- hideFaceLockArea(); // Expose fallback
- stopAndUnbindFromFaceLock();
- mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
- }
-
- // Stops the FaceLock UI and exposes the backup method without unlocking
- // This means FaceLock failed to recognize them
- @Override
- public void reportFailedAttempt() {
- if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
- mUpdateMonitor.reportFailedFaceUnlockAttempt();
- hideFaceLockArea(); // Expose fallback
- stopAndUnbindFromFaceLock();
- mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
- }
-
- // Removes the black area that covers the backup unlock method
- @Override
- public void exposeFallback() {
- if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()");
- hideFaceLockArea(); // Expose fallback
- }
-
- // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
- @Override
- public void pokeWakelock() {
- if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()");
- mKeyguardScreenCallback.pokeWakelock();
- }
- };
}