Skip to content

Commit 4d7cee1

Browse files
author
Brian Colonna
committed
Properly laying out FaceLock on lockscreen
- FaceLock area now specified in layout files instead of trying to grab an existing view, which was only practical if pattern was backup method - Now fills area it is supposed to and works with pin as well as pattern backup - Backup method is no longer exposed behind FaceLock just before it starts or just after it tells the lockscreen to unlock - Added synchronized blocks so FaceLock cannot be told to stopUI by two different threads at the same time Change-Id: I3bfad6b44dbe0e3c2ea3c87d2978451c22a7484c
1 parent 62bb0cd commit 4d7cee1

File tree

5 files changed

+115
-40
lines changed

5 files changed

+115
-40
lines changed

core/res/res/layout/keyguard_screen_password_portrait.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,17 @@
178178
android:layout_height="0dip"
179179
/>
180180

181+
<!-- Area to overlay FaceLock -->
182+
<TextView android:id="@+id/faceLockAreaView"
183+
android:visibility="gone"
184+
android:layout_row="3"
185+
android:layout_column="0"
186+
android:layout_rowSpan="2"
187+
android:layout_columnSpan="1"
188+
android:layout_gravity="fill"
189+
android:layout_width="0dip"
190+
android:layout_height="0dip"
191+
android:background="@color/facelock_color_background"
192+
/>
193+
181194
</GridLayout>

core/res/res/layout/keyguard_screen_unlock_portrait.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,19 @@
171171
android:layout_height="0dip"
172172
/>
173173

174+
<!-- Area to overlay FaceLock -->
175+
<TextView android:id="@+id/faceLockAreaView"
176+
android:visibility="gone"
177+
android:layout_row="4"
178+
android:layout_column="0"
179+
android:layout_rowSpan="1"
180+
android:layout_columnSpan="1"
181+
android:layout_gravity="fill"
182+
android:layout_marginTop="8dip"
183+
android:layout_marginBottom="8dip"
184+
android:layout_width="0dip"
185+
android:layout_height="0dip"
186+
android:background="@color/facelock_color_background"
187+
/>
188+
174189
</GridLayout>

core/res/res/values/colors.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@
112112
<color name="lockscreen_clock_am_pm">#ff9a9a9a</color>
113113
<color name="lockscreen_owner_info">#ff9a9a9a</color>
114114

115+
<!-- FaceLock -->
116+
<color name="facelock_color_background">#000000</color>
117+
115118
<!-- For holo theme -->
116119
<drawable name="screen_background_holo_light">#fff3f3f3</drawable>
117120
<drawable name="screen_background_holo_dark">#ff000000</drawable>

policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java

