Files
app_Settings/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
Milton Wu 20c73a9b06 Attach v2 EnrollingSfpsFragment to activity
1. Attach FingerprintEnrollEnrollingSfpsFragment to
   FingerprintEnrollmentActivity.
2. Refine FinSensor rotation case for SFPS and RFPS

Bug: 260957939
Test: atest FingerprintEnrollmentActivityTest
Change-Id: Ibbeff8deb009271df044480f9f5d6c64ab6e6264
2023-02-20 03:48:16 +00:00

382 lines
12 KiB
Java

/*
* Copyright (C) 2023 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.biometrics2.ui.viewmodel;
import android.annotation.IntDef;
import android.app.Application;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.android.settings.biometrics2.data.repository.AccessibilityRepository;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
import com.android.settings.biometrics2.data.repository.VibratorRepository;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* ViewModel explaining the fingerprint enrolling page
*/
public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel {
private static final String TAG = FingerprintEnrollEnrollingViewModel.class.getSimpleName();
private static final boolean DEBUG = false;
private static final VibrationEffect VIBRATE_EFFECT_ERROR =
VibrationEffect.createWaveform(new long[]{0, 5, 55, 60}, -1);
private static final VibrationAttributes FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY);
/**
* Enrolling skipped
*/
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP = 0;
/**
* Enrolling finished
*/
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE = 1;
/**
* Icon touch dialog show
*/
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG = 2;
/**
* Icon touch dialog dismiss
*/
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_ICON_TOUCH_DIALOG = 3;
/**
* Has got latest cancelled event due to back key
*/
public static final int FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED = 4;
@IntDef(prefix = { "FINGERPRINT_ENROLL_ENROLLING_ACTION_" }, value = {
FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP,
FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE,
FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG,
FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_ICON_TOUCH_DIALOG,
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED
})
@Retention(RetentionPolicy.SOURCE)
public @interface FingerprintEnrollEnrollingAction {}
/**
* Enrolling skipped
*/
public static final int FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH = 0;
/**
* Enrolling finished
*/
public static final int FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT = 1;
/**
* Icon touch dialog show
*/
public static final int FINGERPRINT_ERROR_DIALOG_ACTION_RESTART = 2;
@IntDef(prefix = { "FINGERPRINT_ERROR_DIALOG_ACTION_" }, value = {
FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH,
FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT,
FINGERPRINT_ERROR_DIALOG_ACTION_RESTART
})
@Retention(RetentionPolicy.SOURCE)
public @interface FingerprintErrorDialogAction {}
private final int mUserId;
private boolean mOnBackPressed;
private boolean mOnSkipPressed;
private final FingerprintRepository mFingerprintRepository;
private final AccessibilityRepository mAccessibilityRepository;
private final VibratorRepository mVibratorRepository;
private final MutableLiveData<Integer> mActionLiveData = new MutableLiveData<>();
private final MutableLiveData<Integer> mIconTouchDialogLiveData = new MutableLiveData<>();
private final MutableLiveData<ErrorDialogData> mErrorDialogLiveData = new MutableLiveData<>();
private final MutableLiveData<Integer> mErrorDialogActionLiveData = new MutableLiveData<>();
public FingerprintEnrollEnrollingViewModel(Application application,
int userId,
FingerprintRepository fingerprintRepository,
AccessibilityRepository accessibilityRepository,
VibratorRepository vibratorRepository) {
super(application);
mUserId = userId;
mFingerprintRepository = fingerprintRepository;
mAccessibilityRepository = accessibilityRepository;
mVibratorRepository = vibratorRepository;
}
/**
* Notifies activity to show error dialog
*/
public void showErrorDialog(@NonNull ErrorDialogData errorDialogData) {
mErrorDialogLiveData.postValue(errorDialogData);
}
public LiveData<ErrorDialogData> getErrorDialogLiveData() {
return mErrorDialogLiveData;
}
public LiveData<Integer> getErrorDialogActionLiveData() {
return mErrorDialogActionLiveData;
}
public LiveData<Integer> getActionLiveData() {
return mActionLiveData;
}
/**
* Clears action live data
*/
public void clearActionLiveData() {
mActionLiveData.setValue(null);
}
/**
* Saves new user dialog action to mErrorDialogActionLiveData
*/
public void onErrorDialogAction(@FingerprintErrorDialogAction int action) {
if (DEBUG) {
Log.d(TAG, "onErrorDialogAction(" + action + ")");
}
mErrorDialogActionLiveData.postValue(action);
}
public boolean getOnSkipPressed() {
return mOnSkipPressed;
}
/**
* User clicks skip button
*/
public void setOnSkipPressed() {
mOnSkipPressed = true;
}
/**
* Enrolling is cacelled because user clicks skip
*/
public void onCancelledDueToOnSkipPressed() {
final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP;
if (DEBUG) {
Log.d(TAG, "onSkipButtonClick, post action " + action);
}
mOnSkipPressed = false;
mActionLiveData.postValue(action);
}
/**
* Is enrolling finished
*/
public void onEnrollingDone() {
final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE;
if (DEBUG) {
Log.d(TAG, "onEnrollingDone, post action " + action);
}
mActionLiveData.postValue(action);
}
public boolean getOnBackPressed() {
return mOnBackPressed;
}
/**
* Back key is pressed.
*/
public void setOnBackPressed() {
mOnBackPressed = true;
}
/**
* Enrollment is cancelled because back key is pressed.
*/
public void onCancelledDueToOnBackPressed() {
final int action = FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
if (DEBUG) {
Log.d(TAG, "onCancelledEventReceivedAfterOnBackPressed, post action " + action);
}
mOnBackPressed = false;
mActionLiveData.postValue(action);
}
/**
* Icon touch dialog show
*/
public void onIconTouchDialogShow() {
final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
if (DEBUG) {
Log.d(TAG, "onIconTouchDialogShow, post action " + action);
}
mIconTouchDialogLiveData.postValue(action);
}
/**
* Icon touch dialog dismiss
*/
public void onIconTouchDialogDismiss() {
final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_ICON_TOUCH_DIALOG;
if (DEBUG) {
Log.d(TAG, "onIconTouchDialogDismiss, post action " + action);
}
mIconTouchDialogLiveData.postValue(action);
}
/**
* get enroll stage threshold
*/
public float getEnrollStageThreshold(int index) {
return mFingerprintRepository.getEnrollStageThreshold(index);
}
/**
* Get enroll stage count
*/
public int getEnrollStageCount() {
return mFingerprintRepository.getEnrollStageCount();
}
/**
* Requests interruption of the accessibility feedback from all accessibility services.
*/
public void clearTalkback() {
mAccessibilityRepository.interrupt();
}
/**
* Returns if the {@link AccessibilityManager} is enabled.
*
* @return True if this {@link AccessibilityManager} is enabled, false otherwise.
*/
public boolean isAccessibilityEnabled() {
return mAccessibilityRepository.isEnabled();
}
/**
* Sends an {@link AccessibilityEvent}.
*
* @param event The event to send.
*
* @throws IllegalStateException if accessibility is not enabled.
*
* <strong>Note:</strong> The preferred mechanism for sending custom accessibility
* events is through calling
* {@link android.view.ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
* instead of this method to allow predecessors to augment/filter events sent by
* their descendants.
*/
public void sendAccessibilityEvent(@NonNull AccessibilityEvent event) {
mAccessibilityRepository.sendAccessibilityEvent(event);
}
/**
* Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
* caller to specify the vibration is owned by someone else and set a reason for vibration.
*/
public void vibrateError(String reason) {
mVibratorRepository.vibrate(mUserId, getApplication().getOpPackageName(),
VIBRATE_EFFECT_ERROR, reason, FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES);
}
/**
* Gets the first FingerprintSensorPropertiesInternal from FingerprintManager
*/
@Nullable
public FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() {
return mFingerprintRepository.getFirstFingerprintSensorPropertiesInternal();
}
/**
* The first sensor type is UDFPS sensor or not
*/
public boolean canAssumeUdfps() {
return mFingerprintRepository.canAssumeUdfps();
}
/**
* Saves current state to outState
*/
public void onSaveInstanceState(@NonNull Bundle outState) {
// TODO
// mRestoring = true;
// mIsCanceled = savedInstanceState.getBoolean(KEY_STATE_CANCELED, false);
// mPreviousRotation = savedInstanceState.getInt(KEY_STATE_PREVIOUS_ROTATION,
// getDisplay().getRotation());
// mIsOrientationChanged = mPreviousRotation != getDisplay().getRotation();
}
/**
* Restores saved state from previous savedInstanceState
*/
public void restoreSavedState(@Nullable Bundle savedInstanceState) {
if (savedInstanceState == null) {
return;
}
// TODO
// outState.putBoolean(KEY_STATE_CANCELED, mIsCanceled);
// outState.putInt(KEY_STATE_PREVIOUS_ROTATION, mPreviousRotation);
}
/**
* Data for passing to FingerprintEnrollEnrollingErrorDialog
*/
public static class ErrorDialogData {
@NonNull private final CharSequence mErrMsg;
@NonNull private final CharSequence mErrTitle;
@NonNull private final int mErrMsgId;
public ErrorDialogData(@NonNull CharSequence errMsg, @NonNull CharSequence errTitle,
int errMsgId) {
mErrMsg = errMsg;
mErrTitle = errTitle;
mErrMsgId = errMsgId;
}
public CharSequence getErrMsg() {
return mErrMsg;
}
public CharSequence getErrTitle() {
return mErrTitle;
}
public int getErrMsgId() {
return mErrMsgId;
}
@Override
public String toString() {
return getClass().getSimpleName() + "@" + Integer.toHexString(hashCode())
+ "{id:" + mErrMsgId + "}";
}
}
}