1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.biometrics2.ui.viewmodel; 18 19 import android.annotation.IntDef; 20 import android.app.Application; 21 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 22 import android.os.VibrationAttributes; 23 import android.os.VibrationEffect; 24 import android.os.Vibrator; 25 import android.util.Log; 26 import android.view.accessibility.AccessibilityEvent; 27 import android.view.accessibility.AccessibilityManager; 28 29 import androidx.annotation.NonNull; 30 import androidx.annotation.Nullable; 31 import androidx.lifecycle.AndroidViewModel; 32 import androidx.lifecycle.LiveData; 33 import androidx.lifecycle.MutableLiveData; 34 35 import com.android.settings.biometrics2.data.repository.FingerprintRepository; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 40 /** 41 * ViewModel explaining the fingerprint enrolling page 42 */ 43 public class FingerprintEnrollEnrollingViewModel extends AndroidViewModel { 44 45 private static final String TAG = FingerprintEnrollEnrollingViewModel.class.getSimpleName(); 46 private static final boolean DEBUG = false; 47 48 private static final VibrationEffect VIBRATE_EFFECT_ERROR = 49 VibrationEffect.createWaveform(new long[]{0, 5, 55, 60}, -1); 50 private static final VibrationAttributes FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES = 51 VibrationAttributes.createForUsage(VibrationAttributes.USAGE_ACCESSIBILITY); 52 53 /** 54 * Enrolling finished 55 */ 56 public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE = 0; 57 58 /** 59 * Icon touch dialog show 60 */ 61 public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG = 1; 62 63 /** 64 * Has got latest cancelled event due to user skip 65 */ 66 public static final int FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP = 2; 67 68 /** 69 * Has got latest cancelled event due to back key 70 */ 71 public static final int FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED = 3; 72 73 @IntDef(prefix = { "FINGERPRINT_ENROLL_ENROLLING_ACTION_" }, value = { 74 FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE, 75 FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG, 76 FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP 77 }) 78 @Retention(RetentionPolicy.SOURCE) 79 public @interface FingerprintEnrollEnrollingAction {} 80 81 private final int mUserId; 82 private boolean mOnBackPressed; 83 private boolean mOnSkipPressed; 84 @NonNull private final FingerprintRepository mFingerprintRepository; 85 private final AccessibilityManager mAccessibilityManager; 86 private final Vibrator mVibrator; 87 88 private final MutableLiveData<Integer> mActionLiveData = new MutableLiveData<>(); 89 FingerprintEnrollEnrollingViewModel( @onNull Application application, int userId, @NonNull FingerprintRepository fingerprintRepository )90 public FingerprintEnrollEnrollingViewModel( 91 @NonNull Application application, 92 int userId, 93 @NonNull FingerprintRepository fingerprintRepository 94 ) { 95 super(application); 96 mUserId = userId; 97 mFingerprintRepository = fingerprintRepository; 98 mAccessibilityManager = application.getSystemService(AccessibilityManager.class); 99 mVibrator = application.getSystemService(Vibrator.class); 100 } 101 getActionLiveData()102 public LiveData<Integer> getActionLiveData() { 103 return mActionLiveData; 104 } 105 106 /** 107 * Clears action live data 108 */ clearActionLiveData()109 public void clearActionLiveData() { 110 mActionLiveData.setValue(null); 111 } 112 getOnSkipPressed()113 public boolean getOnSkipPressed() { 114 return mOnSkipPressed; 115 } 116 117 /** 118 * User clicks skip button 119 */ setOnSkipPressed()120 public void setOnSkipPressed() { 121 mOnSkipPressed = true; 122 } 123 124 /** 125 * Enrolling is cancelled because user clicks skip 126 */ onCancelledDueToOnSkipPressed()127 public void onCancelledDueToOnSkipPressed() { 128 final int action = FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP; 129 if (DEBUG) { 130 Log.d(TAG, "onSkipButtonClick, post action " + action); 131 } 132 mOnSkipPressed = false; 133 mActionLiveData.postValue(action); 134 } 135 136 /** 137 * Is enrolling finished 138 */ onEnrollingDone()139 public void onEnrollingDone() { 140 final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE; 141 if (DEBUG) { 142 Log.d(TAG, "onEnrollingDone, post action " + action); 143 } 144 mActionLiveData.postValue(action); 145 } 146 getOnBackPressed()147 public boolean getOnBackPressed() { 148 return mOnBackPressed; 149 } 150 151 /** 152 * Back key is pressed. 153 */ setOnBackPressed()154 public void setOnBackPressed() { 155 mOnBackPressed = true; 156 } 157 158 /** 159 * Enrollment is cancelled because back key is pressed. 160 */ onCancelledDueToOnBackPressed()161 public void onCancelledDueToOnBackPressed() { 162 final int action = FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED; 163 if (DEBUG) { 164 Log.d(TAG, "onCancelledEventReceivedAfterOnBackPressed, post action " + action); 165 } 166 mOnBackPressed = false; 167 mActionLiveData.postValue(action); 168 } 169 170 /** 171 * Icon touch dialog show 172 */ showIconTouchDialog()173 public void showIconTouchDialog() { 174 final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG; 175 if (DEBUG) { 176 Log.d(TAG, "onIconTouchDialogShow, post action " + action); 177 } 178 mActionLiveData.postValue(action); 179 } 180 181 /** 182 * get enroll stage threshold 183 */ getEnrollStageThreshold(int index)184 public float getEnrollStageThreshold(int index) { 185 return mFingerprintRepository.getEnrollStageThreshold(index); 186 } 187 188 /** 189 * Get enroll stage count 190 */ getEnrollStageCount()191 public int getEnrollStageCount() { 192 return mFingerprintRepository.getEnrollStageCount(); 193 } 194 195 /** 196 * Requests interruption of the accessibility feedback from all accessibility services. 197 */ clearTalkback()198 public void clearTalkback() { 199 mAccessibilityManager.interrupt(); 200 } 201 202 /** 203 * Returns if the {@link AccessibilityManager} is enabled. 204 * 205 * @return True if this {@link AccessibilityManager} is enabled, false otherwise. 206 */ isAccessibilityEnabled()207 public boolean isAccessibilityEnabled() { 208 return mAccessibilityManager.isEnabled(); 209 } 210 211 /** 212 * Sends an {@link AccessibilityEvent}. 213 */ sendAccessibilityEvent(CharSequence announcement)214 public void sendAccessibilityEvent(CharSequence announcement) { 215 AccessibilityEvent e = AccessibilityEvent.obtain(); 216 e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT); 217 e.setClassName(getClass().getName()); 218 e.setPackageName(getApplication().getPackageName()); 219 e.getText().add(announcement); 220 mAccessibilityManager.sendAccessibilityEvent(e); 221 } 222 223 /** 224 * Returns if the touch exploration in the system is enabled. 225 * 226 * @return True if touch exploration is enabled, false otherwise. 227 */ isTouchExplorationEnabled()228 public boolean isTouchExplorationEnabled() { 229 return mAccessibilityManager.isTouchExplorationEnabled(); 230 } 231 232 /** 233 * Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the 234 * caller to specify the vibration is owned by someone else and set a reason for vibration. 235 */ vibrateError(String reason)236 public void vibrateError(String reason) { 237 mVibrator.vibrate(mUserId, getApplication().getOpPackageName(), 238 VIBRATE_EFFECT_ERROR, reason, FINGERPRINT_ENROLLING_SONFICATION_ATTRIBUTES); 239 } 240 241 /** 242 * Gets the first FingerprintSensorPropertiesInternal from FingerprintManager 243 */ 244 @Nullable getFirstFingerprintSensorPropertiesInternal()245 public FingerprintSensorPropertiesInternal getFirstFingerprintSensorPropertiesInternal() { 246 return mFingerprintRepository.getFirstFingerprintSensorPropertiesInternal(); 247 } 248 } 249