Lines changed: 84 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import android.graphics.PixelFormat;
4747
import android.graphics.drawable.Drawable;
4848
import android.os.Bundle;
49+
import android.os.Handler;
50+
import android.os.Message;
4951
import android.os.IBinder;
5052
import android.os.RemoteException;
5153
import android.os.SystemClock;
@@ -74,7 +76,7 @@
7476
* {@link com.android.internal.policy.impl.KeyguardViewManager}
7577
* via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
7678
*/
77-
public class LockPatternKeyguardView extends KeyguardViewBase {
79+
public class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback {
7880

7981
private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
8082

@@ -103,9 +105,15 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
103105
// The following were added to support FaceLock
104106
private IFaceLockInterface mFaceLockService;
105107
private boolean mBoundToFaceLockService = false;
106-
private boolean mFaceLockServiceRunning = false;
107108
private View mFaceLockAreaView;
108109

110+
private boolean mFaceLockServiceRunning = false;
111+
private final Object mFaceLockServiceRunningLock = new Object();
112+
113+
private Handler mHandler;
114+
private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0;
115+
private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1;
116+
109117
/**
110118
* The current {@link KeyguardScreen} will use this to communicate back to us.
111119
*/
@@ -244,6 +252,7 @@ public LockPatternKeyguardView(
244252
KeyguardWindowController controller) {
245253
super(context);
246254

255+
mHandler = new Handler(this);
247256
mConfiguration = context.getResources().getConfiguration();
248257
mEnableFallback = false;
249258
mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
@@ -704,12 +713,6 @@ View createUnlockScreenFor(UnlockMode unlockMode) {
704713
mKeyguardScreenCallback,
705714
mUpdateMonitor.getFailedAttempts());
706715
view.setEnableFallback(mEnableFallback);
707-
708-
// TODO(bcolonna): For pattern unlock, it can give us the view where the pattern is
709-
// displayed and FaceLock can draw in that area.
710-
// For other views it's not so simple and we should probably change how the FaceLock
711-
// area is determined.
712-
mFaceLockAreaView = view.getUnlockAreaView();
713716
unlockView = view;
714717
} else if (unlockMode == UnlockMode.SimPuk) {
715718
unlockView = new SimPukUnlockScreen(
@@ -759,6 +762,8 @@ View createUnlockScreenFor(UnlockMode unlockMode) {
759762
throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
760763
}
761764
initializeTransportControlView(unlockView);
765+
initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabled
766+
762767
mUnlockScreenMode = unlockMode;
763768
return unlockView;
764769
}
@@ -938,6 +943,41 @@ public int getMinimumHeight() {
938943

939944
// Everything below pertains to FaceLock - might want to separate this out
940945

946+
// Only pattern and pin unlock screens actually have a view for the FaceLock area, so it's not
947+
// uncommon for it to not exist. But if it does exist, we need to make sure it's showing if
948+
// FaceLock is enabled, and make sure it's not showing if FaceLock is disabled
949+
private void initializeFaceLockAreaView(View view) {
950+
mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView);
951+
if (mFaceLockAreaView == null) {
952+
if (DEBUG) Log.d(TAG, "Layout does not have faceLockAreaView");
953+
} else {
954+
if (mLockPatternUtils.usingBiometricWeak()) {
955+
mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
956+
} else {
957+
mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
958+
}
959+
}
960+
}
961+
962+
// Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
963+
// This needs to be done in a handler because the call could be coming from a callback from the
964+
// FaceLock service that is in a thread that can't modify the UI
965+
@Override
966+
public boolean handleMessage(Message msg) {
967+
switch (msg.what) {
968+
case MSG_SHOW_FACELOCK_AREA_VIEW:
969+
mFaceLockAreaView.setVisibility(View.VISIBLE);
970+
break;
971+
case MSG_HIDE_FACELOCK_AREA_VIEW:
972+
mFaceLockAreaView.setVisibility(View.GONE);
973+
break;
974+
default:
975+
Log.w(TAG, "Unhandled message");
976+
return false;
977+
}
978+
return true;
979+
}
980+
941981
// Binds to FaceLock service, but does not tell it to start
942982
public void bindToFaceLock() {
943983
if (mLockPatternUtils.usingBiometricWeak()) {
@@ -986,23 +1026,20 @@ public void onServiceConnected(ComponentName className, IBinder iservice) {
9861026
throw new RuntimeException("Remote exception");
9871027
}
9881028

989-
// TODO(bcolonna): Need to set location properly (only works for pattern view now)
9901029
if (mFaceLockAreaView != null) {
991-
int[] unlockLocationOnScreen = new int[2];
992-
mFaceLockAreaView.getLocationOnScreen(unlockLocationOnScreen);
993-
int x = unlockLocationOnScreen[0];
994-
int y = unlockLocationOnScreen[1];
995-
int w = mFaceLockAreaView.getWidth();
996-
int h = mFaceLockAreaView.getHeight();
997-
if (DEBUG) Log.d(TAG, "(x,y) (wxh): (" + x + "," + y + ") (" + w + "x" + h + ")");
998-
startFaceLock(mFaceLockAreaView.getWindowToken(), x, y, w, h);
1030+
startFaceLock(mFaceLockAreaView.getWindowToken(),
1031+
mFaceLockAreaView.getLeft(), mFaceLockAreaView.getTop(),
1032+
mFaceLockAreaView.getWidth(), mFaceLockAreaView.getHeight());
9991033
}
10001034
}
10011035

10021036
// Cleans up if FaceLock service unexpectedly disconnects
10031037
@Override
10041038
public void onServiceDisconnected(ComponentName className) {
1005-
mFaceLockService = null;
1039+
synchronized(mFaceLockServiceRunningLock) {
1040+
mFaceLockService = null;
1041+
mFaceLockServiceRunning = false;
1042+
}
10061043
if (DEBUG) Log.w(TAG, "Unexpected disconnect from FaceLock service");
10071044
}
10081045
};
@@ -1011,16 +1048,18 @@ public void onServiceDisconnected(ComponentName className) {
10111048
public void startFaceLock(IBinder windowToken, int x, int y, int h, int w)
10121049
{
10131050
if (mLockPatternUtils.usingBiometricWeak()) {
1014-
if (!mFaceLockServiceRunning) {
1015-
if (DEBUG) Log.d(TAG, "Starting FaceLock");
1016-
try {
1017-
mFaceLockService.startUi(windowToken, x, y, h, w);
1018-
} catch (RemoteException e) {
1019-
throw new RuntimeException("Remote exception");
1051+
synchronized (mFaceLockServiceRunningLock) {
1052+
if (!mFaceLockServiceRunning) {
1053+
if (DEBUG) Log.d(TAG, "Starting FaceLock");
1054+
try {
1055+
mFaceLockService.startUi(windowToken, x, y, h, w);
1056+
} catch (RemoteException e) {
1057+
throw new RuntimeException("Remote exception");
1058+
}
1059+
mFaceLockServiceRunning = true;
1060+
} else {
1061+
if (DEBUG) Log.w(TAG, "startFaceLock() attempted while running");
10201062
}
1021-
mFaceLockServiceRunning = true;
1022-
} else {
1023-
if (DEBUG) Log.w(TAG, "startFaceLock() attempted while running");
10241063
}
10251064
}
10261065
}
@@ -1032,14 +1071,16 @@ public void stopFaceLock()
10321071
// Note that attempting to stop FaceLock when it's not running is not an issue.
10331072
// FaceLock can return, which stops it and then we try to stop it when the
10341073
// screen is turned off. That's why we check.
1035-
if (mFaceLockServiceRunning) {
1036-
try {
1037-
if (DEBUG) Log.d(TAG, "Stopping FaceLock");
1038-
mFaceLockService.stopUi();
1039-
} catch (RemoteException e) {
1040-
throw new RuntimeException("Remote exception");
1074+
synchronized (mFaceLockServiceRunningLock) {
1075+
if (mFaceLockServiceRunning) {
1076+
try {
1077+
if (DEBUG) Log.d(TAG, "Stopping FaceLock");
1078+
mFaceLockService.stopUi();
1079+
} catch (RemoteException e) {
1080+
throw new RuntimeException("Remote exception");
1081+
}
1082+
mFaceLockServiceRunning = false;
10411083
}
1042-
mFaceLockServiceRunning = false;
10431084
}
10441085
}
10451086
}
@@ -1051,6 +1092,9 @@ public void stopFaceLock()
10511092
@Override
10521093
public void unlock() {
10531094
if (DEBUG) Log.d(TAG, "FaceLock unlock");
1095+
// Note that we don't hide the client FaceLockAreaView because we want to keep the
1096+
// lock screen covered while the phone is unlocked
1097+
10541098
stopFaceLock();
10551099
mKeyguardScreenCallback.keyguardDone(true);
10561100
mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
@@ -1061,6 +1105,8 @@ public void unlock() {
10611105
public void cancel() {
10621106
// In this case, either the user has cancelled out, or FaceLock failed to recognize them
10631107
if (DEBUG) Log.d(TAG, "FaceLock cancel");
1108+
// Here we hide the client FaceLockViewArea to expose the underlying backup method
1109+
mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
10641110
stopFaceLock();
10651111
}
10661112

@@ -1069,8 +1115,12 @@ public void cancel() {
10691115
public void sleepDevice() {
10701116
// In this case, it appears the phone has been turned on accidentally
10711117
if (DEBUG) Log.d(TAG, "FaceLock accidental turn on");
1118+
// Here we hide the client FaceLockViewArea to expose the underlying backup method
1119+
mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
10721120
stopFaceLock();
10731121
// TODO(bcolonna): how do we put the phone back to sleep (i.e., turn off the screen)
1122+
// TODO(bcolonna): this should be removed once the service is no longer calling it
1123+
// because we are just going to let the lockscreen timeout
10741124
}
10751125
};
10761126
}

policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,6 @@ private void updateFooter(FooterMode mode) {
199199
setFocusableInTouchMode(true);
200200
}
201201

202-
// TODO(bcolonna): This is to tell FaceLock where to draw...but this covers up the wireless
203-
// service text, so we will want to change the way the area is specified
204-
public View getUnlockAreaView() {
205-
return mLockPatternView;
206-
}
207-
208202
public void setEnableFallback(boolean state) {
209203
if (DEBUG) Log.d(TAG, "setEnableFallback(" + state + ")");
210204
mEnableFallback = state;

0 commit comments

Comments
 (0)