4/n: Add basic enrollment for Face
Bug: 110589286 Test: fingerprint enrolling still works Test: enrollment flow with and without a pin set up still works properly Test: enrollment continues when configuration changes, stops otherwise Change-Id: I39f76c7f1a16e9533cef573f87cf4b81cb20cb18
This commit is contained in:
@@ -1570,6 +1570,8 @@
|
||||
android:theme="@style/GlifTheme.Light"/>
|
||||
|
||||
<activity android:name=".biometrics.face.FaceEnrollIntroduction" android:exported="false" />
|
||||
<activity android:name=".biometrics.face.FaceEnrollEnrolling" android:exported="false" />
|
||||
<activity android:name=".biometrics.face.FaceEnrollFinish" android:exported="false" />
|
||||
|
||||
<activity android:name=".biometrics.fingerprint.FingerprintSettings" android:exported="false"/>
|
||||
<activity android:name=".biometrics.fingerprint.FingerprintEnrollFindSensor" android:exported="false"/>
|
||||
|
71
res/layout/face_enroll_enrolling.xml
Normal file
71
res/layout/face_enroll_enrolling.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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.
|
||||
-->
|
||||
|
||||
<com.android.setupwizardlib.GlifLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/setup_wizard_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
style="?attr/face_layout_theme"
|
||||
app:suwFooter="@layout/face_enroll_enrolling_footer">
|
||||
|
||||
<LinearLayout
|
||||
style="@style/SuwContentFrame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
|
||||
<!-- TODO: replace this with actual content-->
|
||||
<ImageView
|
||||
style="@style/SuwContentIllustration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/face_enroll_introduction" />
|
||||
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.FaceErrorText"
|
||||
android:id="@+id/error_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:accessibilityLiveRegion="polite"
|
||||
android:gravity="center"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.setupwizardlib.GlifLayout>
|
31
res/layout/face_enroll_enrolling_footer.xml
Normal file
31
res/layout/face_enroll_enrolling_footer.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
|
||||
<!-- TODO: Use aapt:attr when it is fixed (b/36809755) -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/SuwGlifButtonBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
style="@style/SuwGlifButton.Secondary"
|
||||
android:id="@+id/skip_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_face_enroll_enrolling_skip" />
|
||||
|
||||
</LinearLayout>
|
60
res/layout/face_enroll_finish.xml
Normal file
60
res/layout/face_enroll_finish.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
|
||||
<com.android.setupwizardlib.GlifLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/setup_wizard_layout"
|
||||
style="?attr/face_layout_theme"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:suwFooter="@layout/face_enroll_finish_footer">
|
||||
|
||||
<LinearLayout
|
||||
style="@style/SuwContentFrame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.android.setupwizardlib.view.FillContentLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
|
||||
<ImageView
|
||||
style="@style/SuwContentIllustration"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/face_enroll_introduction" />
|
||||
|
||||
</com.android.setupwizardlib.view.FillContentLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.android.setupwizardlib.GlifLayout>
|
37
res/layout/face_enroll_finish_footer.xml
Normal file
37
res/layout/face_enroll_finish_footer.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
|
||||
<!-- TODO: Use aapt:attr when it is fixed (b/36809755) -->
|
||||
<com.android.setupwizardlib.view.ButtonBarLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/SuwGlifButtonBar.Stackable"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Button
|
||||
style="@style/SuwGlifButton.Primary"
|
||||
android:id="@+id/next_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/security_settings_face_enroll_done" />
|
||||
|
||||
</com.android.setupwizardlib.view.ButtonBarLayout>
|
@@ -897,12 +897,28 @@
|
||||
<string name="security_settings_face_enroll_introduction_message_unlock_disabled">Use you</string>
|
||||
<!-- Introduction detail message shwon in face enrollment screen in setup wizard. [CHAR LIMIT=NONE] -->
|
||||
<string name="security_settings_face_enroll_introduction_message_setup">Use your face to unlock your phone, authorize purchases, or sign in to apps</string>
|
||||
<!-- Title shown in face enrollment dialog [CHAR LIMIT=40] -->
|
||||
<string name="security_settings_face_enroll_repeat_title">Center your face in the circle</string>
|
||||
<!-- Button text to skip enrollment of face [CHAR LIMIT=40] -->
|
||||
<string name="security_settings_face_enroll_enrolling_skip">Do it later</string>
|
||||
<!-- Text shown when "Add face" button is disabled -->
|
||||
<string name="face_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
|
||||
<!-- Text shown when users has enrolled a maximum number of faces [CHAR LIMIT=NONE] -->
|
||||
<string name="face_intro_error_max">You\u2019ve added the maximum number of faces</string>
|
||||
<!-- Text shown when an unknown error caused the device to be unable to add faces [CHAR LIMIT=NONE] -->
|
||||
<string name="face_intro_error_unknown">Can\u2019t add more faces</string>
|
||||
<!-- Dialog message for dialog which shows when face cannot be enrolled. [CHAR LIMIT=45] -->
|
||||
<string name="security_settings_face_enroll_error_dialog_title">Enrollment was not completed</string>
|
||||
<!-- Button text shown in face dialog shown when an error occurs during enrollment [CHAR LIMIT=22] -->
|
||||
<string name="security_settings_face_enroll_dialog_ok">OK</string>
|
||||
<!-- Dialog message for dialog which shows when face cannot be enrolled due to being idle too long. -->
|
||||
<string name="security_settings_face_enroll_error_timeout_dialog_message">Face enrollment time limit reached. Try again.</string>
|
||||
<!-- Dialog message for dialog which shows when face cannot be enrolled due to an internal error or face can't be read. -->
|
||||
<string name="security_settings_face_enroll_error_generic_dialog_message">Face enrollment didn\'t work.</string>
|
||||
<!-- Message shown in face enrollment dialog once enrollment is completed -->
|
||||
<string name="security_settings_face_enroll_finish_title">All set. Looking good.</string>
|
||||
<!-- Button text to exit face wizard after everything is done [CHAR LIMIT=15] -->
|
||||
<string name="security_settings_face_enroll_done">Done</string>
|
||||
|
||||
<!-- Fingerprint enrollment and settings --><skip />
|
||||
<!-- Title shown for menu item that launches fingerprint settings or enrollment [CHAR LIMIT=22] -->
|
||||
|
@@ -364,6 +364,11 @@
|
||||
<item name="android:icon">@drawable/ic_fingerprint_header</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.FaceErrorText"
|
||||
parent="android:TextAppearance.Material.Body1">
|
||||
<item name="android:textColor">?android:attr/colorError</item>
|
||||
</style>
|
||||
|
||||
<style name="FaceLayoutTheme">
|
||||
<item name="android:icon">@drawable/ic_face_header</item>
|
||||
</style>
|
||||
|
@@ -30,29 +30,33 @@ import android.widget.TextView;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintSettings;
|
||||
import com.android.settings.core.InstrumentedActivity;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
import com.android.setupwizardlib.GlifLayout;
|
||||
|
||||
/**
|
||||
* Base activity for all fingerprint enrollment steps.
|
||||
* Base activity for all biometric enrollment steps.
|
||||
*/
|
||||
public abstract class BiometricEnrollBase extends InstrumentedActivity
|
||||
implements View.OnClickListener {
|
||||
public static final int RESULT_FINISHED = BiometricSettings.RESULT_FINISHED;
|
||||
public static final int RESULT_SKIP = BiometricSettings.RESULT_SKIP;
|
||||
public static final int RESULT_TIMEOUT = BiometricSettings.RESULT_TIMEOUT;
|
||||
public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
|
||||
|
||||
public static final int CONFIRM_REQUEST = 1;
|
||||
public static final int ENROLLING = 2;
|
||||
|
||||
protected boolean mLaunchedConfirmLock;
|
||||
protected byte[] mToken;
|
||||
protected int mUserId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mToken = getIntent().getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
mToken = getIntent().getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
if (savedInstanceState != null && mToken == null) {
|
||||
mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM);
|
||||
mToken = savedInstanceState.getByteArray(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
}
|
||||
@@ -68,6 +72,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(EXTRA_KEY_LAUNCHED_CONFIRM, mLaunchedConfirmLock);
|
||||
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
|
||||
}
|
||||
|
||||
@@ -77,6 +82,10 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity
|
||||
initViews();
|
||||
}
|
||||
|
||||
protected boolean shouldLaunchConfirmLock() {
|
||||
return mToken == null && !mLaunchedConfirmLock;
|
||||
}
|
||||
|
||||
protected void initViews() {
|
||||
getWindow().setStatusBarColor(Color.TRANSPARENT);
|
||||
Button nextButton = getNextButton();
|
||||
@@ -129,4 +138,25 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity
|
||||
}
|
||||
return intent;
|
||||
}
|
||||
|
||||
protected void launchConfirmLock(int titleResId, long challenge) {
|
||||
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
|
||||
boolean launchedConfirmationActivity;
|
||||
if (mUserId == UserHandle.USER_NULL) {
|
||||
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(titleResId),
|
||||
null, null, challenge);
|
||||
} else {
|
||||
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(titleResId),
|
||||
null, null, challenge, mUserId);
|
||||
}
|
||||
if (!launchedConfirmationActivity) {
|
||||
// This shouldn't happen, as we should only end up at this step if a lock thingy is
|
||||
// already set.
|
||||
finish();
|
||||
} else {
|
||||
mLaunchedConfirmLock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -102,9 +102,11 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
protected abstract String getExtraKeyForBiometric();
|
||||
|
||||
/**
|
||||
* @return the intent for proceeding to the next step of enrollment
|
||||
* @return the intent for proceeding to the next step of enrollment. For Fingerprint, this
|
||||
* should lead to the "Find Sensor" activity. For Face, this should lead to the "Enrolling"
|
||||
* activity.
|
||||
*/
|
||||
protected abstract Intent getFindSensorIntent();
|
||||
protected abstract Intent getEnrollingIntent();
|
||||
|
||||
/**
|
||||
* @param span
|
||||
@@ -179,7 +181,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
|
||||
}
|
||||
|
||||
private void launchFindSensor(byte[] token) {
|
||||
Intent intent = getFindSensorIntent();
|
||||
Intent intent = getEnrollingIntent();
|
||||
if (token != null) {
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
}
|
||||
|
218
src/com/android/settings/biometrics/BiometricEnrollSidecar.java
Normal file
218
src/com/android/settings/biometrics/BiometricEnrollSidecar.java
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.biometrics;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Abstract sidecar fragment to handle the state around biometric enrollment. This sidecar manages
|
||||
* the state of enrollment throughout the activity lifecycle so the app can continue after an
|
||||
* event like rotation.
|
||||
*/
|
||||
public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
|
||||
|
||||
public interface Listener {
|
||||
void onEnrollmentHelp(CharSequence helpString);
|
||||
void onEnrollmentError(int errMsgId, CharSequence errString);
|
||||
void onEnrollmentProgressChange(int steps, int remaining);
|
||||
}
|
||||
|
||||
private int mEnrollmentSteps = -1;
|
||||
private int mEnrollmentRemaining = 0;
|
||||
private Listener mListener;
|
||||
private boolean mEnrolling;
|
||||
private Handler mHandler = new Handler();
|
||||
private boolean mDone;
|
||||
private ArrayList<QueuedEvent> mQueuedEvents;
|
||||
|
||||
protected CancellationSignal mEnrollmentCancel;
|
||||
protected byte[] mToken;
|
||||
protected int mUserId;
|
||||
|
||||
private abstract class QueuedEvent {
|
||||
public abstract void send(Listener listener);
|
||||
}
|
||||
|
||||
private class QueuedEnrollmentProgress extends QueuedEvent {
|
||||
int enrollmentSteps;
|
||||
int remaining;
|
||||
public QueuedEnrollmentProgress(int enrollmentSteps, int remaining) {
|
||||
this.enrollmentSteps = enrollmentSteps;
|
||||
this.remaining = remaining;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Listener listener) {
|
||||
listener.onEnrollmentProgressChange(enrollmentSteps, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
private class QueuedEnrollmentHelp extends QueuedEvent {
|
||||
int helpMsgId;
|
||||
CharSequence helpString;
|
||||
public QueuedEnrollmentHelp(int helpMsgId, CharSequence helpString) {
|
||||
this.helpMsgId = helpMsgId;
|
||||
this.helpString = helpString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Listener listener) {
|
||||
listener.onEnrollmentHelp(helpString);
|
||||
}
|
||||
}
|
||||
|
||||
private class QueuedEnrollmentError extends QueuedEvent {
|
||||
int errMsgId;
|
||||
CharSequence errString;
|
||||
public QueuedEnrollmentError(int errMsgId, CharSequence errString) {
|
||||
this.errMsgId = errMsgId;
|
||||
this.errString = errString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Listener listener) {
|
||||
listener.onEnrollmentError(errMsgId, errString);
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mTimeoutRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cancelEnrollment();
|
||||
}
|
||||
};
|
||||
|
||||
public BiometricEnrollSidecar() {
|
||||
mQueuedEvents = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
mToken = activity.getIntent().getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
mUserId = activity.getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (!mEnrolling) {
|
||||
startEnrollment();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (!getActivity().isChangingConfigurations()) {
|
||||
cancelEnrollment();
|
||||
}
|
||||
}
|
||||
|
||||
protected void startEnrollment() {
|
||||
mHandler.removeCallbacks(mTimeoutRunnable);
|
||||
mEnrollmentSteps = -1;
|
||||
mEnrollmentCancel = new CancellationSignal();
|
||||
mEnrolling = true;
|
||||
}
|
||||
|
||||
public boolean cancelEnrollment() {
|
||||
mHandler.removeCallbacks(mTimeoutRunnable);
|
||||
if (mEnrolling) {
|
||||
mEnrollmentCancel.cancel();
|
||||
mEnrolling = false;
|
||||
mEnrollmentSteps = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void onEnrollmentProgress(int remaining) {
|
||||
if (mEnrollmentSteps == -1) {
|
||||
mEnrollmentSteps = remaining;
|
||||
}
|
||||
mEnrollmentRemaining = remaining;
|
||||
mDone = remaining == 0;
|
||||
if (mListener != null) {
|
||||
mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
|
||||
} else {
|
||||
mQueuedEvents.add(new QueuedEnrollmentProgress(mEnrollmentSteps, remaining));
|
||||
}
|
||||
}
|
||||
|
||||
protected void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
|
||||
if (mListener != null) {
|
||||
mListener.onEnrollmentHelp(helpString);
|
||||
} else {
|
||||
mQueuedEvents.add(new QueuedEnrollmentHelp(helpMsgId, helpString));
|
||||
}
|
||||
}
|
||||
|
||||
protected void onEnrollmentError(int errMsgId, CharSequence errString) {
|
||||
if (mListener != null) {
|
||||
mListener.onEnrollmentError(errMsgId, errString);
|
||||
} else {
|
||||
mQueuedEvents.add(new QueuedEnrollmentError(errMsgId, errString));
|
||||
}
|
||||
mEnrolling = false;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
mListener = listener;
|
||||
if (mListener != null) {
|
||||
for (int i=0; i<mQueuedEvents.size(); i++) {
|
||||
QueuedEvent event = mQueuedEvents.get(i);
|
||||
event.send(mListener);
|
||||
}
|
||||
mQueuedEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public int getEnrollmentSteps() {
|
||||
return mEnrollmentSteps;
|
||||
}
|
||||
|
||||
public int getEnrollmentRemaining() {
|
||||
return mEnrollmentRemaining;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return mDone;
|
||||
}
|
||||
|
||||
public boolean isEnrolling() {
|
||||
return mEnrolling;
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.biometrics;
|
||||
|
||||
import static com.android.settings.biometrics.BiometricSettings.RESULT_FINISHED;
|
||||
import static com.android.settings.biometrics.BiometricSettings.RESULT_TIMEOUT;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.hardware.biometrics.BiometricConstants;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
|
||||
/**
|
||||
* Abstract dialog, shown when an error occurs during biometric enrollment.
|
||||
*/
|
||||
public abstract class BiometricErrorDialog extends InstrumentedDialogFragment {
|
||||
|
||||
public static final String KEY_ERROR_MSG = "error_msg";
|
||||
public static final String KEY_ERROR_ID = "error_id";
|
||||
|
||||
public abstract int getTitleResId();
|
||||
public abstract int getOkButtonTextResId();
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
CharSequence errorString = getArguments().getCharSequence(KEY_ERROR_MSG);
|
||||
final int errMsgId = getArguments().getInt(KEY_ERROR_ID);
|
||||
|
||||
builder.setTitle(getTitleResId())
|
||||
.setMessage(errorString)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(getOkButtonTextResId(),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
boolean wasTimeout =
|
||||
errMsgId == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT;
|
||||
Activity activity = getActivity();
|
||||
activity.setResult(wasTimeout ?
|
||||
RESULT_TIMEOUT : RESULT_FINISHED);
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
return dialog;
|
||||
}
|
||||
}
|
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.biometrics;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
/**
|
||||
* Abstract base activity which handles the actual enrolling for biometrics.
|
||||
*/
|
||||
public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
|
||||
implements BiometricEnrollSidecar.Listener {
|
||||
|
||||
private static final String TAG_SIDECAR = "sidecar";
|
||||
|
||||
protected BiometricEnrollSidecar mSidecar;
|
||||
|
||||
/**
|
||||
* @return the intent for the finish activity
|
||||
*/
|
||||
protected abstract Intent getFinishIntent();
|
||||
|
||||
/**
|
||||
* @return an instance of the biometric enroll sidecar
|
||||
*/
|
||||
protected abstract BiometricEnrollSidecar getSidecar();
|
||||
|
||||
/**
|
||||
* @return true if enrollment should start automatically.
|
||||
*/
|
||||
protected abstract boolean shouldStartAutomatically();
|
||||
|
||||
/**
|
||||
* @return true if enrollment should finish when onStop is called.
|
||||
*/
|
||||
protected boolean shouldFinishOnStop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (shouldStartAutomatically()) {
|
||||
startEnrollment();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (mSidecar != null) {
|
||||
mSidecar.setListener(null);
|
||||
}
|
||||
|
||||
if (shouldFinishOnStop() && !isChangingConfigurations()) {
|
||||
if (mSidecar != null) {
|
||||
mSidecar.cancelEnrollment();
|
||||
getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mSidecar != null) {
|
||||
mSidecar.setListener(null);
|
||||
mSidecar.cancelEnrollment();
|
||||
getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
|
||||
mSidecar = null;
|
||||
}
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.skip_button:
|
||||
setResult(RESULT_SKIP);
|
||||
finish();
|
||||
break;
|
||||
default:
|
||||
super.onClick(v);
|
||||
}
|
||||
}
|
||||
|
||||
public void startEnrollment() {
|
||||
mSidecar = (BiometricEnrollSidecar) getFragmentManager().findFragmentByTag(TAG_SIDECAR);
|
||||
if (mSidecar == null) {
|
||||
mSidecar = getSidecar();
|
||||
getFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR).commit();
|
||||
}
|
||||
mSidecar.setListener(this);
|
||||
}
|
||||
|
||||
protected void launchFinish(byte[] token) {
|
||||
Intent intent = getFinishIntent();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
}
|
||||
startActivity(intent);
|
||||
overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
|
||||
finish();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.biometrics.face;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar;
|
||||
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
|
||||
import com.android.settings.biometrics.BiometricErrorDialog;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
|
||||
public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
|
||||
private static final String TAG = "FaceEnrollEnrolling";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private TextView mErrorText;
|
||||
private Interpolator mLinearOutSlowInInterpolator;
|
||||
private boolean mShouldFinishOnStop = true;
|
||||
|
||||
public static class FaceErrorDialog extends BiometricErrorDialog {
|
||||
static FaceErrorDialog newInstance(CharSequence msg, int msgId) {
|
||||
FaceErrorDialog dialog = new FaceErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putCharSequence(KEY_ERROR_MSG, msg);
|
||||
args.putInt(KEY_ERROR_ID, msgId);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.DIALOG_FACE_ERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTitleResId() {
|
||||
return R.string.security_settings_face_enroll_error_dialog_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOkButtonTextResId() {
|
||||
return R.string.security_settings_face_enroll_dialog_ok;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.face_enroll_enrolling);
|
||||
setHeaderText(R.string.security_settings_face_enroll_repeat_title);
|
||||
mErrorText = findViewById(R.id.error_text);
|
||||
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
|
||||
this, android.R.interpolator.linear_out_slow_in);
|
||||
|
||||
Button skipButton = findViewById(R.id.skip_button);
|
||||
skipButton.setOnClickListener(this);
|
||||
|
||||
if (shouldLaunchConfirmLock()) {
|
||||
launchConfirmLock(R.string.security_settings_face_preference_title,
|
||||
Utils.getFaceManagerOrNull(this).preEnroll());
|
||||
mShouldFinishOnStop = false;
|
||||
} else {
|
||||
startEnrollment();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFinishIntent() {
|
||||
return new Intent(this, FaceEnrollFinish.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BiometricEnrollSidecar getSidecar() {
|
||||
return new FaceEnrollSidecar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldStartAutomatically() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldFinishOnStop() {
|
||||
return mShouldFinishOnStop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FACE_ENROLL_ENROLLING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentHelp(CharSequence helpString) {
|
||||
if (!TextUtils.isEmpty(helpString)) {
|
||||
showError(helpString);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentError(int errMsgId, CharSequence errString) {
|
||||
int msgId;
|
||||
switch (errMsgId) {
|
||||
case FaceManager.FACE_ERROR_TIMEOUT:
|
||||
msgId = R.string.security_settings_face_enroll_error_timeout_dialog_message;
|
||||
break;
|
||||
default:
|
||||
msgId = R.string.security_settings_face_enroll_error_generic_dialog_message;
|
||||
break;
|
||||
}
|
||||
showErrorDialog(getText(msgId), errMsgId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentProgressChange(int steps, int remaining) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "Steps: " + steps + " Remaining: " + remaining);
|
||||
}
|
||||
// TODO: Update the actual animation
|
||||
showError("Steps: " + steps + " Remaining: " + remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (requestCode == CONFIRM_REQUEST) {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
mShouldFinishOnStop = true;
|
||||
mToken = data.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
|
||||
getIntent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
|
||||
startEnrollment();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
} else {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
|
||||
private void showErrorDialog(CharSequence msg, int msgId) {
|
||||
BiometricErrorDialog dialog = FaceErrorDialog.newInstance(msg, msgId);
|
||||
dialog.show(getFragmentManager(), FaceErrorDialog.class.getName());
|
||||
}
|
||||
|
||||
private void showError(CharSequence error) {
|
||||
mErrorText.setText(error);
|
||||
if (mErrorText.getVisibility() == View.INVISIBLE) {
|
||||
mErrorText.setVisibility(View.VISIBLE);
|
||||
mErrorText.setTranslationY(getResources().getDimensionPixelSize(
|
||||
R.dimen.fingerprint_error_text_appear_distance));
|
||||
mErrorText.setAlpha(0f);
|
||||
mErrorText.animate()
|
||||
.alpha(1f)
|
||||
.translationY(0f)
|
||||
.setDuration(200)
|
||||
.setInterpolator(mLinearOutSlowInInterpolator)
|
||||
.start();
|
||||
} else {
|
||||
mErrorText.animate().cancel();
|
||||
mErrorText.setAlpha(1f);
|
||||
mErrorText.setTranslationY(0f);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.biometrics.face;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
|
||||
/**
|
||||
* Activity which concludes face enrollment.
|
||||
*/
|
||||
public class FaceEnrollFinish extends BiometricEnrollBase {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.face_enroll_finish);
|
||||
setHeaderText(R.string.security_settings_face_enroll_finish_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FACE_ENROLL_FINISHED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNextButtonClick() {
|
||||
setResult(RESULT_FINISHED);
|
||||
finish();
|
||||
}
|
||||
}
|
@@ -113,8 +113,8 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFindSensorIntent() {
|
||||
return null; // TODO
|
||||
protected Intent getEnrollingIntent() {
|
||||
return new Intent(this, FaceEnrollEnrolling.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.settings.biometrics.face;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.hardware.face.FaceManager;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar;
|
||||
|
||||
/**
|
||||
* Sidecar fragment to handle the state around face enrollment
|
||||
*/
|
||||
public class FaceEnrollSidecar extends BiometricEnrollSidecar {
|
||||
|
||||
private FaceManager mFaceManager;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
mFaceManager = Utils.getFaceManagerOrNull(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEnrollment() {
|
||||
super.startEnrollment();
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
mFaceManager.setActiveUser(mUserId);
|
||||
}
|
||||
mFaceManager.enroll(mToken, mEnrollmentCancel,
|
||||
0 /* flags */, mUserId, mEnrollmentCallback);
|
||||
}
|
||||
|
||||
private FaceManager.EnrollmentCallback mEnrollmentCallback
|
||||
= new FaceManager.EnrollmentCallback() {
|
||||
|
||||
@Override
|
||||
public void onEnrollmentProgress(int remaining) {
|
||||
FaceEnrollSidecar.super.onEnrollmentProgress(remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
|
||||
FaceEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentError(int errMsgId, CharSequence errString) {
|
||||
FaceEnrollSidecar.super.onEnrollmentError(errMsgId, errString);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FACE_ENROLL_SIDECAR;
|
||||
}
|
||||
}
|
@@ -18,7 +18,6 @@ package com.android.settings.biometrics.fingerprint;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
@@ -30,7 +29,6 @@ import android.graphics.drawable.LayerDrawable;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.media.AudioAttributes;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.text.TextUtils;
|
||||
@@ -44,15 +42,15 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar;
|
||||
import com.android.settings.biometrics.BiometricErrorDialog;
|
||||
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
/**
|
||||
* Activity which handles the actual enrolling for fingerprint.
|
||||
*/
|
||||
public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
implements FingerprintEnrollSidecar.Listener {
|
||||
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
|
||||
static final String TAG_SIDECAR = "sidecar";
|
||||
|
||||
@@ -93,13 +91,38 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
private Interpolator mLinearOutSlowInInterpolator;
|
||||
private Interpolator mFastOutLinearInInterpolator;
|
||||
private int mIconTouchCount;
|
||||
private FingerprintEnrollSidecar mSidecar;
|
||||
private boolean mAnimationCancelled;
|
||||
private AnimatedVectorDrawable mIconAnimationDrawable;
|
||||
private AnimatedVectorDrawable mIconBackgroundBlinksDrawable;
|
||||
private boolean mRestoring;
|
||||
private Vibrator mVibrator;
|
||||
|
||||
public static class FingerprintErrorDialog extends BiometricErrorDialog {
|
||||
static FingerprintErrorDialog newInstance(CharSequence msg, int msgId) {
|
||||
FingerprintErrorDialog dialog = new FingerprintErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putCharSequence(KEY_ERROR_MSG, msg);
|
||||
args.putInt(KEY_ERROR_ID, msgId);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.DIALOG_FINGERPINT_ERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTitleResId() {
|
||||
return R.string.security_settings_fingerprint_enroll_error_dialog_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOkButtonTextResId() {
|
||||
return R.string.security_settings_fingerprint_enroll_dialog_ok;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -147,15 +170,19 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
mRestoring = savedInstanceState != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BiometricEnrollSidecar getSidecar() {
|
||||
return new FingerprintEnrollSidecar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldStartAutomatically() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mSidecar = (FingerprintEnrollSidecar) getFragmentManager().findFragmentByTag(TAG_SIDECAR);
|
||||
if (mSidecar == null) {
|
||||
mSidecar = new FingerprintEnrollSidecar();
|
||||
getFragmentManager().beginTransaction().add(mSidecar, TAG_SIDECAR).commit();
|
||||
}
|
||||
mSidecar.setListener(this);
|
||||
updateProgress(false /* animate */);
|
||||
updateDescription();
|
||||
if (mRestoring) {
|
||||
@@ -182,40 +209,7 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (mSidecar != null) {
|
||||
mSidecar.setListener(null);
|
||||
}
|
||||
stopIconAnimation();
|
||||
if (!isChangingConfigurations()) {
|
||||
if (mSidecar != null) {
|
||||
mSidecar.cancelEnrollment();
|
||||
getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (mSidecar != null) {
|
||||
mSidecar.setListener(null);
|
||||
mSidecar.cancelEnrollment();
|
||||
getFragmentManager().beginTransaction().remove(mSidecar).commitAllowingStateLoss();
|
||||
mSidecar = null;
|
||||
}
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.skip_button:
|
||||
setResult(RESULT_SKIP);
|
||||
finish();
|
||||
break;
|
||||
default:
|
||||
super.onClick(v);
|
||||
}
|
||||
}
|
||||
|
||||
private void animateProgress(int progress) {
|
||||
@@ -235,20 +229,6 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
mIconBackgroundBlinksDrawable.start();
|
||||
}
|
||||
|
||||
private void launchFinish(byte[] token) {
|
||||
Intent intent = getFinishIntent();
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
|
||||
}
|
||||
startActivity(intent);
|
||||
overridePendingTransition(R.anim.suw_slide_next_in, R.anim.suw_slide_next_out);
|
||||
finish();
|
||||
}
|
||||
|
||||
protected Intent getFinishIntent() {
|
||||
return new Intent(this, FingerprintEnrollFinish.class);
|
||||
}
|
||||
@@ -263,7 +243,6 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnrollmentHelp(CharSequence helpString) {
|
||||
if (!TextUtils.isEmpty(helpString)) {
|
||||
@@ -323,8 +302,8 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
}
|
||||
|
||||
private void showErrorDialog(CharSequence msg, int msgId) {
|
||||
ErrorDialog dlg = ErrorDialog.newInstance(msg, msgId);
|
||||
dlg.show(getFragmentManager(), ErrorDialog.class.getName());
|
||||
BiometricErrorDialog dlg = FingerprintErrorDialog.newInstance(msg, msgId);
|
||||
dlg.show(getFragmentManager(), FingerprintErrorDialog.class.getName());
|
||||
}
|
||||
|
||||
private void showIconTouchDialog() {
|
||||
@@ -455,54 +434,4 @@ public class FingerprintEnrollEnrolling extends BiometricEnrollBase
|
||||
return MetricsEvent.DIALOG_FINGERPRINT_ICON_TOUCH;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ErrorDialog extends InstrumentedDialogFragment {
|
||||
|
||||
/**
|
||||
* Create a new instance of ErrorDialog.
|
||||
*
|
||||
* @param msg the string to show for message text
|
||||
* @param msgId the FingerprintManager error id so we know the cause
|
||||
* @return a new ErrorDialog
|
||||
*/
|
||||
static ErrorDialog newInstance(CharSequence msg, int msgId) {
|
||||
ErrorDialog dlg = new ErrorDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putCharSequence("error_msg", msg);
|
||||
args.putInt("error_id", msgId);
|
||||
dlg.setArguments(args);
|
||||
return dlg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
CharSequence errorString = getArguments().getCharSequence("error_msg");
|
||||
final int errMsgId = getArguments().getInt("error_id");
|
||||
builder.setTitle(R.string.security_settings_fingerprint_enroll_error_dialog_title)
|
||||
.setMessage(errorString)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.security_settings_fingerprint_enroll_dialog_ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.dismiss();
|
||||
boolean wasTimeout =
|
||||
errMsgId == FingerprintManager.FINGERPRINT_ERROR_TIMEOUT;
|
||||
Activity activity = getActivity();
|
||||
activity.setResult(wasTimeout ?
|
||||
RESULT_TIMEOUT : RESULT_FINISHED);
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.DIALOG_FINGERPINT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,16 +19,14 @@ package com.android.settings.biometrics.fingerprint;
|
||||
import android.content.Intent;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.BiometricEnrollBase;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollSidecar.Listener;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar.Listener;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -38,14 +36,9 @@ import androidx.annotation.Nullable;
|
||||
*/
|
||||
public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
|
||||
|
||||
@VisibleForTesting
|
||||
static final int CONFIRM_REQUEST = 1;
|
||||
private static final int ENROLLING = 2;
|
||||
public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
|
||||
|
||||
@Nullable
|
||||
private FingerprintFindSensorAnimation mAnimation;
|
||||
private boolean mLaunchedConfirmLock;
|
||||
|
||||
private FingerprintEnrollSidecar mSidecar;
|
||||
private boolean mNextClicked;
|
||||
|
||||
@@ -57,13 +50,10 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
|
||||
skipButton.setOnClickListener(this);
|
||||
|
||||
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
|
||||
if (savedInstanceState != null) {
|
||||
mLaunchedConfirmLock = savedInstanceState.getBoolean(EXTRA_KEY_LAUNCHED_CONFIRM);
|
||||
mToken = savedInstanceState.getByteArray(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
}
|
||||
if (mToken == null && !mLaunchedConfirmLock) {
|
||||
launchConfirmLock();
|
||||
|
||||
if (shouldLaunchConfirmLock()) {
|
||||
launchConfirmLock(R.string.security_settings_fingerprint_preference_title,
|
||||
Utils.getFingerprintManagerOrNull(this).preEnroll());
|
||||
} else if (mToken != null) {
|
||||
startLookingForFingerprint(); // already confirmed, so start looking for fingerprint
|
||||
}
|
||||
@@ -132,13 +122,6 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(EXTRA_KEY_LAUNCHED_CONFIRM, mLaunchedConfirmLock);
|
||||
outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
@@ -209,28 +192,6 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void launchConfirmLock() {
|
||||
long challenge = Utils.getFingerprintManagerOrNull(this).preEnroll();
|
||||
ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
|
||||
boolean launchedConfirmationActivity = false;
|
||||
if (mUserId == UserHandle.USER_NULL) {
|
||||
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(R.string.security_settings_fingerprint_preference_title),
|
||||
null, null, challenge);
|
||||
} else {
|
||||
launchedConfirmationActivity = helper.launchConfirmationActivity(CONFIRM_REQUEST,
|
||||
getString(R.string.security_settings_fingerprint_preference_title),
|
||||
null, null, challenge, mUserId);
|
||||
}
|
||||
if (!launchedConfirmationActivity) {
|
||||
// This shouldn't happen, as we should only end up at this step if a lock thingy is
|
||||
// already set.
|
||||
finish();
|
||||
} else {
|
||||
mLaunchedConfirmLock = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.FINGERPRINT_FIND_SENSOR;
|
||||
|
@@ -117,7 +117,7 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFindSensorIntent() {
|
||||
protected Intent getEnrollingIntent() {
|
||||
return new Intent(this, FingerprintEnrollFindSensor.class);
|
||||
}
|
||||
|
||||
|
@@ -16,164 +16,35 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.InstrumentedFragment;
|
||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar;
|
||||
|
||||
/**
|
||||
* Sidecar fragment to handle the state around fingerprint enrollment.
|
||||
*/
|
||||
public class FingerprintEnrollSidecar extends InstrumentedFragment {
|
||||
public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
|
||||
|
||||
private int mEnrollmentSteps = -1;
|
||||
private int mEnrollmentRemaining = 0;
|
||||
private Listener mListener;
|
||||
private boolean mEnrolling;
|
||||
private CancellationSignal mEnrollmentCancel;
|
||||
private Handler mHandler = new Handler();
|
||||
private byte[] mToken;
|
||||
private boolean mDone;
|
||||
private int mUserId;
|
||||
private FingerprintManager mFingerprintManager;
|
||||
private ArrayList<QueuedEvent> mQueuedEvents;
|
||||
|
||||
private abstract class QueuedEvent {
|
||||
public abstract void send(Listener listener);
|
||||
}
|
||||
|
||||
private class QueuedEnrollmentProgress extends QueuedEvent {
|
||||
int enrollmentSteps;
|
||||
int remaining;
|
||||
public QueuedEnrollmentProgress(int enrollmentSteps, int remaining) {
|
||||
this.enrollmentSteps = enrollmentSteps;
|
||||
this.remaining = remaining;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Listener listener) {
|
||||
listener.onEnrollmentProgressChange(enrollmentSteps, remaining);
|
||||
}
|
||||
}
|
||||
|
||||
private class QueuedEnrollmentHelp extends QueuedEvent {
|
||||
int helpMsgId;
|
||||
CharSequence helpString;
|
||||
public QueuedEnrollmentHelp(int helpMsgId, CharSequence helpString) {
|
||||
this.helpMsgId = helpMsgId;
|
||||
this.helpString = helpString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Listener listener) {
|
||||
listener.onEnrollmentHelp(helpString);
|
||||
}
|
||||
}
|
||||
|
||||
private class QueuedEnrollmentError extends QueuedEvent {
|
||||
int errMsgId;
|
||||
CharSequence errString;
|
||||
public QueuedEnrollmentError(int errMsgId, CharSequence errString) {
|
||||
this.errMsgId = errMsgId;
|
||||
this.errString = errString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Listener listener) {
|
||||
listener.onEnrollmentError(errMsgId, errString);
|
||||
}
|
||||
}
|
||||
|
||||
public FingerprintEnrollSidecar() {
|
||||
mQueuedEvents = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
|
||||
mToken = activity.getIntent().getByteArrayExtra(
|
||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||
mUserId = activity.getIntent().getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (!mEnrolling) {
|
||||
startEnrollment();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (!getActivity().isChangingConfigurations()) {
|
||||
cancelEnrollment();
|
||||
}
|
||||
}
|
||||
|
||||
private void startEnrollment() {
|
||||
mHandler.removeCallbacks(mTimeoutRunnable);
|
||||
mEnrollmentSteps = -1;
|
||||
mEnrollmentCancel = new CancellationSignal();
|
||||
protected void startEnrollment() {
|
||||
super.startEnrollment();
|
||||
if (mUserId != UserHandle.USER_NULL) {
|
||||
mFingerprintManager.setActiveUser(mUserId);
|
||||
}
|
||||
mFingerprintManager.enroll(mToken, mEnrollmentCancel,
|
||||
0 /* flags */, mUserId, mEnrollmentCallback);
|
||||
mEnrolling = true;
|
||||
}
|
||||
|
||||
boolean cancelEnrollment() {
|
||||
mHandler.removeCallbacks(mTimeoutRunnable);
|
||||
if (mEnrolling) {
|
||||
mEnrollmentCancel.cancel();
|
||||
mEnrolling = false;
|
||||
mEnrollmentSteps = -1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
mListener = listener;
|
||||
if (mListener != null) {
|
||||
for (int i=0; i<mQueuedEvents.size(); i++) {
|
||||
QueuedEvent event = mQueuedEvents.get(i);
|
||||
event.send(mListener);
|
||||
}
|
||||
mQueuedEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public int getEnrollmentSteps() {
|
||||
return mEnrollmentSteps;
|
||||
}
|
||||
|
||||
public int getEnrollmentRemaining() {
|
||||
return mEnrollmentRemaining;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return mDone;
|
||||
}
|
||||
|
||||
private FingerprintManager.EnrollmentCallback mEnrollmentCallback
|
||||
@@ -181,42 +52,17 @@ public class FingerprintEnrollSidecar extends InstrumentedFragment {
|
||||
|
||||
@Override
|
||||
public void onEnrollmentProgress(int remaining) {
|
||||
if (mEnrollmentSteps == -1) {
|
||||
mEnrollmentSteps = remaining;
|
||||
}
|
||||
mEnrollmentRemaining = remaining;
|
||||
mDone = remaining == 0;
|
||||
if (mListener != null) {
|
||||
mListener.onEnrollmentProgressChange(mEnrollmentSteps, remaining);
|
||||
} else {
|
||||
mQueuedEvents.add(new QueuedEnrollmentProgress(mEnrollmentSteps, remaining));
|
||||
}
|
||||
FingerprintEnrollSidecar.super.onEnrollmentProgress(remaining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
|
||||
if (mListener != null) {
|
||||
mListener.onEnrollmentHelp(helpString);
|
||||
} else {
|
||||
mQueuedEvents.add(new QueuedEnrollmentHelp(helpMsgId, helpString));
|
||||
}
|
||||
FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnrollmentError(int errMsgId, CharSequence errString) {
|
||||
if (mListener != null) {
|
||||
mListener.onEnrollmentError(errMsgId, errString);
|
||||
} else {
|
||||
mQueuedEvents.add(new QueuedEnrollmentError(errMsgId, errString));
|
||||
}
|
||||
mEnrolling = false;
|
||||
}
|
||||
};
|
||||
|
||||
private final Runnable mTimeoutRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
cancelEnrollment();
|
||||
FingerprintEnrollSidecar.super.onEnrollmentError(errMsgId, errString);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -224,14 +70,4 @@ public class FingerprintEnrollSidecar extends InstrumentedFragment {
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.FINGERPRINT_ENROLL_SIDECAR;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onEnrollmentHelp(CharSequence helpString);
|
||||
void onEnrollmentError(int errMsgId, CharSequence errString);
|
||||
void onEnrollmentProgressChange(int steps, int remaining);
|
||||
}
|
||||
|
||||
public boolean isEnrolling() {
|
||||
return mEnrolling;
|
||||
}
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent getFindSensorIntent() {
|
||||
protected Intent getEnrollingIntent() {
|
||||
final Intent intent = new Intent(this, SetupFingerprintEnrollFindSensor.class);
|
||||
SetupWizardUtils.copySetupExtras(getIntent(), intent);
|
||||
return intent;
|
||||
|
@@ -157,7 +157,7 @@ public class FingerprintEnrollFindSensorTest {
|
||||
@Test
|
||||
public void onActivityResult_withNullIntentShouldNotCrash() {
|
||||
// this should not crash
|
||||
mActivity.onActivityResult(FingerprintEnrollFindSensor.CONFIRM_REQUEST, Activity.RESULT_OK,
|
||||
mActivity.onActivityResult(BiometricEnrollBase.CONFIRM_REQUEST, Activity.RESULT_OK,
|
||||
null);
|
||||
assertThat(Shadows.shadowOf(mActivity).getResultCode()).isEqualTo(Activity.RESULT_CANCELED);
|
||||
}
|
||||
|
Reference in New Issue
Block a user