Biometrics Enrollment refactor (7/N)
This cl moves the creation of repos and interactors to the SettingsApplication. Bug: 297082837 Test: atest Change-Id: I9049da6f03bb1dc18d4186961444bf613d773d0e
@@ -108,6 +108,8 @@ android_library {
|
|||||||
"telephony_flags_core_java_lib",
|
"telephony_flags_core_java_lib",
|
||||||
"setupdesign-lottie-loading-layout",
|
"setupdesign-lottie-loading-layout",
|
||||||
"device_policy_aconfig_flags_lib",
|
"device_policy_aconfig_flags_lib",
|
||||||
|
"kotlinx-coroutines-core",
|
||||||
|
"kotlinx-coroutines-android",
|
||||||
],
|
],
|
||||||
|
|
||||||
plugins: ["androidx.room_room-compiler-plugin"],
|
plugins: ["androidx.room_room-compiler-plugin"],
|
||||||
|
@@ -24,9 +24,11 @@ import android.provider.Settings;
|
|||||||
import android.util.FeatureFlagUtils;
|
import android.util.FeatureFlagUtils;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
import com.android.settings.activityembedding.ActivityEmbeddingRulesController;
|
||||||
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||||
|
import com.android.settings.biometrics.fingerprint2.BiometricsEnvironment;
|
||||||
import com.android.settings.core.instrumentation.ElapsedTimeUtils;
|
import com.android.settings.core.instrumentation.ElapsedTimeUtils;
|
||||||
import com.android.settings.development.DeveloperOptionsActivityLifecycle;
|
import com.android.settings.development.DeveloperOptionsActivityLifecycle;
|
||||||
import com.android.settings.fuelgauge.BatterySettingsStorage;
|
import com.android.settings.fuelgauge.BatterySettingsStorage;
|
||||||
@@ -47,6 +49,7 @@ import java.lang.ref.WeakReference;
|
|||||||
public class SettingsApplication extends Application {
|
public class SettingsApplication extends Application {
|
||||||
|
|
||||||
private WeakReference<SettingsHomepageActivity> mHomeActivity = new WeakReference<>(null);
|
private WeakReference<SettingsHomepageActivity> mHomeActivity = new WeakReference<>(null);
|
||||||
|
private BiometricsEnvironment mBiometricsEnvironment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void attachBaseContext(Context base) {
|
protected void attachBaseContext(Context base) {
|
||||||
@@ -70,6 +73,7 @@ public class SettingsApplication extends Application {
|
|||||||
|
|
||||||
// Set Spa environment.
|
// Set Spa environment.
|
||||||
setSpaEnvironment();
|
setSpaEnvironment();
|
||||||
|
mBiometricsEnvironment = new BiometricsEnvironment(this);
|
||||||
|
|
||||||
if (ActivityEmbeddingUtils.isSettingsSplitEnabled(this)
|
if (ActivityEmbeddingUtils.isSettingsSplitEnabled(this)
|
||||||
&& FeatureFlagUtils.isEnabled(this,
|
&& FeatureFlagUtils.isEnabled(this,
|
||||||
@@ -111,6 +115,11 @@ public class SettingsApplication extends Application {
|
|||||||
return mHomeActivity.get();
|
return mHomeActivity.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public BiometricsEnvironment getBiometricEnvironment() {
|
||||||
|
return mBiometricsEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTrimMemory(int level) {
|
public void onTrimMemory(int level) {
|
||||||
super.onTrimMemory(level);
|
super.onTrimMemory(level);
|
||||||
|
@@ -184,7 +184,6 @@ public class UdfpsEnrollHelper extends InstrumentedFragment {
|
|||||||
*/
|
*/
|
||||||
public void onAcquired(boolean isAcquiredGood) {
|
public void onAcquired(boolean isAcquiredGood) {
|
||||||
if (mListener != null) {
|
if (mListener != null) {
|
||||||
Log.e("JRM", "OnaCquired " + isAcquiredGood + " lastStepIsGood" + animateIfLastStep());
|
|
||||||
mListener.onAcquired(isAcquiredGood && animateIfLastStep());
|
mListener.onAcquired(isAcquiredGood && animateIfLastStep());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fingerprint2
|
||||||
|
|
||||||
|
import android.hardware.fingerprint.FingerprintManager
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.accessibility.AccessibilityManager
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.lifecycle.ViewModelStore
|
||||||
|
import androidx.lifecycle.ViewModelStoreOwner
|
||||||
|
import com.android.internal.widget.LockPatternUtils
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
|
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.DebuggingRepository
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.DebuggingRepositoryImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepositoryImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.debug.data.repository.UdfpsEnrollDebugRepositoryImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.debug.domain.interactor.DebugTouchEventInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DebuggingInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DebuggingInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintSensorInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintSensorInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.TouchEventInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.lib.model.Settings
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
import kotlinx.coroutines.MainScope
|
||||||
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class should handle all repo & interactor creation needed by the ViewModels for the
|
||||||
|
* biometrics code.
|
||||||
|
*
|
||||||
|
* This code is instantiated within the [SettingsApplication], all repos should be private &
|
||||||
|
* immutable and all interactors should public and immutable
|
||||||
|
*/
|
||||||
|
class BiometricsEnvironment(context: SettingsApplication) : ViewModelStoreOwner {
|
||||||
|
|
||||||
|
private val executorService = Executors.newSingleThreadExecutor()
|
||||||
|
private val backgroundDispatcher = executorService.asCoroutineDispatcher()
|
||||||
|
private val applicationScope = MainScope()
|
||||||
|
private val gateKeeperPasswordProvider = GatekeeperPasswordProvider(LockPatternUtils(context))
|
||||||
|
private val fingerprintManager =
|
||||||
|
context.getSystemService(FragmentActivity.FINGERPRINT_SERVICE) as FingerprintManager?
|
||||||
|
|
||||||
|
private val fingerprintSensorRepository: FingerprintSensorRepository =
|
||||||
|
FingerprintSensorRepositoryImpl(fingerprintManager, backgroundDispatcher, applicationScope)
|
||||||
|
private val debuggingRepository: DebuggingRepository = DebuggingRepositoryImpl()
|
||||||
|
private val udfpsDebugRepo = UdfpsEnrollDebugRepositoryImpl()
|
||||||
|
|
||||||
|
/** For now, interactors are public to those with access to the [BiometricsEnvironment] class */
|
||||||
|
val fingerprintEnrollInteractor: FingerprintEnrollInteractor by lazy {
|
||||||
|
FingerprintEnrollInteractorImpl(context, fingerprintManager, Settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** [FingerprintManagerInteractor] to be used to construct view models */
|
||||||
|
val fingerprintManagerInteractor: FingerprintManagerInteractor by lazy {
|
||||||
|
FingerprintManagerInteractorImpl(
|
||||||
|
context,
|
||||||
|
backgroundDispatcher,
|
||||||
|
fingerprintManager,
|
||||||
|
fingerprintSensorRepository,
|
||||||
|
gateKeeperPasswordProvider,
|
||||||
|
fingerprintEnrollInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val accessibilityInteractor: AccessibilityInteractor by lazy {
|
||||||
|
AccessibilityInteractorImpl(
|
||||||
|
context.getSystemService(AccessibilityManager::class.java)!!,
|
||||||
|
applicationScope,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val foldStateInteractor: FoldStateInteractor by lazy { FoldStateInteractorImpl(context) }
|
||||||
|
|
||||||
|
val orientationInteractor: OrientationInteractor by lazy { OrientationInteractorImpl(context) }
|
||||||
|
|
||||||
|
val vibrationInteractor: VibrationInteractor by lazy { VibrationInteractorImpl(context) }
|
||||||
|
|
||||||
|
val displayDensityInteractor: DisplayDensityInteractor by lazy {
|
||||||
|
DisplayDensityInteractorImpl(context, applicationScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
val debuggingInteractor: DebuggingInteractor by lazy {
|
||||||
|
DebuggingInteractorImpl(debuggingRepository)
|
||||||
|
}
|
||||||
|
|
||||||
|
val enrollStageInteractor: EnrollStageInteractor by lazy { EnrollStageInteractorImpl() }
|
||||||
|
|
||||||
|
val udfpsEnrollInteractor: UdfpsEnrollInteractor by lazy {
|
||||||
|
UdfpsEnrollInteractorImpl(context, accessibilityInteractor)
|
||||||
|
}
|
||||||
|
|
||||||
|
val sensorInteractor: FingerprintSensorInteractor by lazy {
|
||||||
|
FingerprintSensorInteractorImpl(fingerprintSensorRepository)
|
||||||
|
}
|
||||||
|
|
||||||
|
val touchEventInteractor: TouchEventInteractor by lazy {
|
||||||
|
if (debuggingRepository.isDebuggingEnabled()) {
|
||||||
|
DebugTouchEventInteractorImpl(udfpsDebugRepo)
|
||||||
|
} else {
|
||||||
|
object : TouchEventInteractor {
|
||||||
|
override val touchEvent: Flow<MotionEvent> = flowOf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val viewModelStore: ViewModelStore = ViewModelStore()
|
||||||
|
}
|
@@ -23,6 +23,7 @@ interface DebuggingRepository {
|
|||||||
|
|
||||||
/** A function that will return if a build is debuggable */
|
/** A function that will return if a build is debuggable */
|
||||||
fun isDebuggingEnabled(): Boolean
|
fun isDebuggingEnabled(): Boolean
|
||||||
|
|
||||||
/** A function that will return if udfps enrollment should be swapped with debug repos */
|
/** A function that will return if udfps enrollment should be swapped with debug repos */
|
||||||
fun isUdfpsEnrollmentDebuggingEnabled(): Boolean
|
fun isUdfpsEnrollmentDebuggingEnabled(): Boolean
|
||||||
}
|
}
|
||||||
|
@@ -46,7 +46,7 @@ interface FingerprintSensorRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintSensorRepositoryImpl(
|
class FingerprintSensorRepositoryImpl(
|
||||||
fingerprintManager: FingerprintManager,
|
fingerprintManager: FingerprintManager?,
|
||||||
backgroundDispatcher: CoroutineDispatcher,
|
backgroundDispatcher: CoroutineDispatcher,
|
||||||
activityScope: CoroutineScope,
|
activityScope: CoroutineScope,
|
||||||
) : FingerprintSensorRepository {
|
) : FingerprintSensorRepository {
|
||||||
@@ -73,12 +73,9 @@ class FingerprintSensorRepositoryImpl(
|
|||||||
.stateIn(activityScope, started = SharingStarted.Eagerly, initialValue = DEFAULT_PROPS)
|
.stateIn(activityScope, started = SharingStarted.Eagerly, initialValue = DEFAULT_PROPS)
|
||||||
|
|
||||||
override val fingerprintSensor: Flow<FingerprintSensor> =
|
override val fingerprintSensor: Flow<FingerprintSensor> =
|
||||||
fingerprintPropsInternal.transform {
|
fingerprintPropsInternal.transform { emit(it.toFingerprintSensor()) }
|
||||||
emit(it.toFingerprintSensor())
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "FingerprintSensorRepoImpl"
|
|
||||||
|
|
||||||
private val DEFAULT_PROPS =
|
private val DEFAULT_PROPS =
|
||||||
FingerprintSensorPropertiesInternal(
|
FingerprintSensorPropertiesInternal(
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package com.android.settings.biometrics.fingerprint2.data.repository
|
package com.android.settings.biometrics.fingerprint2.data.repository
|
||||||
|
|
||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
|
import android.view.MotionEvent
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,8 +25,6 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
* that talkback is correct.
|
* that talkback is correct.
|
||||||
*/
|
*/
|
||||||
interface SimulatedTouchEventsRepository {
|
interface SimulatedTouchEventsRepository {
|
||||||
/**
|
/** A flow simulating user touches. */
|
||||||
* A flow simulating user touches.
|
val touchExplorationDebug: Flow<MotionEvent>
|
||||||
*/
|
|
||||||
val touchExplorationDebug: Flow<Point>
|
|
||||||
}
|
}
|
||||||
|
@@ -14,10 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.data.repository
|
package com.android.settings.biometrics.fingerprint2.debug.data.repository
|
||||||
|
|
||||||
import android.graphics.Point
|
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.MotionEvent.ACTION_HOVER_MOVE
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.SimulatedTouchEventsRepository
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
@@ -36,7 +40,11 @@ import kotlinx.coroutines.flow.flowOf
|
|||||||
class UdfpsEnrollDebugRepositoryImpl :
|
class UdfpsEnrollDebugRepositoryImpl :
|
||||||
FingerprintEnrollInteractor, FingerprintSensorRepository, SimulatedTouchEventsRepository {
|
FingerprintEnrollInteractor, FingerprintSensorRepository, SimulatedTouchEventsRepository {
|
||||||
|
|
||||||
override suspend fun enroll(hardwareAuthToken: ByteArray?, enrollReason: EnrollReason) = flow {
|
override suspend fun enroll(
|
||||||
|
hardwareAuthToken: ByteArray?,
|
||||||
|
enrollReason: EnrollReason,
|
||||||
|
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||||
|
) = flow {
|
||||||
emit(FingerEnrollState.OverlayShown)
|
emit(FingerEnrollState.OverlayShown)
|
||||||
delay(200)
|
delay(200)
|
||||||
emit(FingerEnrollState.EnrollHelp(helpMsgId, "Hello world"))
|
emit(FingerEnrollState.EnrollHelp(helpMsgId, "Hello world"))
|
||||||
@@ -77,7 +85,7 @@ class UdfpsEnrollDebugRepositoryImpl :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Provides touch events to the UdfpsEnrollFragment */
|
/** Provides touch events to the UdfpsEnrollFragment */
|
||||||
override val touchExplorationDebug: Flow<Point> = flow {
|
override val touchExplorationDebug: Flow<MotionEvent> = flow {
|
||||||
delay(2000)
|
delay(2000)
|
||||||
emit(pointToLeftOfSensor(sensorRect))
|
emit(pointToLeftOfSensor(sensorRect))
|
||||||
delay(2000)
|
delay(2000)
|
||||||
@@ -90,17 +98,45 @@ class UdfpsEnrollDebugRepositoryImpl :
|
|||||||
|
|
||||||
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensorProps)
|
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensorProps)
|
||||||
|
|
||||||
private fun pointToLeftOfSensor(sensorLocation: Rect) =
|
private fun pointToLeftOfSensor(sensorLocation: Rect): MotionEvent =
|
||||||
Point(sensorLocation.right + 5, sensorLocation.centerY())
|
MotionEvent.obtain(
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
ACTION_HOVER_MOVE,
|
||||||
|
sensorLocation.right + 5.0f,
|
||||||
|
sensorLocation.centerY().toFloat(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
private fun pointToRightOfSensor(sensorLocation: Rect) =
|
private fun pointToRightOfSensor(sensorLocation: Rect): MotionEvent =
|
||||||
Point(sensorLocation.left - 5, sensorLocation.centerY())
|
MotionEvent.obtain(
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
ACTION_HOVER_MOVE,
|
||||||
|
sensorLocation.right - 5.0f,
|
||||||
|
sensorLocation.centerY().toFloat(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
private fun pointBelowSensor(sensorLocation: Rect) =
|
private fun pointBelowSensor(sensorLocation: Rect): MotionEvent =
|
||||||
Point(sensorLocation.centerX(), sensorLocation.bottom + 5)
|
MotionEvent.obtain(
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
ACTION_HOVER_MOVE,
|
||||||
|
sensorLocation.centerX().toFloat(),
|
||||||
|
sensorLocation.bottom + 5.0f,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
private fun pointAboveSensor(sensorLocation: Rect) =
|
private fun pointAboveSensor(sensorLocation: Rect): MotionEvent =
|
||||||
Point(sensorLocation.centerX(), sensorLocation.top - 5)
|
MotionEvent.obtain(
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
ACTION_HOVER_MOVE,
|
||||||
|
sensorLocation.centerX().toFloat(),
|
||||||
|
sensorLocation.top - 5.0f,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@@ -109,10 +145,10 @@ class UdfpsEnrollDebugRepositoryImpl :
|
|||||||
private val sensorRadius = 100
|
private val sensorRadius = 100
|
||||||
private val sensorRect =
|
private val sensorRect =
|
||||||
Rect(
|
Rect(
|
||||||
this.sensorLocationInternal.first - sensorRadius,
|
sensorLocationInternal.first - sensorRadius,
|
||||||
this.sensorLocationInternal.second - sensorRadius,
|
sensorLocationInternal.second - sensorRadius,
|
||||||
this.sensorLocationInternal.first + sensorRadius,
|
sensorLocationInternal.first + sensorRadius,
|
||||||
this.sensorLocationInternal.second + sensorRadius,
|
sensorLocationInternal.second + sensorRadius,
|
||||||
)
|
)
|
||||||
val sensorProps =
|
val sensorProps =
|
||||||
FingerprintSensor(
|
FingerprintSensor(
|
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fingerprint2.debug.domain.interactor
|
||||||
|
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.SimulatedTouchEventsRepository
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.TouchEventInteractor
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class DebugTouchEventInteractorImpl(
|
||||||
|
udfpsSimulatedTouchEventsRepository: SimulatedTouchEventsRepository
|
||||||
|
) : TouchEventInteractor {
|
||||||
|
override val touchEvent: Flow<MotionEvent> =
|
||||||
|
udfpsSimulatedTouchEventsRepository.touchExplorationDebug
|
||||||
|
}
|
@@ -17,7 +17,7 @@
|
|||||||
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
||||||
|
|
||||||
import android.view.accessibility.AccessibilityManager
|
import android.view.accessibility.AccessibilityManager
|
||||||
import androidx.lifecycle.LifecycleCoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
@@ -32,7 +32,7 @@ interface AccessibilityInteractor {
|
|||||||
|
|
||||||
class AccessibilityInteractorImpl(
|
class AccessibilityInteractorImpl(
|
||||||
accessibilityManager: AccessibilityManager,
|
accessibilityManager: AccessibilityManager,
|
||||||
activityScope: LifecycleCoroutineScope
|
applicationScope: CoroutineScope,
|
||||||
) : AccessibilityInteractor {
|
) : AccessibilityInteractor {
|
||||||
/** A flow that contains whether or not accessibility is enabled */
|
/** A flow that contains whether or not accessibility is enabled */
|
||||||
override val isAccessibilityEnabled: Flow<Boolean> =
|
override val isAccessibilityEnabled: Flow<Boolean> =
|
||||||
@@ -45,8 +45,8 @@ class AccessibilityInteractorImpl(
|
|||||||
awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) }
|
awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) }
|
||||||
}
|
}
|
||||||
.stateIn(
|
.stateIn(
|
||||||
activityScope, // This is going to tied to the activity scope
|
applicationScope, // This is going to tied to the activity scope
|
||||||
SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener
|
SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
}
|
}
|
@@ -28,9 +28,7 @@ interface DebuggingInteractor {
|
|||||||
val udfpsEnrollmentDebuggingEnabled: Flow<Boolean>
|
val udfpsEnrollmentDebuggingEnabled: Flow<Boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** This interactor essentially forwards the [DebuggingRepository] */
|
||||||
* This interactor essentially forwards the [DebuggingRepository]
|
|
||||||
*/
|
|
||||||
class DebuggingInteractorImpl(val debuggingRepository: DebuggingRepository) : DebuggingInteractor {
|
class DebuggingInteractorImpl(val debuggingRepository: DebuggingRepository) : DebuggingInteractor {
|
||||||
override val debuggingEnabled: Flow<Boolean> = flow {
|
override val debuggingEnabled: Flow<Boolean> = flow {
|
||||||
emit(debuggingRepository.isDebuggingEnabled())
|
emit(debuggingRepository.isDebuggingEnabled())
|
||||||
|
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.android.settingslib.display.DisplayDensityUtils
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -50,12 +52,11 @@ interface DisplayDensityInteractor {
|
|||||||
* Implementation of the [DisplayDensityInteractor]. This interactor is used to forward activity
|
* Implementation of the [DisplayDensityInteractor]. This interactor is used to forward activity
|
||||||
* information to the rest of the application.
|
* information to the rest of the application.
|
||||||
*/
|
*/
|
||||||
class DisplayDensityInteractorImpl(
|
class DisplayDensityInteractorImpl(context: Context, scope: CoroutineScope) :
|
||||||
currentFontScale: Float,
|
DisplayDensityInteractor {
|
||||||
currentDisplayDensity: Int,
|
|
||||||
defaultDisplayDensity: Int,
|
val displayDensityUtils = DisplayDensityUtils(context)
|
||||||
scope: CoroutineScope,
|
|
||||||
) : DisplayDensityInteractor {
|
|
||||||
override fun updateDisplayDensity(density: Int) {
|
override fun updateDisplayDensity(density: Int) {
|
||||||
_displayDensity.update { density }
|
_displayDensity.update { density }
|
||||||
}
|
}
|
||||||
@@ -64,13 +65,18 @@ class DisplayDensityInteractorImpl(
|
|||||||
_fontScale.update { fontScale }
|
_fontScale.update { fontScale }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _fontScale = MutableStateFlow(currentFontScale)
|
private val _fontScale = MutableStateFlow(context.resources.configuration.fontScale)
|
||||||
private val _displayDensity = MutableStateFlow(currentDisplayDensity)
|
private val _displayDensity =
|
||||||
|
MutableStateFlow(
|
||||||
|
displayDensityUtils.defaultDisplayDensityValues[
|
||||||
|
displayDensityUtils.currentIndexForDefaultDisplay]
|
||||||
|
)
|
||||||
|
|
||||||
override val fontScale: Flow<Float> = _fontScale.asStateFlow()
|
override val fontScale: Flow<Float> = _fontScale.asStateFlow()
|
||||||
|
|
||||||
override val displayDensity: Flow<Int> = _displayDensity.asStateFlow()
|
override val displayDensity: Flow<Int> = _displayDensity.asStateFlow()
|
||||||
|
|
||||||
override val defaultDisplayDensity: Flow<Int> =
|
override val defaultDisplayDensity: Flow<Int> =
|
||||||
flowOf(defaultDisplayDensity).shareIn(scope, SharingStarted.Eagerly, 1)
|
flowOf(displayDensityUtils.defaultDensityForDefaultDisplay)
|
||||||
|
.shareIn(scope, SharingStarted.Eagerly, 1)
|
||||||
}
|
}
|
||||||
|
@@ -33,7 +33,6 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
import kotlinx.coroutines.flow.transform
|
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
/** This repository is responsible for collecting all state related to the enroll API. */
|
/** This repository is responsible for collecting all state related to the enroll API. */
|
||||||
@@ -45,13 +44,13 @@ interface FingerprintEnrollInteractor {
|
|||||||
suspend fun enroll(
|
suspend fun enroll(
|
||||||
hardwareAuthToken: ByteArray?,
|
hardwareAuthToken: ByteArray?,
|
||||||
enrollReason: EnrollReason,
|
enrollReason: EnrollReason,
|
||||||
|
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||||
): Flow<FingerEnrollState>
|
): Flow<FingerEnrollState>
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintEnrollInteractorImpl(
|
class FingerprintEnrollInteractorImpl(
|
||||||
private val applicationContext: Context,
|
private val applicationContext: Context,
|
||||||
private val fingerprintEnrollOptions: FingerprintEnrollOptions,
|
private val fingerprintManager: FingerprintManager?,
|
||||||
private val fingerprintManager: FingerprintManager,
|
|
||||||
private val fingerprintFlow: FingerprintFlow,
|
private val fingerprintFlow: FingerprintFlow,
|
||||||
) : FingerprintEnrollInteractor {
|
) : FingerprintEnrollInteractor {
|
||||||
private val enrollRequestOutstanding = MutableStateFlow(false)
|
private val enrollRequestOutstanding = MutableStateFlow(false)
|
||||||
@@ -59,6 +58,7 @@ class FingerprintEnrollInteractorImpl(
|
|||||||
override suspend fun enroll(
|
override suspend fun enroll(
|
||||||
hardwareAuthToken: ByteArray?,
|
hardwareAuthToken: ByteArray?,
|
||||||
enrollReason: EnrollReason,
|
enrollReason: EnrollReason,
|
||||||
|
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||||
): Flow<FingerEnrollState> = callbackFlow {
|
): Flow<FingerEnrollState> = callbackFlow {
|
||||||
// TODO (b/308456120) Improve this logic
|
// TODO (b/308456120) Improve this logic
|
||||||
if (enrollRequestOutstanding.value) {
|
if (enrollRequestOutstanding.value) {
|
||||||
@@ -135,7 +135,7 @@ class FingerprintEnrollInteractorImpl(
|
|||||||
|
|
||||||
val cancellationSignal = CancellationSignal()
|
val cancellationSignal = CancellationSignal()
|
||||||
|
|
||||||
fingerprintManager.enroll(
|
fingerprintManager?.enroll(
|
||||||
hardwareAuthToken,
|
hardwareAuthToken,
|
||||||
cancellationSignal,
|
cancellationSignal,
|
||||||
applicationContext.userId,
|
applicationContext.userId,
|
||||||
|
@@ -18,6 +18,7 @@ package com.android.settings.biometrics.fingerprint2.domain.interactor
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
import android.hardware.fingerprint.FingerprintManager
|
import android.hardware.fingerprint.FingerprintManager
|
||||||
import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback
|
import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback
|
||||||
import android.hardware.fingerprint.FingerprintManager.RemovalCallback
|
import android.hardware.fingerprint.FingerprintManager.RemovalCallback
|
||||||
@@ -45,7 +46,7 @@ private const val TAG = "FingerprintManagerInteractor"
|
|||||||
class FingerprintManagerInteractorImpl(
|
class FingerprintManagerInteractorImpl(
|
||||||
applicationContext: Context,
|
applicationContext: Context,
|
||||||
private val backgroundDispatcher: CoroutineDispatcher,
|
private val backgroundDispatcher: CoroutineDispatcher,
|
||||||
private val fingerprintManager: FingerprintManager,
|
private val fingerprintManager: FingerprintManager?,
|
||||||
fingerprintSensorRepository: FingerprintSensorRepository,
|
fingerprintSensorRepository: FingerprintSensorRepository,
|
||||||
private val gatekeeperPasswordProvider: GatekeeperPasswordProvider,
|
private val gatekeeperPasswordProvider: GatekeeperPasswordProvider,
|
||||||
private val fingerprintEnrollStateRepository: FingerprintEnrollInteractor,
|
private val fingerprintEnrollStateRepository: FingerprintEnrollInteractor,
|
||||||
@@ -57,7 +58,6 @@ class FingerprintManagerInteractorImpl(
|
|||||||
)
|
)
|
||||||
private val applicationContext = applicationContext.applicationContext
|
private val applicationContext = applicationContext.applicationContext
|
||||||
|
|
||||||
|
|
||||||
override suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray> =
|
override suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray> =
|
||||||
suspendCoroutine {
|
suspendCoroutine {
|
||||||
val callback = GenerateChallengeCallback { _, userId, challenge ->
|
val callback = GenerateChallengeCallback { _, userId, challenge ->
|
||||||
@@ -70,21 +70,19 @@ class FingerprintManagerInteractorImpl(
|
|||||||
val p = Pair(challenge, challengeToken)
|
val p = Pair(challenge, challengeToken)
|
||||||
it.resume(p)
|
it.resume(p)
|
||||||
}
|
}
|
||||||
fingerprintManager.generateChallenge(applicationContext.userId, callback)
|
fingerprintManager?.generateChallenge(applicationContext.userId, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val enrolledFingerprints: Flow<List<FingerprintData>> = flow {
|
override val enrolledFingerprints: Flow<List<FingerprintData>?> = flow {
|
||||||
emit(
|
emit(
|
||||||
fingerprintManager
|
fingerprintManager?.getEnrolledFingerprints(applicationContext.userId)
|
||||||
.getEnrolledFingerprints(applicationContext.userId)
|
?.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }?.toList()
|
||||||
.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }
|
|
||||||
.toList()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val canEnrollFingerprints: Flow<Boolean> = flow {
|
override val canEnrollFingerprints: Flow<Boolean> = flow {
|
||||||
emit(
|
emit(
|
||||||
fingerprintManager.getEnrolledFingerprints(applicationContext.userId).size < maxFingerprints
|
fingerprintManager?.getEnrolledFingerprints(applicationContext.userId)?.size ?: maxFingerprints < maxFingerprints
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,8 +90,16 @@ class FingerprintManagerInteractorImpl(
|
|||||||
|
|
||||||
override val maxEnrollableFingerprints = flow { emit(maxFingerprints) }
|
override val maxEnrollableFingerprints = flow { emit(maxFingerprints) }
|
||||||
|
|
||||||
override suspend fun enroll(hardwareAuthToken: ByteArray?, enrollReason: EnrollReason): Flow<FingerEnrollState> =
|
override suspend fun enroll(
|
||||||
fingerprintEnrollStateRepository.enroll(hardwareAuthToken, enrollReason)
|
hardwareAuthToken: ByteArray?,
|
||||||
|
enrollReason: EnrollReason,
|
||||||
|
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||||
|
): Flow<FingerEnrollState> =
|
||||||
|
fingerprintEnrollStateRepository.enroll(
|
||||||
|
hardwareAuthToken,
|
||||||
|
enrollReason,
|
||||||
|
fingerprintEnrollOptions,
|
||||||
|
)
|
||||||
|
|
||||||
override suspend fun removeFingerprint(fp: FingerprintData): Boolean = suspendCoroutine {
|
override suspend fun removeFingerprint(fp: FingerprintData): Boolean = suspendCoroutine {
|
||||||
val callback =
|
val callback =
|
||||||
@@ -113,7 +119,7 @@ class FingerprintManagerInteractorImpl(
|
|||||||
it.resume(true)
|
it.resume(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fingerprintManager.remove(
|
fingerprintManager?.remove(
|
||||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
||||||
applicationContext.userId,
|
applicationContext.userId,
|
||||||
callback,
|
callback,
|
||||||
@@ -122,12 +128,12 @@ class FingerprintManagerInteractorImpl(
|
|||||||
|
|
||||||
override suspend fun renameFingerprint(fp: FingerprintData, newName: String) {
|
override suspend fun renameFingerprint(fp: FingerprintData, newName: String) {
|
||||||
withContext(backgroundDispatcher) {
|
withContext(backgroundDispatcher) {
|
||||||
fingerprintManager.rename(fp.fingerId, applicationContext.userId, newName)
|
fingerprintManager?.rename(fp.fingerId, applicationContext.userId, newName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun hasSideFps(): Boolean = suspendCancellableCoroutine {
|
override suspend fun hasSideFps(): Boolean? = suspendCancellableCoroutine {
|
||||||
it.resume(fingerprintManager.isPowerbuttonFps)
|
it.resume(fingerprintManager?.isPowerbuttonFps)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun authenticate(): FingerprintAuthAttemptModel =
|
override suspend fun authenticate(): FingerprintAuthAttemptModel =
|
||||||
@@ -156,7 +162,7 @@ class FingerprintManagerInteractorImpl(
|
|||||||
|
|
||||||
val cancellationSignal = CancellationSignal()
|
val cancellationSignal = CancellationSignal()
|
||||||
c.invokeOnCancellation { cancellationSignal.cancel() }
|
c.invokeOnCancellation { cancellationSignal.cancel() }
|
||||||
fingerprintManager.authenticate(
|
fingerprintManager?.authenticate(
|
||||||
null,
|
null,
|
||||||
cancellationSignal,
|
cancellationSignal,
|
||||||
authenticationCallback,
|
authenticationCallback,
|
||||||
@@ -164,5 +170,4 @@ class FingerprintManagerInteractorImpl(
|
|||||||
applicationContext.userId,
|
applicationContext.userId,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fingerprint2.domain.interactor
|
||||||
|
|
||||||
|
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
|
||||||
|
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interactor that propagates the type of [FingerprintSensor] this device supports.
|
||||||
|
*/
|
||||||
|
interface FingerprintSensorInteractor {
|
||||||
|
/** Get the [FingerprintSensor] */
|
||||||
|
val fingerprintSensor: Flow<FingerprintSensor>
|
||||||
|
}
|
||||||
|
|
||||||
|
class FingerprintSensorInteractorImpl(repo: FingerprintSensorRepository) :
|
||||||
|
FingerprintSensorInteractor {
|
||||||
|
override val fingerprintSensor: Flow<FingerprintSensor> = repo.fingerprintSensor
|
||||||
|
}
|
@@ -29,15 +29,12 @@ interface FoldStateInteractor {
|
|||||||
val isFolded: Flow<Boolean>
|
val isFolded: Flow<Boolean>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates a configuration change has occurred, and the repo
|
* Indicates a configuration change has occurred, and the repo should update the [isFolded] flow.
|
||||||
* should update the [isFolded] flow.
|
|
||||||
*/
|
*/
|
||||||
fun onConfigurationChange(newConfig: Configuration)
|
fun onConfigurationChange(newConfig: Configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Interactor which handles fold state */
|
||||||
* Interactor which handles fold state
|
|
||||||
*/
|
|
||||||
class FoldStateInteractorImpl(context: Context) : FoldStateInteractor {
|
class FoldStateInteractorImpl(context: Context) : FoldStateInteractor {
|
||||||
private val screenSizeFoldProvider = ScreenSizeFoldProvider(context)
|
private val screenSizeFoldProvider = ScreenSizeFoldProvider(context)
|
||||||
override val isFolded: Flow<Boolean> = callbackFlow {
|
override val isFolded: Flow<Boolean> = callbackFlow {
|
||||||
@@ -54,5 +51,4 @@ class FoldStateInteractorImpl(context: Context) : FoldStateInteractor {
|
|||||||
override fun onConfigurationChange(newConfig: Configuration) {
|
override fun onConfigurationChange(newConfig: Configuration) {
|
||||||
screenSizeFoldProvider.onConfigurationChange(newConfig)
|
screenSizeFoldProvider.onConfigurationChange(newConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -60,10 +60,7 @@ class OrientationInteractorImpl(private val context: Context) : OrientationInter
|
|||||||
awaitClose { orientationEventListener.disable() }
|
awaitClose { orientationEventListener.disable() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override val rotation: Flow<Int> =
|
override val rotation: Flow<Int> = orientation.transform { emit(context.display.rotation) }
|
||||||
orientation.transform {
|
|
||||||
emit(context.display!!.rotation)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val rotationFromDefault: Flow<Int> = rotation.map { getRotationFromDefault(it) }
|
override val rotationFromDefault: Flow<Int> = rotation.map { getRotationFromDefault(it) }
|
||||||
|
|
||||||
|
@@ -38,19 +38,14 @@ class PressToAuthInteractorImpl(
|
|||||||
private val backgroundDispatcher: CoroutineDispatcher,
|
private val backgroundDispatcher: CoroutineDispatcher,
|
||||||
) : PressToAuthInteractor {
|
) : PressToAuthInteractor {
|
||||||
|
|
||||||
/**
|
/** A flow that contains the status of the press to auth feature. */
|
||||||
* A flow that contains the status of the press to auth feature.
|
|
||||||
*/
|
|
||||||
override val isEnabled: Flow<Boolean> =
|
override val isEnabled: Flow<Boolean> =
|
||||||
|
|
||||||
callbackFlow {
|
callbackFlow {
|
||||||
val callback =
|
val callback =
|
||||||
object : ContentObserver(null) {
|
object : ContentObserver(null) {
|
||||||
override fun onChange(selfChange: Boolean) {
|
override fun onChange(selfChange: Boolean) {
|
||||||
Log.d(TAG, "SFPS_PERFORMANT_AUTH_ENABLED#onchange")
|
Log.d(TAG, "SFPS_PERFORMANT_AUTH_ENABLED#onchange")
|
||||||
trySend(
|
trySend(getPressToAuth())
|
||||||
getPressToAuth(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,18 +53,14 @@ class PressToAuthInteractorImpl(
|
|||||||
Settings.Secure.getUriFor(Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED),
|
Settings.Secure.getUriFor(Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED),
|
||||||
false,
|
false,
|
||||||
callback,
|
callback,
|
||||||
context.userId
|
context.userId,
|
||||||
)
|
)
|
||||||
trySend(getPressToAuth())
|
trySend(getPressToAuth())
|
||||||
awaitClose {
|
awaitClose { context.contentResolver.unregisterContentObserver(callback) }
|
||||||
context.contentResolver.unregisterContentObserver(callback)
|
|
||||||
}
|
}
|
||||||
}.flowOn(backgroundDispatcher)
|
.flowOn(backgroundDispatcher)
|
||||||
|
|
||||||
|
/** Returns true if press to auth is enabled */
|
||||||
/**
|
|
||||||
* Returns true if press to auth is enabled
|
|
||||||
*/
|
|
||||||
private fun getPressToAuth(): Boolean {
|
private fun getPressToAuth(): Boolean {
|
||||||
var toReturn: Int =
|
var toReturn: Int =
|
||||||
Settings.Secure.getIntForUser(
|
Settings.Secure.getIntForUser(
|
||||||
@@ -95,7 +86,6 @@ class PressToAuthInteractorImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return toReturn == 1
|
return toReturn == 1
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.fingerprint2.domain.interactor
|
||||||
|
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
interface TouchEventInteractor {
|
||||||
|
|
||||||
|
/** A flow simulating user touches. */
|
||||||
|
val touchEvent: Flow<MotionEvent>
|
||||||
|
}
|
||||||
|
|
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.util.Log
|
import android.util.TypedValue
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
@@ -43,13 +44,18 @@ interface UdfpsEnrollInteractor {
|
|||||||
|
|
||||||
/** Keeps track of which guided enrollment point we should be using */
|
/** Keeps track of which guided enrollment point we should be using */
|
||||||
class UdfpsEnrollInteractorImpl(
|
class UdfpsEnrollInteractorImpl(
|
||||||
pixelsPerMillimeter: Float,
|
applicationContext: Context,
|
||||||
accessibilityInteractor: AccessibilityInteractor,
|
accessibilityInteractor: AccessibilityInteractor,
|
||||||
) : UdfpsEnrollInteractor {
|
) : UdfpsEnrollInteractor {
|
||||||
|
|
||||||
private var isGuidedEnrollment = MutableStateFlow(false)
|
private var isGuidedEnrollment = MutableStateFlow(false)
|
||||||
// Number of pixels per mm
|
// Number of pixels per mm
|
||||||
val px = pixelsPerMillimeter
|
val px =
|
||||||
|
TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_MM,
|
||||||
|
1f,
|
||||||
|
applicationContext.resources.displayMetrics,
|
||||||
|
)
|
||||||
private val guidedEnrollmentPoints: MutableList<PointF> =
|
private val guidedEnrollmentPoints: MutableList<PointF> =
|
||||||
mutableListOf(
|
mutableListOf(
|
||||||
PointF(2.00f * px, 0.00f * px),
|
PointF(2.00f * px, 0.00f * px),
|
||||||
@@ -70,7 +76,6 @@ class UdfpsEnrollInteractorImpl(
|
|||||||
|
|
||||||
override fun onEnrollmentStep(stepsRemaining: Int, totalStep: Int) {
|
override fun onEnrollmentStep(stepsRemaining: Int, totalStep: Int) {
|
||||||
val index = (totalStep - stepsRemaining) % guidedEnrollmentPoints.size
|
val index = (totalStep - stepsRemaining) % guidedEnrollmentPoints.size
|
||||||
Log.e("JRM", "guided enroll step $index")
|
|
||||||
_guidedEnrollment.update { guidedEnrollmentPoints[index] }
|
_guidedEnrollment.update { guidedEnrollmentPoints[index] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -36,6 +36,7 @@ sealed class FingerprintVibrationEffects {
|
|||||||
/** This vibration typically occurs when a help message is shown during UDFPS enrollment */
|
/** This vibration typically occurs when a help message is shown during UDFPS enrollment */
|
||||||
data object UdfpsHelp : FingerprintVibrationEffects()
|
data object UdfpsHelp : FingerprintVibrationEffects()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Interface for sending haptic feedback */
|
/** Interface for sending haptic feedback */
|
||||||
interface VibrationInteractor {
|
interface VibrationInteractor {
|
||||||
/** This will send a haptic vibration */
|
/** This will send a haptic vibration */
|
||||||
@@ -43,8 +44,9 @@ interface VibrationInteractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Implementation of the VibrationInteractor interface */
|
/** Implementation of the VibrationInteractor interface */
|
||||||
class VibrationInteractorImpl(val vibrator: Vibrator, val applicationContext: Context) :
|
class VibrationInteractorImpl(val applicationContext: Context) : VibrationInteractor {
|
||||||
VibrationInteractor {
|
val vibrator = applicationContext.getSystemService(Vibrator::class.java)!!
|
||||||
|
|
||||||
override fun vibrate(effect: FingerprintVibrationEffects, caller: String) {
|
override fun vibrate(effect: FingerprintVibrationEffects, caller: String) {
|
||||||
val callerString = "$caller::$effect"
|
val callerString = "$caller::$effect"
|
||||||
val res =
|
val res =
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.lib.domain.interactor
|
package com.android.settings.biometrics.fingerprint2.lib.domain.interactor
|
||||||
|
|
||||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||||
@@ -32,7 +32,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
*/
|
*/
|
||||||
interface FingerprintManagerInteractor {
|
interface FingerprintManagerInteractor {
|
||||||
/** Returns the list of current fingerprints. */
|
/** Returns the list of current fingerprints. */
|
||||||
val enrolledFingerprints: Flow<List<FingerprintData>>
|
val enrolledFingerprints: Flow<List<FingerprintData>?>
|
||||||
|
|
||||||
/** Returns the max enrollable fingerprints, note during SUW this might be 1 */
|
/** Returns the max enrollable fingerprints, note during SUW this might be 1 */
|
||||||
val maxEnrollableFingerprints: Flow<Int>
|
val maxEnrollableFingerprints: Flow<Int>
|
||||||
@@ -62,6 +62,7 @@ interface FingerprintManagerInteractor {
|
|||||||
suspend fun enroll(
|
suspend fun enroll(
|
||||||
hardwareAuthToken: ByteArray?,
|
hardwareAuthToken: ByteArray?,
|
||||||
enrollReason: EnrollReason,
|
enrollReason: EnrollReason,
|
||||||
|
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||||
): Flow<FingerEnrollState>
|
): Flow<FingerEnrollState>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,5 +75,5 @@ interface FingerprintManagerInteractor {
|
|||||||
suspend fun renameFingerprint(fp: FingerprintData, newName: String)
|
suspend fun renameFingerprint(fp: FingerprintData, newName: String)
|
||||||
|
|
||||||
/** Indicates if the device has side fingerprint */
|
/** Indicates if the device has side fingerprint */
|
||||||
suspend fun hasSideFps(): Boolean
|
suspend fun hasSideFps(): Boolean?
|
||||||
}
|
}
|
||||||
|
@@ -24,5 +24,5 @@ enum class EnrollReason {
|
|||||||
*/
|
*/
|
||||||
FindSensor,
|
FindSensor,
|
||||||
/** The enroll happens on enrolling screen. */
|
/** The enroll happens on enrolling screen. */
|
||||||
EnrollEnrolling
|
EnrollEnrolling,
|
||||||
}
|
}
|
||||||
|
@@ -22,16 +22,12 @@ import android.content.res.Configuration
|
|||||||
import android.hardware.fingerprint.FingerprintEnrollOptions
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
import android.hardware.fingerprint.FingerprintManager
|
import android.hardware.fingerprint.FingerprintManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Vibrator
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.accessibility.AccessibilityManager
|
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.android.internal.widget.LockPatternUtils
|
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.SetupWizardUtils
|
import com.android.settings.SetupWizardUtils
|
||||||
import com.android.settings.Utils.SETTINGS_PACKAGE_NAME
|
import com.android.settings.Utils.SETTINGS_PACKAGE_NAME
|
||||||
@@ -40,27 +36,9 @@ import com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST
|
|||||||
import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
|
import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
|
||||||
import com.android.settings.biometrics.BiometricUtils
|
import com.android.settings.biometrics.BiometricUtils
|
||||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||||
import com.android.settings.biometrics.fingerprint2.data.repository.DebuggingRepositoryImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepositoryImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.data.repository.UdfpsEnrollDebugRepositoryImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DebuggingInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractor
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractor
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.Settings
|
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
|
import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollEnrollingV2Fragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollEnrollingV2Fragment
|
||||||
@@ -68,18 +46,12 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.Finge
|
|||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.education.RfpsEnrollFindSensorFragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.education.RfpsEnrollFindSensorFragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.education.SfpsEnrollFindSensorFragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.education.SfpsEnrollFindSensorFragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.education.UdfpsEnrollFindSensorFragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.education.UdfpsEnrollFindSensorFragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.fragment.RFPSEnrollFragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.fragment.RFPSEnrollFragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.fragment.UdfpsEnrollFragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.fragment.UdfpsEnrollFragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsLastStepViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsLastStepViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel.UdfpsViewModel
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintAction
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintAction
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollEnrollingViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollEnrollingViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||||
@@ -91,7 +63,6 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
|
|||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Transition
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Transition
|
||||||
import com.android.settings.flags.Flags
|
import com.android.settings.flags.Flags
|
||||||
@@ -113,23 +84,38 @@ private const val TAG = "FingerprintEnrollmentV2Activity"
|
|||||||
* children fragments.
|
* children fragments.
|
||||||
*/
|
*/
|
||||||
class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||||
private lateinit var fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel
|
private val navigationViewModel: FingerprintNavigationViewModel by viewModels {
|
||||||
private lateinit var navigationViewModel: FingerprintNavigationViewModel
|
FingerprintNavigationViewModel.Factory
|
||||||
private lateinit var gatekeeperViewModel: FingerprintGatekeeperViewModel
|
}
|
||||||
private lateinit var fingerprintEnrollViewModel: FingerprintEnrollViewModel
|
private val fingerprintFlowViewModel: FingerprintFlowViewModel by viewModels {
|
||||||
private lateinit var vibrationInteractor: VibrationInteractor
|
FingerprintFlowViewModel.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
private val gatekeeperViewModel: FingerprintGatekeeperViewModel by viewModels {
|
||||||
|
FingerprintGatekeeperViewModel.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View models below this line are not used by this class but must be initialized
|
||||||
|
* in the activity view model store to be used by other view models.
|
||||||
|
*/
|
||||||
|
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel by viewModels {
|
||||||
|
FingerprintEnrollViewModel.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
private val fingerprintEnrollEnrollingViewModel:
|
||||||
|
FingerprintEnrollEnrollingViewModel by viewModels {
|
||||||
|
FingerprintEnrollEnrollingViewModel.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
private val udfpsLastStepViewModel: UdfpsLastStepViewModel by viewModels {
|
||||||
|
UdfpsLastStepViewModel.Factory
|
||||||
|
}
|
||||||
|
|
||||||
|
private val backgroundViewModel: BackgroundViewModel by viewModels { BackgroundViewModel.Factory }
|
||||||
|
|
||||||
private lateinit var foldStateInteractor: FoldStateInteractor
|
private lateinit var foldStateInteractor: FoldStateInteractor
|
||||||
private lateinit var orientationInteractor: OrientationInteractor
|
|
||||||
private lateinit var displayDensityInteractor: DisplayDensityInteractor
|
private lateinit var displayDensityInteractor: DisplayDensityInteractor
|
||||||
private lateinit var udfpsEnrollInteractor: UdfpsEnrollInteractor
|
|
||||||
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
|
|
||||||
private lateinit var backgroundViewModel: BackgroundViewModel
|
|
||||||
private lateinit var fingerprintFlowViewModel: FingerprintFlowViewModel
|
|
||||||
private lateinit var fingerprintEnrollConfirmationViewModel:
|
|
||||||
FingerprintEnrollConfirmationViewModel
|
|
||||||
private lateinit var udfpsLastStepViewModel: UdfpsLastStepViewModel
|
|
||||||
private lateinit var udfpsViewModel: UdfpsViewModel
|
|
||||||
private lateinit var enrollStageInteractor: EnrollStageInteractor
|
|
||||||
private val coroutineDispatcher = Dispatchers.Default
|
private val coroutineDispatcher = Dispatchers.Default
|
||||||
|
|
||||||
/** Result listener for ChooseLock activity flow. */
|
/** Result listener for ChooseLock activity flow. */
|
||||||
@@ -172,7 +158,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
|||||||
|
|
||||||
private fun onConfirmDevice(resultCode: Int, data: Intent?) {
|
private fun onConfirmDevice(resultCode: Int, data: Intent?) {
|
||||||
val wasSuccessful = resultCode == RESULT_FINISHED || resultCode == Activity.RESULT_OK
|
val wasSuccessful = resultCode == RESULT_FINISHED || resultCode == Activity.RESULT_OK
|
||||||
val gateKeeperPasswordHandle = data?.getExtra(EXTRA_KEY_GK_PW_HANDLE) as Long?
|
val gateKeeperPasswordHandle = data?.getExtra(EXTRA_KEY_GK_PW_HANDLE) as Long
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val confirmDeviceResult =
|
val confirmDeviceResult =
|
||||||
@@ -204,6 +190,15 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that these view models are actually created and in this order
|
||||||
|
navigationViewModel
|
||||||
|
fingerprintFlowViewModel
|
||||||
|
gatekeeperViewModel
|
||||||
|
fingerprintEnrollViewModel
|
||||||
|
backgroundViewModel
|
||||||
|
fingerprintEnrollEnrollingViewModel
|
||||||
|
udfpsLastStepViewModel
|
||||||
|
|
||||||
setTheme(SetupWizardUtils.getTheme(applicationContext, intent))
|
setTheme(SetupWizardUtils.getTheme(applicationContext, intent))
|
||||||
ThemeHelper.trySetDynamicColor(applicationContext)
|
ThemeHelper.trySetDynamicColor(applicationContext)
|
||||||
|
|
||||||
@@ -219,31 +214,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
|||||||
Default
|
Default
|
||||||
}
|
}
|
||||||
|
|
||||||
backgroundViewModel =
|
fingerprintFlowViewModel.updateFlowType(enrollType)
|
||||||
ViewModelProvider(this, BackgroundViewModel.BackgroundViewModelFactory())[
|
|
||||||
BackgroundViewModel::class.java]
|
|
||||||
|
|
||||||
fingerprintFlowViewModel =
|
|
||||||
ViewModelProvider(this, FingerprintFlowViewModel.FingerprintFlowViewModelFactory(enrollType))[
|
|
||||||
FingerprintFlowViewModel::class.java]
|
|
||||||
val displayDensityUtils = DisplayDensityUtils(context)
|
|
||||||
val currIndex = displayDensityUtils.currentIndexForDefaultDisplay
|
|
||||||
val defaultDisplayDensity = displayDensityUtils.defaultDensityForDefaultDisplay
|
|
||||||
displayDensityInteractor =
|
|
||||||
DisplayDensityInteractorImpl(
|
|
||||||
resources.configuration.fontScale,
|
|
||||||
displayDensityUtils.defaultDisplayDensityValues[currIndex],
|
|
||||||
defaultDisplayDensity,
|
|
||||||
lifecycleScope,
|
|
||||||
)
|
|
||||||
|
|
||||||
val debuggingRepo = DebuggingRepositoryImpl()
|
|
||||||
val debuggingInteractor = DebuggingInteractorImpl(debuggingRepo)
|
|
||||||
val udfpsEnrollDebugRepositoryImpl = UdfpsEnrollDebugRepositoryImpl()
|
|
||||||
|
|
||||||
val fingerprintSensorRepo =
|
|
||||||
if (debuggingRepo.isUdfpsEnrollmentDebuggingEnabled()) udfpsEnrollDebugRepositoryImpl
|
|
||||||
else FingerprintSensorRepositoryImpl(fingerprintManager, backgroundDispatcher, lifecycleScope)
|
|
||||||
|
|
||||||
if (intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1) === -1) {
|
if (intent.getIntExtra(BiometricUtils.EXTRA_ENROLL_REASON, -1) === -1) {
|
||||||
val isSuw: Boolean = WizardManagerHelper.isAnySetupWizard(intent)
|
val isSuw: Boolean = WizardManagerHelper.isAnySetupWizard(intent)
|
||||||
@@ -254,170 +225,18 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fingerprintEnrollStateRepository =
|
|
||||||
if (debuggingRepo.isUdfpsEnrollmentDebuggingEnabled()) udfpsEnrollDebugRepositoryImpl
|
|
||||||
else
|
|
||||||
FingerprintEnrollInteractorImpl(
|
|
||||||
context.applicationContext,
|
|
||||||
intent.toFingerprintEnrollOptions(),
|
|
||||||
fingerprintManager,
|
|
||||||
Settings,
|
|
||||||
)
|
|
||||||
val accessibilityInteractor =
|
|
||||||
AccessibilityInteractorImpl(
|
|
||||||
getSystemService(AccessibilityManager::class.java)!!,
|
|
||||||
lifecycleScope,
|
|
||||||
)
|
|
||||||
|
|
||||||
val pixelsPerMillimeter =
|
|
||||||
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1f, context.resources.displayMetrics)
|
|
||||||
udfpsEnrollInteractor = UdfpsEnrollInteractorImpl(pixelsPerMillimeter, accessibilityInteractor)
|
|
||||||
|
|
||||||
val fingerprintManagerInteractor =
|
|
||||||
FingerprintManagerInteractorImpl(
|
|
||||||
context,
|
|
||||||
backgroundDispatcher,
|
|
||||||
fingerprintManager,
|
|
||||||
fingerprintSensorRepo,
|
|
||||||
GatekeeperPasswordProvider(LockPatternUtils(context)),
|
|
||||||
fingerprintEnrollStateRepository,
|
|
||||||
)
|
|
||||||
|
|
||||||
var challenge = intent.getExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE) as Long?
|
var challenge = intent.getExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE) as Long?
|
||||||
val token = intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
|
val token = intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
|
||||||
val gatekeeperInfo = FingerprintGatekeeperViewModel.toGateKeeperInfo(challenge, token)
|
val gatekeeperInfo = FingerprintGatekeeperViewModel.toGateKeeperInfo(challenge, token)
|
||||||
|
|
||||||
val hasConfirmedDeviceCredential = gatekeeperInfo is GatekeeperInfo.GatekeeperPasswordInfo
|
val hasConfirmedDeviceCredential = gatekeeperInfo is GatekeeperInfo.GatekeeperPasswordInfo
|
||||||
|
|
||||||
navigationViewModel =
|
navigationViewModel.updateFingerprintFlow(enrollType)
|
||||||
ViewModelProvider(
|
navigationViewModel.hasConfirmedDeviceCredential(hasConfirmedDeviceCredential)
|
||||||
this,
|
|
||||||
FingerprintNavigationViewModel.FingerprintNavigationViewModelFactory(
|
|
||||||
Init,
|
|
||||||
hasConfirmedDeviceCredential,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
),
|
|
||||||
)[FingerprintNavigationViewModel::class.java]
|
|
||||||
// Initialize FingerprintEnrollIntroViewModel
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
FingerprintEnrollIntroViewModel.FingerprintEnrollIntoViewModelFactory(
|
|
||||||
navigationViewModel,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
),
|
|
||||||
)[FingerprintEnrollIntroViewModel::class.java]
|
|
||||||
|
|
||||||
gatekeeperViewModel =
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
FingerprintGatekeeperViewModel.FingerprintGatekeeperViewModelFactory(
|
|
||||||
gatekeeperInfo,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
),
|
|
||||||
)[FingerprintGatekeeperViewModel::class.java]
|
|
||||||
|
|
||||||
// Initialize FoldStateViewModel
|
|
||||||
foldStateInteractor = FoldStateInteractorImpl(context)
|
|
||||||
foldStateInteractor.onConfigurationChange(resources.configuration)
|
|
||||||
|
|
||||||
orientationInteractor = OrientationInteractorImpl(context)
|
|
||||||
vibrationInteractor =
|
|
||||||
VibrationInteractorImpl(context.getSystemService(Vibrator::class.java)!!, context)
|
|
||||||
|
|
||||||
// Initialize FingerprintViewModel
|
|
||||||
fingerprintEnrollViewModel =
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
FingerprintEnrollViewModel.FingerprintEnrollViewModelFactory(
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
gatekeeperViewModel,
|
|
||||||
navigationViewModel,
|
|
||||||
),
|
|
||||||
)[FingerprintEnrollViewModel::class.java]
|
|
||||||
|
|
||||||
// Initialize scroll view model
|
|
||||||
fingerprintScrollViewModel =
|
|
||||||
ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
|
|
||||||
FingerprintScrollViewModel::class.java]
|
|
||||||
|
|
||||||
// Initialize FingerprintEnrollEnrollingViewModel
|
|
||||||
fingerprintEnrollEnrollingViewModel =
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
FingerprintEnrollEnrollingViewModel.FingerprintEnrollEnrollingViewModelFactory(
|
|
||||||
fingerprintEnrollViewModel,
|
|
||||||
backgroundViewModel,
|
|
||||||
),
|
|
||||||
)[FingerprintEnrollEnrollingViewModel::class.java]
|
|
||||||
|
|
||||||
// Initialize FingerprintEnrollFindSensorViewModel
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
FingerprintEnrollFindSensorViewModel.FingerprintEnrollFindSensorViewModelFactory(
|
|
||||||
navigationViewModel,
|
|
||||||
fingerprintEnrollViewModel,
|
|
||||||
gatekeeperViewModel,
|
|
||||||
backgroundViewModel,
|
|
||||||
accessibilityInteractor,
|
|
||||||
foldStateInteractor,
|
|
||||||
orientationInteractor,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
),
|
|
||||||
)[FingerprintEnrollFindSensorViewModel::class.java]
|
|
||||||
|
|
||||||
// Initialize RFPS View Model
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
RFPSViewModel.RFPSViewModelFactory(
|
|
||||||
fingerprintEnrollEnrollingViewModel,
|
|
||||||
navigationViewModel,
|
|
||||||
orientationInteractor,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
),
|
|
||||||
)[RFPSViewModel::class.java]
|
|
||||||
|
|
||||||
enrollStageInteractor = EnrollStageInteractorImpl()
|
|
||||||
|
|
||||||
udfpsLastStepViewModel =
|
|
||||||
UdfpsLastStepViewModel(fingerprintEnrollEnrollingViewModel, vibrationInteractor)
|
|
||||||
|
|
||||||
udfpsViewModel =
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
UdfpsViewModel.UdfpsEnrollmentFactory(
|
|
||||||
vibrationInteractor,
|
|
||||||
displayDensityInteractor,
|
|
||||||
navigationViewModel,
|
|
||||||
debuggingInteractor,
|
|
||||||
fingerprintEnrollEnrollingViewModel,
|
|
||||||
udfpsEnrollDebugRepositoryImpl,
|
|
||||||
enrollStageInteractor,
|
|
||||||
orientationInteractor,
|
|
||||||
backgroundViewModel,
|
|
||||||
fingerprintSensorRepo,
|
|
||||||
udfpsEnrollInteractor,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
udfpsLastStepViewModel,
|
|
||||||
accessibilityInteractor,
|
|
||||||
),
|
|
||||||
)[UdfpsViewModel::class.java]
|
|
||||||
|
|
||||||
fingerprintEnrollConfirmationViewModel =
|
|
||||||
ViewModelProvider(
|
|
||||||
this,
|
|
||||||
FingerprintEnrollConfirmationViewModel.FingerprintEnrollConfirmationViewModelFactory(
|
|
||||||
navigationViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
),
|
|
||||||
)[FingerprintEnrollConfirmationViewModel::class.java]
|
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
navigationViewModel.currentStep.collect { step ->
|
navigationViewModel.currentStep.collect { step ->
|
||||||
if (step is Init) {
|
if (step is Init) {
|
||||||
Log.d(TAG, "FingerprintNav.init($step)")
|
|
||||||
navigationViewModel.update(FingerprintAction.ACTIVITY_CREATED, Init::class, "$TAG#init")
|
navigationViewModel.update(FingerprintAction.ACTIVITY_CREATED, Init::class, "$TAG#init")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,8 +20,8 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.VisibleForTesting
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -39,31 +39,11 @@ import kotlinx.coroutines.launch
|
|||||||
* This page will display basic information about what a fingerprint can be used for and acts as the
|
* This page will display basic information about what a fingerprint can be used for and acts as the
|
||||||
* final step of enrollment.
|
* final step of enrollment.
|
||||||
*/
|
*/
|
||||||
class FingerprintEnrollConfirmationV2Fragment() :
|
class FingerprintEnrollConfirmationV2Fragment(factory: ViewModelProvider.Factory? = null) :
|
||||||
Fragment(R.layout.fingerprint_enroll_finish_base) {
|
Fragment(R.layout.fingerprint_enroll_finish_base) {
|
||||||
|
|
||||||
companion object {
|
private val viewModel: FingerprintEnrollConfirmationViewModel by activityViewModels {
|
||||||
const val TAG = "FingerprintEnrollConfirmationV2Fragment"
|
factory ?: FingerprintEnrollConfirmationViewModel.Factory
|
||||||
}
|
|
||||||
|
|
||||||
/** Used for testing purposes */
|
|
||||||
private var factory: ViewModelProvider.Factory? = null
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
constructor(theFactory: ViewModelProvider.Factory) : this() {
|
|
||||||
factory = theFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
|
||||||
if (factory != null) {
|
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val viewModel: FingerprintEnrollConfirmationViewModel by lazy {
|
|
||||||
viewModelProvider[FingerprintEnrollConfirmationViewModel::class.java]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@@ -106,4 +86,8 @@ class FingerprintEnrollConfirmationV2Fragment() :
|
|||||||
private fun onNextButtonClick(view: View?) {
|
private fun onNextButtonClick(view: View?) {
|
||||||
viewModel.onNextButtonClicked()
|
viewModel.onNextButtonClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val TAG = "FingerprintEnrollConfirmationV2Fragment"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,8 +30,9 @@ import android.view.ViewGroup
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.VisibleForTesting
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
@@ -74,37 +75,22 @@ private data class TextModel(
|
|||||||
* 2. How the data will be stored
|
* 2. How the data will be stored
|
||||||
* 3. How the user can access and remove their data
|
* 3. How the user can access and remove their data
|
||||||
*/
|
*/
|
||||||
class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enroll_introduction) {
|
class FingerprintEnrollIntroV2Fragment(testFactory: ViewModelProvider.Factory? = null) :
|
||||||
|
Fragment(R.layout.fingerprint_v2_enroll_introduction) {
|
||||||
/** Used for testing purposes */
|
|
||||||
private var factory: ViewModelProvider.Factory? = null
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
constructor(theFactory: ViewModelProvider.Factory) : this() {
|
|
||||||
factory = theFactory
|
|
||||||
}
|
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
|
||||||
if (factory != null) {
|
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var footerBarMixin: FooterBarMixin
|
private lateinit var footerBarMixin: FooterBarMixin
|
||||||
private lateinit var textModel: TextModel
|
private lateinit var textModel: TextModel
|
||||||
|
|
||||||
private val viewModel: FingerprintEnrollIntroViewModel by lazy {
|
private val viewModel: FingerprintEnrollIntroViewModel by activityViewModels {
|
||||||
viewModelProvider[FingerprintEnrollIntroViewModel::class.java]
|
testFactory ?: FingerprintEnrollIntroViewModel.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val fingerprintScrollViewModel: FingerprintScrollViewModel by lazy {
|
private val fingerprintScrollViewModel: FingerprintScrollViewModel by viewModels {
|
||||||
viewModelProvider[FingerprintScrollViewModel::class.java]
|
testFactory ?: FingerprintScrollViewModel.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val gateKeeperViewModel: FingerprintGatekeeperViewModel by lazy {
|
private val gateKeeperViewModel: FingerprintGatekeeperViewModel by activityViewModels {
|
||||||
viewModelProvider[FingerprintGatekeeperViewModel::class.java]
|
testFactory ?: FingerprintGatekeeperViewModel.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
|
@@ -23,11 +23,15 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation
|
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
||||||
import com.google.android.setupcompat.template.FooterBarMixin
|
import com.google.android.setupcompat.template.FooterBarMixin
|
||||||
import com.google.android.setupcompat.template.FooterButton
|
import com.google.android.setupcompat.template.FooterButton
|
||||||
@@ -51,18 +55,10 @@ class RfpsEnrollFindSensorFragment() : Fragment() {
|
|||||||
factory = theFactory
|
factory = theFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
|
||||||
if (factory != null) {
|
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var animation: FingerprintFindSensorAnimation? = null
|
private var animation: FingerprintFindSensorAnimation? = null
|
||||||
|
|
||||||
private val viewModel: FingerprintEnrollFindSensorViewModel by lazy {
|
private val viewModel: FingerprintEnrollFindSensorViewModel by activityViewModels {
|
||||||
viewModelProvider[FingerprintEnrollFindSensorViewModel::class.java]
|
factory ?: FingerprintEnrollFindSensorViewModel.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@@ -78,6 +74,12 @@ class RfpsEnrollFindSensorFragment() : Fragment() {
|
|||||||
// Set up footer bar
|
// Set up footer bar
|
||||||
val footerBarMixin = view.getMixin(FooterBarMixin::class.java)
|
val footerBarMixin = view.getMixin(FooterBarMixin::class.java)
|
||||||
setupSecondaryButton(footerBarMixin)
|
setupSecondaryButton(footerBarMixin)
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
viewModel.enroll(requireActivity().intent.toFingerprintEnrollOptions())
|
||||||
|
}
|
||||||
|
}
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModel.showPrimaryButton.collect { setupPrimaryButton(footerBarMixin) }
|
viewModel.showPrimaryButton.collect { setupPrimaryButton(footerBarMixin) }
|
||||||
}
|
}
|
||||||
|
@@ -24,11 +24,15 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.airbnb.lottie.LottieAnimationView
|
import com.airbnb.lottie.LottieAnimationView
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
||||||
import com.google.android.setupcompat.template.FooterBarMixin
|
import com.google.android.setupcompat.template.FooterBarMixin
|
||||||
import com.google.android.setupcompat.template.FooterButton
|
import com.google.android.setupcompat.template.FooterButton
|
||||||
@@ -52,16 +56,8 @@ class SfpsEnrollFindSensorFragment() : Fragment() {
|
|||||||
factory = theFactory
|
factory = theFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
private val viewModel: FingerprintEnrollFindSensorViewModel by activityViewModels {
|
||||||
if (factory != null) {
|
factory ?: FingerprintEnrollFindSensorViewModel.Factory
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val viewModel: FingerprintEnrollFindSensorViewModel by lazy {
|
|
||||||
viewModelProvider[FingerprintEnrollFindSensorViewModel::class.java]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@@ -78,6 +74,12 @@ class SfpsEnrollFindSensorFragment() : Fragment() {
|
|||||||
val footerBarMixin = view.getMixin(FooterBarMixin::class.java)
|
val footerBarMixin = view.getMixin(FooterBarMixin::class.java)
|
||||||
setupSecondaryButton(footerBarMixin)
|
setupSecondaryButton(footerBarMixin)
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
viewModel.enroll(requireActivity().intent.toFingerprintEnrollOptions())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set up lottie
|
// Set up lottie
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModel.sfpsLottieInfo.collect { (isFolded, rotation) ->
|
viewModel.sfpsLottieInfo.collect { (isFolded, rotation) ->
|
||||||
|
@@ -24,11 +24,15 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.airbnb.lottie.LottieAnimationView
|
import com.airbnb.lottie.LottieAnimationView
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
||||||
import com.google.android.setupcompat.template.FooterBarMixin
|
import com.google.android.setupcompat.template.FooterBarMixin
|
||||||
import com.google.android.setupcompat.template.FooterButton
|
import com.google.android.setupcompat.template.FooterButton
|
||||||
@@ -53,16 +57,8 @@ class UdfpsEnrollFindSensorFragment() : Fragment() {
|
|||||||
factory = theFactory
|
factory = theFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
private val viewModel: FingerprintEnrollFindSensorViewModel by activityViewModels {
|
||||||
if (factory != null) {
|
factory ?: FingerprintEnrollFindSensorViewModel.Factory
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val viewModel: FingerprintEnrollFindSensorViewModel by lazy {
|
|
||||||
viewModelProvider[FingerprintEnrollFindSensorViewModel::class.java]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@@ -79,6 +75,12 @@ class UdfpsEnrollFindSensorFragment() : Fragment() {
|
|||||||
val footerBarMixin = view.getMixin(FooterBarMixin::class.java)
|
val footerBarMixin = view.getMixin(FooterBarMixin::class.java)
|
||||||
setupSecondaryButton(footerBarMixin)
|
setupSecondaryButton(footerBarMixin)
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
viewModel.enroll(requireActivity().intent.toFingerprintEnrollOptions())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModel.showPrimaryButton.collect { setupPrimaryButton(footerBarMixin) }
|
viewModel.showPrimaryButton.collect { setupPrimaryButton(footerBarMixin) }
|
||||||
}
|
}
|
||||||
|
@@ -28,12 +28,15 @@ import android.view.animation.Interpolator
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.widget.FingerprintErrorDialog
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.widget.FingerprintErrorDialog
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSIconTouchViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSIconTouchViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
|
||||||
@@ -62,29 +65,21 @@ class RFPSEnrollFragment() : Fragment(R.layout.fingerprint_v2_rfps_enroll_enroll
|
|||||||
factory = theFactory
|
factory = theFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
|
||||||
if (factory != null) {
|
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var linearOutSlowInInterpolator: Interpolator
|
private lateinit var linearOutSlowInInterpolator: Interpolator
|
||||||
private lateinit var fastOutLinearInInterpolator: Interpolator
|
private lateinit var fastOutLinearInInterpolator: Interpolator
|
||||||
private lateinit var textView: TextView
|
private lateinit var textView: TextView
|
||||||
private lateinit var progressBar: RFPSProgressBar
|
private lateinit var progressBar: RFPSProgressBar
|
||||||
|
|
||||||
private val iconTouchViewModel: RFPSIconTouchViewModel by lazy {
|
private val iconTouchViewModel: RFPSIconTouchViewModel by viewModels {
|
||||||
viewModelProvider[RFPSIconTouchViewModel::class.java]
|
RFPSIconTouchViewModel.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
private val rfpsViewModel: RFPSViewModel by lazy { viewModelProvider[RFPSViewModel::class.java] }
|
private val rfpsViewModel: RFPSViewModel by activityViewModels {
|
||||||
|
factory ?: RFPSViewModel.Factory
|
||||||
private val backgroundViewModel: BackgroundViewModel by lazy {
|
|
||||||
viewModelProvider[BackgroundViewModel::class.java]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val backgroundViewModel: BackgroundViewModel by activityViewModels()
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
@@ -131,6 +126,7 @@ class RFPSEnrollFragment() : Fragment(R.layout.fingerprint_v2_rfps_enroll_enroll
|
|||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
rfpsViewModel.enroll(requireActivity().intent.toFingerprintEnrollOptions())
|
||||||
// Icon animation update
|
// Icon animation update
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
// TODO(b/324427704): Fix this delay
|
// TODO(b/324427704): Fix this delay
|
||||||
|
@@ -19,6 +19,8 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrol
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
@@ -27,6 +29,7 @@ import kotlinx.coroutines.flow.transform
|
|||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
private const val touchesToShowDialog = 3
|
private const val touchesToShowDialog = 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is responsible for counting the number of touches on the fingerprint icon, and if this
|
* This class is responsible for counting the number of touches on the fingerprint icon, and if this
|
||||||
* number reaches a threshold it will produce an action via [shouldShowDialog] to indicate the ui
|
* number reaches a threshold it will produce an action via [shouldShowDialog] to indicate the ui
|
||||||
@@ -52,10 +55,9 @@ class RFPSIconTouchViewModel : ViewModel() {
|
|||||||
_touches.update { _touches.value + 1 }
|
_touches.update { _touches.value + 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
class RFPSIconTouchViewModelFactory : ViewModelProvider.Factory {
|
companion object {
|
||||||
@Suppress("UNCHECKED_CAST")
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
initializer { RFPSIconTouchViewModel() }
|
||||||
return RFPSIconTouchViewModel() as T
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,9 +16,14 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel
|
||||||
|
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
@@ -158,27 +163,27 @@ class RFPSViewModel(
|
|||||||
enrollFlow = fingerprintEnrollViewModel.enrollFlow
|
enrollFlow = fingerprintEnrollViewModel.enrollFlow
|
||||||
}
|
}
|
||||||
|
|
||||||
class RFPSViewModelFactory(
|
/** Starts enrollment. */
|
||||||
private val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
|
fun enroll(enrollOptions: FingerprintEnrollOptions) {
|
||||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
fingerprintEnrollViewModel.enroll(enrollOptions)
|
||||||
private val orientationInteractor: OrientationInteractor,
|
|
||||||
private val fingerprintManager: FingerprintManagerInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return RFPSViewModel(
|
|
||||||
fingerprintEnrollEnrollingViewModel,
|
|
||||||
navigationViewModel,
|
|
||||||
orientationInteractor,
|
|
||||||
fingerprintManager,
|
|
||||||
)
|
|
||||||
as T
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val navStep = Enrollment::class
|
private val navStep = Enrollment::class
|
||||||
private const val TAG = "RFPSViewModel"
|
private const val TAG = "RFPSViewModel"
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment!!
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
RFPSViewModel(
|
||||||
|
provider[FingerprintEnrollEnrollingViewModel::class],
|
||||||
|
provider[FingerprintNavigationViewModel::class],
|
||||||
|
biometricEnvironment.orientationInteractor,
|
||||||
|
biometricEnvironment.fingerprintManagerInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -82,6 +82,7 @@ class RFPSProgressBar : RingProgressBar {
|
|||||||
|
|
||||||
shouldAnimateInternal = shouldAnimate
|
shouldAnimateInternal = shouldAnimate
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This function should only be called when actual progress has been made. */
|
/** This function should only be called when actual progress has been made. */
|
||||||
fun updateProgress(percentComplete: Float) {
|
fun updateProgress(percentComplete: Float) {
|
||||||
val progress = maxProgress - (percentComplete.coerceIn(0.0f, 100.0f) * maxProgress).toInt()
|
val progress = maxProgress - (percentComplete.coerceIn(0.0f, 100.0f) * maxProgress).toInt()
|
||||||
|
@@ -18,8 +18,6 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrol
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.MotionEvent.ACTION_HOVER_MOVE
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
@@ -27,6 +25,7 @@ import android.widget.Button
|
|||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -36,6 +35,7 @@ import com.airbnb.lottie.LottieCompositionFactory
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.biometrics.fingerprint2.data.model.EnrollStageModel
|
import com.android.settings.biometrics.fingerprint2.data.model.EnrollStageModel
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.widget.FingerprintErrorDialog
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.widget.FingerprintErrorDialog
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.model.DescriptionText
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.model.DescriptionText
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.model.HeaderText
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.model.HeaderText
|
||||||
@@ -50,17 +50,10 @@ class UdfpsEnrollFragment() : Fragment(R.layout.fingerprint_v2_udfps_enroll_enro
|
|||||||
|
|
||||||
/** Used for testing purposes */
|
/** Used for testing purposes */
|
||||||
private var factory: ViewModelProvider.Factory? = null
|
private var factory: ViewModelProvider.Factory? = null
|
||||||
private val viewModel: UdfpsViewModel by lazy { viewModelProvider[UdfpsViewModel::class.java] }
|
|
||||||
private lateinit var udfpsEnrollView: UdfpsEnrollViewV2
|
private lateinit var udfpsEnrollView: UdfpsEnrollViewV2
|
||||||
private lateinit var lottie: LottieAnimationView
|
private lateinit var lottie: LottieAnimationView
|
||||||
|
|
||||||
private val viewModelProvider: ViewModelProvider by lazy {
|
private val viewModel: UdfpsViewModel by activityViewModels { factory ?: UdfpsViewModel.Factory }
|
||||||
if (factory != null) {
|
|
||||||
ViewModelProvider(requireActivity(), factory!!)
|
|
||||||
} else {
|
|
||||||
ViewModelProvider(requireActivity())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
constructor(theFactory: ViewModelProvider.Factory) : this() {
|
constructor(theFactory: ViewModelProvider.Factory) : this() {
|
||||||
@@ -90,6 +83,7 @@ class UdfpsEnrollFragment() : Fragment(R.layout.fingerprint_v2_udfps_enroll_enro
|
|||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
viewModel.enroll(requireActivity().intent.toFingerprintEnrollOptions())
|
||||||
launch {
|
launch {
|
||||||
viewModel.sensorLocation.collect { sensor ->
|
viewModel.sensorLocation.collect { sensor ->
|
||||||
udfpsEnrollView.setSensorRect(sensor.sensorBounds, sensor.sensorType)
|
udfpsEnrollView.setSensorRect(sensor.sensorBounds, sensor.sensorType)
|
||||||
@@ -204,12 +198,16 @@ class UdfpsEnrollFragment() : Fragment(R.layout.fingerprint_v2_udfps_enroll_enro
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewModel.touchExplorationDebug.collect {
|
view.setOnTouchListener { _, motionEvent ->
|
||||||
udfpsEnrollView.sendDebugTouchExplorationEvent(
|
viewModel.onTouchEvent(motionEvent)
|
||||||
MotionEvent.obtain(100, 100, ACTION_HOVER_MOVE, it.x.toFloat(), it.y.toFloat(), 0)
|
false
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
viewModel.touchEvent.collect { udfpsEnrollView.onTouchEvent(it) }
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.readyForEnrollment()
|
viewModel.readyForEnrollment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,9 +16,13 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintVibrationEffects
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintVibrationEffects
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
@@ -89,14 +93,18 @@ class UdfpsLastStepViewModel(
|
|||||||
}
|
}
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
|
|
||||||
class UdfpsLastStepViewModelFactory(
|
companion object {
|
||||||
private val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
private val vibrationInteractor: VibrationInteractor,
|
initializer {
|
||||||
) : ViewModelProvider.Factory {
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
@Suppress("UNCHECKED_CAST")
|
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
return UdfpsLastStepViewModel(fingerprintEnrollEnrollingViewModel, vibrationInteractor) as T
|
UdfpsLastStepViewModel(
|
||||||
|
provider[FingerprintEnrollEnrollingViewModel::class],
|
||||||
|
biometricEnvironment!!.vibrationInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,21 +16,26 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.viewmodel
|
||||||
|
|
||||||
import android.graphics.Point
|
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.data.model.EnrollStageModel
|
import com.android.settings.biometrics.fingerprint2.data.model.EnrollStageModel
|
||||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
|
|
||||||
import com.android.settings.biometrics.fingerprint2.data.repository.SimulatedTouchEventsRepository
|
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DebuggingInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DebuggingInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintSensorInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintVibrationEffects
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintVibrationEffects
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.TouchEventInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
@@ -45,6 +50,7 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
|
|||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.combineTransform
|
import kotlinx.coroutines.flow.combineTransform
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
@@ -60,20 +66,20 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
/** ViewModel used to drive UDFPS Enrollment through [UdfpsEnrollFragment] */
|
/** ViewModel used to drive UDFPS Enrollment through [UdfpsEnrollFragment] */
|
||||||
class UdfpsViewModel(
|
class UdfpsViewModel(
|
||||||
|
val navigationViewModel: FingerprintNavigationViewModel,
|
||||||
|
val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
|
||||||
|
backgroundViewModel: BackgroundViewModel,
|
||||||
|
val udfpsLastStepViewModel: UdfpsLastStepViewModel,
|
||||||
val vibrationInteractor: VibrationInteractor,
|
val vibrationInteractor: VibrationInteractor,
|
||||||
displayDensityInteractor: DisplayDensityInteractor,
|
displayDensityInteractor: DisplayDensityInteractor,
|
||||||
val navigationViewModel: FingerprintNavigationViewModel,
|
|
||||||
debuggingInteractor: DebuggingInteractor,
|
debuggingInteractor: DebuggingInteractor,
|
||||||
val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
|
|
||||||
simulatedTouchEventsDebugRepository: SimulatedTouchEventsRepository,
|
|
||||||
enrollStageInteractor: EnrollStageInteractor,
|
enrollStageInteractor: EnrollStageInteractor,
|
||||||
orientationInteractor: OrientationInteractor,
|
orientationInteractor: OrientationInteractor,
|
||||||
backgroundViewModel: BackgroundViewModel,
|
|
||||||
sensorRepository: FingerprintSensorRepository,
|
|
||||||
udfpsEnrollInteractor: UdfpsEnrollInteractor,
|
udfpsEnrollInteractor: UdfpsEnrollInteractor,
|
||||||
fingerprintManager: FingerprintManagerInteractor,
|
fingerprintManager: FingerprintManagerInteractor,
|
||||||
val udfpsLastStepViewModel: UdfpsLastStepViewModel,
|
|
||||||
accessibilityInteractor: AccessibilityInteractor,
|
accessibilityInteractor: AccessibilityInteractor,
|
||||||
|
sensorRepository: FingerprintSensorInteractor,
|
||||||
|
touchEventInteractor: TouchEventInteractor,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val isSetupWizard = flowOf(false)
|
private val isSetupWizard = flowOf(false)
|
||||||
@@ -191,15 +197,9 @@ class UdfpsViewModel(
|
|||||||
.transform { emit(it == Surface.ROTATION_90) }
|
.transform { emit(it == Surface.ROTATION_90) }
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
|
|
||||||
/** This sends touch exploration events only used for debugging purposes. */
|
private val _touchEvent: MutableStateFlow<MotionEvent?> = MutableStateFlow(null)
|
||||||
val touchExplorationDebug: Flow<Point> =
|
val touchEvent =
|
||||||
debuggingInteractor.debuggingEnabled.combineTransform(
|
_touchEvent.asStateFlow().filterNotNull()
|
||||||
simulatedTouchEventsDebugRepository.touchExplorationDebug
|
|
||||||
) { enabled, point ->
|
|
||||||
if (enabled) {
|
|
||||||
emit(point)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Determines the current [EnrollStageModel] enrollment is in */
|
/** Determines the current [EnrollStageModel] enrollment is in */
|
||||||
private val enrollStage: Flow<EnrollStageModel> =
|
private val enrollStage: Flow<EnrollStageModel> =
|
||||||
@@ -266,6 +266,12 @@ class UdfpsViewModel(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
backgroundViewModel.background.filter { it }.collect { didGoToBackground() }
|
backgroundViewModel.background.filter { it }.collect { didGoToBackground() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModelScope.launch {
|
||||||
|
touchEventInteractor.touchEvent.collect {
|
||||||
|
_touchEvent.update { it }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Indicates if we should show the lottie. */
|
/** Indicates if we should show the lottie. */
|
||||||
@@ -393,47 +399,43 @@ class UdfpsViewModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class UdfpsEnrollmentFactory(
|
/** Starts enrollment. */
|
||||||
private val vibrationInteractor: VibrationInteractor,
|
fun enroll(enrollOptions: FingerprintEnrollOptions) {
|
||||||
private val displayDensityInteractor: DisplayDensityInteractor,
|
fingerprintEnrollEnrollingViewModel.enroll(enrollOptions)
|
||||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
|
||||||
private val debuggingInteractor: DebuggingInteractor,
|
|
||||||
private val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
|
|
||||||
private val simulatedTouchEventsRepository: SimulatedTouchEventsRepository,
|
|
||||||
private val enrollStageInteractor: EnrollStageInteractor,
|
|
||||||
private val orientationInteractor: OrientationInteractor,
|
|
||||||
private val backgroundViewModel: BackgroundViewModel,
|
|
||||||
private val sensorRepository: FingerprintSensorRepository,
|
|
||||||
private val udfpsEnrollInteractor: UdfpsEnrollInteractor,
|
|
||||||
private val fingerprintManager: FingerprintManagerInteractor,
|
|
||||||
private val udfpsLastStepViewModel: UdfpsLastStepViewModel,
|
|
||||||
private val accessibilityInteractor: AccessibilityInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return UdfpsViewModel(
|
|
||||||
vibrationInteractor,
|
|
||||||
displayDensityInteractor,
|
|
||||||
navigationViewModel,
|
|
||||||
debuggingInteractor,
|
|
||||||
fingerprintEnrollEnrollingViewModel,
|
|
||||||
simulatedTouchEventsRepository,
|
|
||||||
enrollStageInteractor,
|
|
||||||
orientationInteractor,
|
|
||||||
backgroundViewModel,
|
|
||||||
sensorRepository,
|
|
||||||
udfpsEnrollInteractor,
|
|
||||||
fingerprintManager,
|
|
||||||
udfpsLastStepViewModel,
|
|
||||||
accessibilityInteractor,
|
|
||||||
)
|
|
||||||
as T
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Indicates a touch event has occurred. */
|
||||||
|
fun onTouchEvent(event: MotionEvent) {
|
||||||
|
_touchEvent.update { event }
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val navStep = FingerprintNavigationStep.Enrollment::class
|
private val navStep = FingerprintNavigationStep.Enrollment::class
|
||||||
private const val TAG = "UDFPSViewModel"
|
private const val TAG = "UDFPSViewModel"
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment!!
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
|
||||||
|
UdfpsViewModel(
|
||||||
|
provider[FingerprintNavigationViewModel::class],
|
||||||
|
provider[FingerprintEnrollEnrollingViewModel::class],
|
||||||
|
provider[BackgroundViewModel::class],
|
||||||
|
provider[UdfpsLastStepViewModel::class],
|
||||||
|
biometricEnvironment.vibrationInteractor,
|
||||||
|
biometricEnvironment.displayDensityInteractor,
|
||||||
|
biometricEnvironment.debuggingInteractor,
|
||||||
|
biometricEnvironment.enrollStageInteractor,
|
||||||
|
biometricEnvironment.orientationInteractor,
|
||||||
|
biometricEnvironment.udfpsEnrollInteractor,
|
||||||
|
biometricEnvironment.fingerprintManagerInteractor,
|
||||||
|
biometricEnvironment.accessibilityInteractor,
|
||||||
|
biometricEnvironment.sensorInteractor,
|
||||||
|
biometricEnvironment.touchEventInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -210,6 +210,7 @@ class UdfpsEnrollProgressBarDrawableV2(private val context: Context, attrs: Attr
|
|||||||
override fun getOpacity(): Int {
|
override fun getOpacity(): Int {
|
||||||
return PixelFormat.UNKNOWN
|
return PixelFormat.UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the progress with locations [sensorLocationX] [sensorLocationY], note these must be with
|
* Draws the progress with locations [sensorLocationX] [sensorLocationY], note these must be with
|
||||||
* respect to the parent framelayout.
|
* respect to the parent framelayout.
|
||||||
|
@@ -148,18 +148,10 @@ class UdfpsEnrollViewV2(context: Context, attrs: AttributeSet?) : FrameLayout(co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends a touch exploration event to the [onHoverListener] this should only be used for
|
|
||||||
* debugging.
|
|
||||||
*/
|
|
||||||
fun sendDebugTouchExplorationEvent(motionEvent: MotionEvent) {
|
|
||||||
touchExplorationAnnouncer.onTouch(motionEvent)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the addHoverListener, this should happen when talkback is enabled. */
|
/** Sets the addHoverListener, this should happen when talkback is enabled. */
|
||||||
private fun addHoverListener() {
|
private fun addHoverListener() {
|
||||||
onHoverListener = OnHoverListener { _: View, event: MotionEvent ->
|
onHoverListener = OnHoverListener { _: View, event: MotionEvent ->
|
||||||
sendDebugTouchExplorationEvent(event)
|
touchExplorationAnnouncer.onTouch(event)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
this.setOnHoverListener(onHoverListener)
|
this.setOnHoverListener(onHoverListener)
|
||||||
|
@@ -18,6 +18,8 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
@@ -39,10 +41,9 @@ class BackgroundViewModel : ViewModel() {
|
|||||||
_background.update { false }
|
_background.update { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
class BackgroundViewModelFactory : ViewModelProvider.Factory {
|
companion object {
|
||||||
@Suppress("UNCHECKED_CAST")
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
initializer { BackgroundViewModel() }
|
||||||
return BackgroundViewModel() as T
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,14 +16,17 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
/**
|
/** Models the UI state for [FingerprintEnrollConfirmationV2Fragment] */
|
||||||
* Models the UI state for [FingerprintEnrollConfirmationV2Fragment]
|
|
||||||
*/
|
|
||||||
class FingerprintEnrollConfirmationViewModel(
|
class FingerprintEnrollConfirmationViewModel(
|
||||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||||
fingerprintInteractor: FingerprintManagerInteractor,
|
fingerprintInteractor: FingerprintManagerInteractor,
|
||||||
@@ -50,18 +53,20 @@ class FingerprintEnrollConfirmationViewModel(
|
|||||||
navigationViewModel.update(FingerprintAction.ADD_ANOTHER, navStep, "onAddAnotherButtonClicked")
|
navigationViewModel.update(FingerprintAction.ADD_ANOTHER, navStep, "onAddAnotherButtonClicked")
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintEnrollConfirmationViewModelFactory(
|
|
||||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
|
||||||
private val fingerprintInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintEnrollConfirmationViewModel(navigationViewModel, fingerprintInteractor) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "FingerprintEnrollConfirmationViewModel"
|
private const val TAG = "FingerprintEnrollConfirmationViewModel"
|
||||||
private val navStep = FingerprintNavigationStep.Confirmation::class
|
private val navStep = FingerprintNavigationStep.Confirmation::class
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
FingerprintEnrollConfirmationViewModel(
|
||||||
|
provider[FingerprintNavigationViewModel::class],
|
||||||
|
biometricEnvironment!!.fingerprintManagerInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,14 +16,15 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||||
|
|
||||||
import android.util.Log
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
|
||||||
import kotlinx.coroutines.flow.transformLatest
|
import kotlinx.coroutines.flow.transformLatest
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
@@ -69,23 +70,24 @@ class FingerprintEnrollEnrollingViewModel(
|
|||||||
val enrollFlow =
|
val enrollFlow =
|
||||||
enrollFlowShouldBeRunning.transformLatest {
|
enrollFlowShouldBeRunning.transformLatest {
|
||||||
if (it) {
|
if (it) {
|
||||||
fingerprintEnrollViewModel.enrollFlow.collect { event ->
|
fingerprintEnrollViewModel.enrollFlow.collect { event -> emit(event) }
|
||||||
emit(event) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintEnrollEnrollingViewModelFactory(
|
/** Indicates enrollment to start */
|
||||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
fun enroll(enrollOptions: FingerprintEnrollOptions) {
|
||||||
private val backgroundViewModel: BackgroundViewModel,
|
fingerprintEnrollViewModel.enroll(enrollOptions)
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
|
||||||
as T
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = "FingerprintEnrollEnrollingViewModel"
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
FingerprintEnrollEnrollingViewModel(
|
||||||
|
provider[FingerprintEnrollViewModel::class],
|
||||||
|
provider[BackgroundViewModel::class],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,9 +16,14 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||||
|
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||||
@@ -43,10 +48,10 @@ class FingerprintEnrollFindSensorViewModel(
|
|||||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||||
backgroundViewModel: BackgroundViewModel,
|
backgroundViewModel: BackgroundViewModel,
|
||||||
|
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||||
accessibilityInteractor: AccessibilityInteractor,
|
accessibilityInteractor: AccessibilityInteractor,
|
||||||
foldStateInteractor: FoldStateInteractor,
|
foldStateInteractor: FoldStateInteractor,
|
||||||
orientationInteractor: OrientationInteractor,
|
orientationInteractor: OrientationInteractor,
|
||||||
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
@@ -64,6 +69,7 @@ class FingerprintEnrollFindSensorViewModel(
|
|||||||
val showPrimaryButton: Flow<Boolean> = _isUdfps.filter { it }
|
val showPrimaryButton: Flow<Boolean> = _isUdfps.filter { it }
|
||||||
|
|
||||||
private val _showSfpsLottie = _isSfps.filter { it }
|
private val _showSfpsLottie = _isSfps.filter { it }
|
||||||
|
|
||||||
/** Represents the stream of showing sfps lottie and the information Pair(isFolded, rotation). */
|
/** Represents the stream of showing sfps lottie and the information Pair(isFolded, rotation). */
|
||||||
val sfpsLottieInfo: Flow<Pair<Boolean, Int>> =
|
val sfpsLottieInfo: Flow<Pair<Boolean, Int>> =
|
||||||
combineTransform(
|
combineTransform(
|
||||||
@@ -75,6 +81,7 @@ class FingerprintEnrollFindSensorViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val _showUdfpsLottie = _isUdfps.filter { it }
|
private val _showUdfpsLottie = _isUdfps.filter { it }
|
||||||
|
|
||||||
/** Represents the stream of showing udfps lottie and whether accessibility is enabled. */
|
/** Represents the stream of showing udfps lottie and whether accessibility is enabled. */
|
||||||
val udfpsLottieInfo: Flow<Boolean> =
|
val udfpsLottieInfo: Flow<Boolean> =
|
||||||
_showUdfpsLottie.combine(accessibilityInteractor.isAccessibilityEnabled) {
|
_showUdfpsLottie.combine(accessibilityInteractor.isAccessibilityEnabled) {
|
||||||
@@ -87,11 +94,13 @@ class FingerprintEnrollFindSensorViewModel(
|
|||||||
val showRfpsAnimation: Flow<Boolean> = _isRearSfps.filter { it }
|
val showRfpsAnimation: Flow<Boolean> = _isRearSfps.filter { it }
|
||||||
|
|
||||||
private val _showErrorDialog: MutableStateFlow<Pair<Int, Boolean>?> = MutableStateFlow(null)
|
private val _showErrorDialog: MutableStateFlow<Pair<Int, Boolean>?> = MutableStateFlow(null)
|
||||||
|
|
||||||
/** Represents the stream of showing error dialog. */
|
/** Represents the stream of showing error dialog. */
|
||||||
val showErrorDialog = _showErrorDialog.filterNotNull()
|
val showErrorDialog = _showErrorDialog.filterNotNull()
|
||||||
|
|
||||||
private var _didTryEducation = false
|
private var _didTryEducation = false
|
||||||
private var _education: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
private var _education: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||||
|
|
||||||
/** Indicates if the education flow should be running. */
|
/** Indicates if the education flow should be running. */
|
||||||
private val educationFlowShouldBeRunning: Flow<Boolean> =
|
private val educationFlowShouldBeRunning: Flow<Boolean> =
|
||||||
_education.combine(backgroundViewModel.background) { shouldRunEducation, isInBackground ->
|
_education.combine(backgroundViewModel.background) { shouldRunEducation, isInBackground ->
|
||||||
@@ -167,6 +176,11 @@ class FingerprintEnrollFindSensorViewModel(
|
|||||||
_education.update { false }
|
_education.update { false }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Indicates enrollment to start */
|
||||||
|
fun enroll(enrollOptions: FingerprintEnrollOptions) {
|
||||||
|
fingerprintEnrollViewModel.enroll(enrollOptions)
|
||||||
|
}
|
||||||
|
|
||||||
/** Proceed to EnrollEnrolling page. */
|
/** Proceed to EnrollEnrolling page. */
|
||||||
fun proceedToEnrolling() {
|
fun proceedToEnrolling() {
|
||||||
stopEducation()
|
stopEducation()
|
||||||
@@ -182,36 +196,29 @@ class FingerprintEnrollFindSensorViewModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintEnrollFindSensorViewModelFactory(
|
|
||||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
|
||||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
|
||||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
|
||||||
private val backgroundViewModel: BackgroundViewModel,
|
|
||||||
private val accessibilityInteractor: AccessibilityInteractor,
|
|
||||||
private val foldStateInteractor: FoldStateInteractor,
|
|
||||||
private val orientationInteractor: OrientationInteractor,
|
|
||||||
private val fingerprintFlowViewModel: FingerprintFlowViewModel,
|
|
||||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintEnrollFindSensorViewModel(
|
|
||||||
navigationViewModel,
|
|
||||||
fingerprintEnrollViewModel,
|
|
||||||
gatekeeperViewModel,
|
|
||||||
backgroundViewModel,
|
|
||||||
accessibilityInteractor,
|
|
||||||
foldStateInteractor,
|
|
||||||
orientationInteractor,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "FingerprintEnrollFindSensorViewModel"
|
private const val TAG = "FingerprintEnrollFindSensorViewModel"
|
||||||
private val navStep = Education::class
|
private val navStep = Education::class
|
||||||
|
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment!!
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
|
||||||
|
FingerprintEnrollFindSensorViewModel(
|
||||||
|
provider[FingerprintNavigationViewModel::class],
|
||||||
|
provider[FingerprintEnrollViewModel::class],
|
||||||
|
provider[FingerprintGatekeeperViewModel::class],
|
||||||
|
provider[BackgroundViewModel::class],
|
||||||
|
provider[FingerprintFlowViewModel::class],
|
||||||
|
biometricEnvironment.accessibilityInteractor,
|
||||||
|
biometricEnvironment.foldStateInteractor,
|
||||||
|
biometricEnvironment.orientationInteractor,
|
||||||
|
biometricEnvironment.fingerprintManagerInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,8 +16,12 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||||
|
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
||||||
@@ -27,8 +31,8 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
/** A view model for fingerprint enroll introduction. */
|
/** A view model for fingerprint enroll introduction. */
|
||||||
class FingerprintEnrollIntroViewModel(
|
class FingerprintEnrollIntroViewModel(
|
||||||
val navigationViewModel: FingerprintNavigationViewModel,
|
val navigationViewModel: FingerprintNavigationViewModel,
|
||||||
private val fingerprintFlowViewModel: FingerprintFlowViewModel,
|
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
/** Represents a stream of [FingerprintSensor] */
|
/** Represents a stream of [FingerprintSensor] */
|
||||||
@@ -51,25 +55,21 @@ class FingerprintEnrollIntroViewModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintEnrollIntoViewModelFactory(
|
|
||||||
val navigationViewModel: FingerprintNavigationViewModel,
|
|
||||||
val fingerprintFlowViewModel: FingerprintFlowViewModel,
|
|
||||||
val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintEnrollIntroViewModel(
|
|
||||||
navigationViewModel,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val navStep = Introduction::class
|
val navStep = Introduction::class
|
||||||
private const val TAG = "FingerprintEnrollIntroViewModel"
|
private const val TAG = "FingerprintEnrollIntroViewModel"
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
FingerprintEnrollIntroViewModel(
|
||||||
|
provider[FingerprintNavigationViewModel::class],
|
||||||
|
provider[FingerprintFlowViewModel::class],
|
||||||
|
biometricEnvironment!!.fingerprintManagerInteractor,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,9 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||||
|
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
|
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||||
@@ -25,12 +31,14 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
|
|||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
||||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.shareIn
|
import kotlinx.coroutines.flow.shareIn
|
||||||
import kotlinx.coroutines.flow.transformLatest
|
import kotlinx.coroutines.flow.transformLatest
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
/** Represents all of the fingerprint information needed for a fingerprint enrollment process. */
|
/** Represents all of the fingerprint information needed for a fingerprint enrollment process. */
|
||||||
class FingerprintEnrollViewModel(
|
class FingerprintEnrollViewModel(
|
||||||
@@ -55,6 +63,8 @@ class FingerprintEnrollViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val enrollOptions: MutableStateFlow<FingerprintEnrollOptions?> = MutableStateFlow(null)
|
||||||
|
|
||||||
/** Represents the stream of [FingerprintSensorType] */
|
/** Represents the stream of [FingerprintSensorType] */
|
||||||
val sensorType: Flow<FingerprintSensorType?> =
|
val sensorType: Flow<FingerprintSensorType?> =
|
||||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||||
@@ -66,16 +76,23 @@ class FingerprintEnrollViewModel(
|
|||||||
* This flow should be the only flow which calls enroll().
|
* This flow should be the only flow which calls enroll().
|
||||||
*/
|
*/
|
||||||
val _enrollFlow: Flow<FingerEnrollState> =
|
val _enrollFlow: Flow<FingerEnrollState> =
|
||||||
combine(gatekeeperViewModel.gatekeeperInfo, _enrollReason) { hardwareAuthToken, enrollReason ->
|
combine(gatekeeperViewModel.gatekeeperInfo, _enrollReason, enrollOptions) {
|
||||||
Pair(hardwareAuthToken, enrollReason)
|
hardwareAuthToken,
|
||||||
|
enrollReason,
|
||||||
|
enrollOptions ->
|
||||||
|
Triple(hardwareAuthToken, enrollReason, enrollOptions)
|
||||||
}
|
}
|
||||||
.transformLatest {
|
.transformLatest {
|
||||||
/** [transformLatest] is used as we want to make sure to cancel previous API call. */
|
/** [transformLatest] is used as we want to make sure to cancel previous API call. */
|
||||||
(hardwareAuthToken, enrollReason) ->
|
(hardwareAuthToken, enrollReason, enrollOptions) ->
|
||||||
if (hardwareAuthToken is GatekeeperInfo.GatekeeperPasswordInfo && enrollReason != null) {
|
if (
|
||||||
fingerprintManagerInteractor.enroll(hardwareAuthToken.token, enrollReason).collect {
|
hardwareAuthToken is GatekeeperInfo.GatekeeperPasswordInfo &&
|
||||||
emit(it)
|
enrollReason != null &&
|
||||||
}
|
enrollOptions != null
|
||||||
|
) {
|
||||||
|
fingerprintManagerInteractor
|
||||||
|
.enroll(hardwareAuthToken.token, enrollReason, enrollOptions)
|
||||||
|
.collect { emit(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 0)
|
.shareIn(viewModelScope, SharingStarted.WhileSubscribed(), 0)
|
||||||
@@ -108,14 +125,23 @@ class FingerprintEnrollViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintEnrollViewModelFactory(
|
/** Starts enrollment. */
|
||||||
val interactor: FingerprintManagerInteractor,
|
fun enroll(options: FingerprintEnrollOptions) {
|
||||||
val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
enrollOptions.update { options }
|
||||||
val navigationViewModel: FingerprintNavigationViewModel,
|
}
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
companion object {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
return FingerprintEnrollViewModel(interactor, gatekeeperViewModel, navigationViewModel) as T
|
initializer {
|
||||||
|
val settingsApplication = this[APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||||
|
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||||
|
FingerprintEnrollViewModel(
|
||||||
|
biometricEnvironment!!.fingerprintManagerInteractor,
|
||||||
|
provider[FingerprintGatekeeperViewModel::class],
|
||||||
|
provider[FingerprintNavigationViewModel::class],
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,21 +19,28 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
import kotlinx.coroutines.flow.shareIn
|
import kotlinx.coroutines.flow.shareIn
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
||||||
class FingerprintFlowViewModel(private val fingerprintFlowType: FingerprintFlow) : ViewModel() {
|
class FingerprintFlowViewModel() : ViewModel() {
|
||||||
val fingerprintFlow: Flow<FingerprintFlow> =
|
val _mutableFingerprintFlow: MutableStateFlow<FingerprintFlow?> = MutableStateFlow(null)
|
||||||
flowOf(fingerprintFlowType).shareIn(viewModelScope, SharingStarted.Eagerly, 1)
|
val fingerprintFlow: Flow<FingerprintFlow?> =
|
||||||
|
_mutableFingerprintFlow.shareIn(viewModelScope, SharingStarted.Eagerly, 1)
|
||||||
|
|
||||||
class FingerprintFlowViewModelFactory(val flowType: FingerprintFlow) : ViewModelProvider.Factory {
|
/** Used to set the fingerprint flow type */
|
||||||
|
fun updateFlowType(fingerprintFlowType: FingerprintFlow) {
|
||||||
|
_mutableFingerprintFlow.update { fingerprintFlowType }
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
companion object {
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
return FingerprintFlowViewModel(flowType) as T
|
initializer { FingerprintFlowViewModel() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,9 @@ import android.util.Log
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -47,12 +50,10 @@ sealed interface GatekeeperInfo {
|
|||||||
* in as a parameter to this class.
|
* in as a parameter to this class.
|
||||||
*/
|
*/
|
||||||
class FingerprintGatekeeperViewModel(
|
class FingerprintGatekeeperViewModel(
|
||||||
theGatekeeperInfo: GatekeeperInfo?,
|
private val fingerprintManagerInteractor: FingerprintManagerInteractor
|
||||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private var _gatekeeperInfo: MutableStateFlow<GatekeeperInfo?> =
|
private var _gatekeeperInfo: MutableStateFlow<GatekeeperInfo?> = MutableStateFlow(null)
|
||||||
MutableStateFlow(theGatekeeperInfo)
|
|
||||||
|
|
||||||
/** The gatekeeper info for fingerprint enrollment. */
|
/** The gatekeeper info for fingerprint enrollment. */
|
||||||
val gatekeeperInfo: Flow<GatekeeperInfo?> = _gatekeeperInfo.asStateFlow()
|
val gatekeeperInfo: Flow<GatekeeperInfo?> = _gatekeeperInfo.asStateFlow()
|
||||||
@@ -61,29 +62,30 @@ class FingerprintGatekeeperViewModel(
|
|||||||
val hasValidGatekeeperInfo: Flow<Boolean> =
|
val hasValidGatekeeperInfo: Flow<Boolean> =
|
||||||
gatekeeperInfo.map { it is GatekeeperInfo.GatekeeperPasswordInfo }
|
gatekeeperInfo.map { it is GatekeeperInfo.GatekeeperPasswordInfo }
|
||||||
|
|
||||||
private var _credentialConfirmed: MutableStateFlow<Boolean?> = MutableStateFlow(null)
|
|
||||||
val credentialConfirmed: Flow<Boolean?> = _credentialConfirmed.asStateFlow()
|
|
||||||
|
|
||||||
private var countDownTimer: CountDownTimer? = null
|
private var countDownTimer: CountDownTimer? = null
|
||||||
|
|
||||||
/** Timeout of 15 minutes for a generated challenge */
|
/** Timeout of 15 minutes for a generated challenge */
|
||||||
private val TIMEOUT: Long = 15 * 60 * 1000
|
private val TIMEOUT: Long = 15 * 60 * 1000
|
||||||
|
|
||||||
/** Called after a confirm device credential attempt has been made. */
|
/** Called after a confirm device credential attempt has been made. */
|
||||||
fun onConfirmDevice(wasSuccessful: Boolean, theGatekeeperPasswordHandle: Long?) {
|
fun onConfirmDevice(
|
||||||
|
wasSuccessful: Boolean,
|
||||||
|
theGatekeeperPasswordHandle: Long?,
|
||||||
|
shouldStartTimer: Boolean = true,
|
||||||
|
) {
|
||||||
if (!wasSuccessful) {
|
if (!wasSuccessful) {
|
||||||
Log.d(TAG, "confirmDevice failed")
|
Log.d(TAG, "confirmDevice failed")
|
||||||
_gatekeeperInfo.update { GatekeeperInfo.Invalid }
|
_gatekeeperInfo.update { GatekeeperInfo.Invalid }
|
||||||
_credentialConfirmed.update { false }
|
|
||||||
} else {
|
} else {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val res = fingerprintManagerInteractor.generateChallenge(theGatekeeperPasswordHandle!!)
|
val res = fingerprintManagerInteractor.generateChallenge(theGatekeeperPasswordHandle!!)
|
||||||
_gatekeeperInfo.update { GatekeeperInfo.GatekeeperPasswordInfo(res.second, res.first) }
|
_gatekeeperInfo.update { GatekeeperInfo.GatekeeperPasswordInfo(res.second, res.first) }
|
||||||
_credentialConfirmed.update { true }
|
if (shouldStartTimer) {
|
||||||
startTimeout()
|
startTimeout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun startTimeout() {
|
private fun startTimeout() {
|
||||||
countDownTimer?.cancel()
|
countDownTimer?.cancel()
|
||||||
@@ -97,19 +99,9 @@ class FingerprintGatekeeperViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintGatekeeperViewModelFactory(
|
|
||||||
private val gatekeeperInfo: GatekeeperInfo?,
|
|
||||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintGatekeeperViewModel(gatekeeperInfo, fingerprintManagerInteractor) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "FingerprintGatekeeperViewModel"
|
private const val TAG = "FingerprintGatekeeperViewModel"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function that checks if the challenge and token are valid, in which case a
|
* A function that checks if the challenge and token are valid, in which case a
|
||||||
* [GatekeeperInfo.GatekeeperPasswordInfo] is provided, else [GatekeeperInfo.Invalid]
|
* [GatekeeperInfo.GatekeeperPasswordInfo] is provided, else [GatekeeperInfo.Invalid]
|
||||||
@@ -121,5 +113,14 @@ class FingerprintGatekeeperViewModel(
|
|||||||
}
|
}
|
||||||
return GatekeeperInfo.GatekeeperPasswordInfo(token, challenge)
|
return GatekeeperInfo.GatekeeperPasswordInfo(token, challenge)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||||
|
FingerprintGatekeeperViewModel(biometricEnvironment!!.fingerprintManagerInteractor)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,11 @@ import android.util.Log
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
|
import com.android.settings.SettingsApplication
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Finish
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Finish
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.UiStep
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.UiStep
|
||||||
@@ -28,39 +32,40 @@ import java.lang.NullPointerException
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.combineTransform
|
import kotlinx.coroutines.flow.combineTransform
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is essentially a wrapper around [FingerprintNavigationStep] that will be used by
|
* This class is essentially a wrapper around [FingerprintNavigationStep] that will be used by
|
||||||
* fragments/viewmodels that want to consume these events. It should provide no additional
|
* fragments/viewmodels that want to consume these events. It should provide no additional
|
||||||
* functionality beyond what is available in [FingerprintNavigationStep].
|
* functionality beyond what is available in [FingerprintNavigationStep].
|
||||||
*/
|
*/
|
||||||
class FingerprintNavigationViewModel(
|
class FingerprintNavigationViewModel(fingerprintManagerInteractor: FingerprintManagerInteractor) :
|
||||||
step: UiStep,
|
ViewModel() {
|
||||||
hasConfirmedDeviceCredential: Boolean,
|
|
||||||
flowViewModel: FingerprintFlowViewModel,
|
|
||||||
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModel() {
|
|
||||||
|
|
||||||
private var _navStateInternal: MutableStateFlow<NavigationState?> = MutableStateFlow(null)
|
private val _flowInternal: MutableStateFlow<FingerprintFlow?> = MutableStateFlow(null)
|
||||||
|
private val _hasConfirmedDeviceCredential: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||||
|
private val _navStateInternal: StateFlow<NavigationState?> =
|
||||||
|
combine(
|
||||||
|
_flowInternal,
|
||||||
|
_hasConfirmedDeviceCredential,
|
||||||
|
fingerprintManagerInteractor.sensorPropertiesInternal,
|
||||||
|
) { flow, hasConfirmed, sensorType ->
|
||||||
|
if (flow == null || sensorType == null) {
|
||||||
|
return@combine null
|
||||||
|
}
|
||||||
|
return@combine NavigationState(flow, hasConfirmed, sensorType)
|
||||||
|
}
|
||||||
|
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
|
||||||
|
|
||||||
init {
|
private var _currentStep =
|
||||||
viewModelScope.launch {
|
MutableStateFlow<FingerprintNavigationStep?>(FingerprintNavigationStep.Init)
|
||||||
flowViewModel.fingerprintFlow
|
|
||||||
.combineTransform(fingerprintManagerInteractor.sensorPropertiesInternal) { flow, props ->
|
|
||||||
if (props?.sensorId != -1) {
|
|
||||||
emit(NavigationState(flow, hasConfirmedDeviceCredential, props))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.collect { navState -> _navStateInternal.update { navState } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _currentStep = MutableStateFlow<FingerprintNavigationStep?>(step)
|
|
||||||
|
|
||||||
private var _navigateTo: MutableStateFlow<UiStep?> = MutableStateFlow(null)
|
private var _navigateTo: MutableStateFlow<UiStep?> = MutableStateFlow(null)
|
||||||
val navigateTo: Flow<UiStep?> = _navigateTo.asStateFlow()
|
val navigateTo: Flow<UiStep?> = _navigateTo.asStateFlow()
|
||||||
@@ -85,6 +90,16 @@ class FingerprintNavigationViewModel(
|
|||||||
/** This indicates what screen should currently be presenting to the user. */
|
/** This indicates what screen should currently be presenting to the user. */
|
||||||
val currentScreen: Flow<UiStep?> = _currentScreen.asStateFlow()
|
val currentScreen: Flow<UiStep?> = _currentScreen.asStateFlow()
|
||||||
|
|
||||||
|
/** Updates the type of flow the navigation should begin */
|
||||||
|
fun updateFingerprintFlow(flow: FingerprintFlow) {
|
||||||
|
_flowInternal.update { flow }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Indicates if we have confirmed device credential */
|
||||||
|
fun hasConfirmedDeviceCredential(hasConfirmedDeviceCredential: Boolean) {
|
||||||
|
_hasConfirmedDeviceCredential.update { hasConfirmedDeviceCredential }
|
||||||
|
}
|
||||||
|
|
||||||
/** See [updateInternal] for more details */
|
/** See [updateInternal] for more details */
|
||||||
fun update(action: FingerprintAction, caller: KClass<*>, debugStr: String) {
|
fun update(action: FingerprintAction, caller: KClass<*>, debugStr: String) {
|
||||||
Log.d(TAG, "$caller.update($action) $debugStr")
|
Log.d(TAG, "$caller.update($action) $debugStr")
|
||||||
@@ -122,26 +137,15 @@ class FingerprintNavigationViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintNavigationViewModelFactory(
|
|
||||||
private val step: UiStep,
|
|
||||||
private val hasConfirmedDeviceCredential: Boolean,
|
|
||||||
private val flowViewModel: FingerprintFlowViewModel,
|
|
||||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
|
||||||
) : ViewModelProvider.Factory {
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintNavigationViewModel(
|
|
||||||
step,
|
|
||||||
hasConfirmedDeviceCredential,
|
|
||||||
flowViewModel,
|
|
||||||
fingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "FingerprintNavigationViewModel"
|
private const val TAG = "FingerprintNavigationViewModel"
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
|
initializer {
|
||||||
|
val settingsApplication =
|
||||||
|
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||||
|
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||||
|
FingerprintNavigationViewModel(biometricEnvironment!!.fingerprintManagerInteractor)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,8 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.viewmodel.initializer
|
||||||
|
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
@@ -36,11 +38,9 @@ class FingerprintScrollViewModel : ViewModel() {
|
|||||||
_hasReadConsentScreen.update { true }
|
_hasReadConsentScreen.update { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
class FingerprintScrollViewModelFactory : ViewModelProvider.Factory {
|
companion object {
|
||||||
|
val Factory: ViewModelProvider.Factory = viewModelFactory {
|
||||||
@Suppress("UNCHECKED_CAST")
|
initializer { FingerprintScrollViewModel() }
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return FingerprintScrollViewModel() as T
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,24 +18,15 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
|||||||
|
|
||||||
/** Indicates the type of transitions that can occur between fragments */
|
/** Indicates the type of transitions that can occur between fragments */
|
||||||
sealed class Transition {
|
sealed class Transition {
|
||||||
/**
|
/** Indicates the new fragment should slide in from the left side */
|
||||||
* Indicates the new fragment should slide in from the left side
|
|
||||||
*/
|
|
||||||
data object EnterFromLeft : Transition()
|
data object EnterFromLeft : Transition()
|
||||||
|
|
||||||
/**
|
/** Indicates the new fragment should slide in from the right side */
|
||||||
* Indicates the new fragment should slide in from the right side
|
|
||||||
*/
|
|
||||||
data object EnterFromRight : Transition()
|
data object EnterFromRight : Transition()
|
||||||
|
|
||||||
/**
|
/** Indicates the old fragment should slide out to the left side */
|
||||||
* Indicates the old fragment should slide out to the left side
|
|
||||||
*/
|
|
||||||
data object ExitToLeft : Transition()
|
data object ExitToLeft : Transition()
|
||||||
|
|
||||||
/**
|
/** Indicates the old fragment should slide out to the right side */
|
||||||
* Indicates the old fragment should slide out to the right side
|
|
||||||
*/
|
|
||||||
data object ExitToRight : Transition()
|
data object ExitToRight : Transition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -54,29 +54,40 @@ object FingerprintSettingsViewBinder {
|
|||||||
challenge: Long?,
|
challenge: Long?,
|
||||||
challengeToken: ByteArray?,
|
challengeToken: ByteArray?,
|
||||||
)
|
)
|
||||||
|
|
||||||
/** Helper to launch an add fingerprint request */
|
/** Helper to launch an add fingerprint request */
|
||||||
fun launchAddFingerprint(userId: Int, challengeToken: ByteArray?)
|
fun launchAddFingerprint(userId: Int, challengeToken: ByteArray?)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that will try and launch confirm lock, if that fails we will prompt user to
|
* Helper function that will try and launch confirm lock, if that fails we will prompt user to
|
||||||
* choose a PIN/PATTERN/PASS.
|
* choose a PIN/PATTERN/PASS.
|
||||||
*/
|
*/
|
||||||
fun launchConfirmOrChooseLock(userId: Int)
|
fun launchConfirmOrChooseLock(userId: Int)
|
||||||
|
|
||||||
/** Used to indicate that FingerprintSettings is finished. */
|
/** Used to indicate that FingerprintSettings is finished. */
|
||||||
fun finish()
|
fun finish()
|
||||||
|
|
||||||
/** Indicates what result should be set for the returning callee */
|
/** Indicates what result should be set for the returning callee */
|
||||||
fun setResultExternal(resultCode: Int)
|
fun setResultExternal(resultCode: Int)
|
||||||
|
|
||||||
/** Indicates the settings UI should be shown */
|
/** Indicates the settings UI should be shown */
|
||||||
fun showSettings(enrolledFingerprints: List<FingerprintData>)
|
fun showSettings(enrolledFingerprints: List<FingerprintData>)
|
||||||
|
|
||||||
/** Updates the add fingerprints preference */
|
/** Updates the add fingerprints preference */
|
||||||
fun updateAddFingerprintsPreference(canEnroll: Boolean, maxFingerprints: Int)
|
fun updateAddFingerprintsPreference(canEnroll: Boolean, maxFingerprints: Int)
|
||||||
|
|
||||||
/** Updates the sfps fingerprints preference */
|
/** Updates the sfps fingerprints preference */
|
||||||
fun updateSfpsPreference(isSfpsPrefVisible: Boolean)
|
fun updateSfpsPreference(isSfpsPrefVisible: Boolean)
|
||||||
|
|
||||||
/** Indicates that a user has been locked out */
|
/** Indicates that a user has been locked out */
|
||||||
fun userLockout(authAttemptViewModel: FingerprintAuthAttemptModel.Error)
|
fun userLockout(authAttemptViewModel: FingerprintAuthAttemptModel.Error)
|
||||||
|
|
||||||
/** Indicates a fingerprint preference should be highlighted */
|
/** Indicates a fingerprint preference should be highlighted */
|
||||||
suspend fun highlightPref(fingerId: Int)
|
suspend fun highlightPref(fingerId: Int)
|
||||||
|
|
||||||
/** Indicates a user should be prompted to delete a fingerprint */
|
/** Indicates a user should be prompted to delete a fingerprint */
|
||||||
suspend fun askUserToDeleteDialog(fingerprintViewModel: FingerprintData): Boolean
|
suspend fun askUserToDeleteDialog(fingerprintViewModel: FingerprintData): Boolean
|
||||||
|
|
||||||
/** Indicates a user should be asked to renae ma dialog */
|
/** Indicates a user should be asked to renae ma dialog */
|
||||||
suspend fun askUserToRenameDialog(
|
suspend fun askUserToRenameDialog(
|
||||||
fingerprintViewModel: FingerprintData
|
fingerprintViewModel: FingerprintData
|
||||||
|
@@ -45,14 +45,13 @@ import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
|
|||||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling
|
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling
|
||||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal
|
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
|
||||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepositoryImpl
|
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepositoryImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractorImpl
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractorImpl
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.Settings
|
import com.android.settings.biometrics.fingerprint2.lib.model.Settings
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.common.util.toFingerprintEnrollOptions
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.settings.binder.FingerprintSettingsViewBinder
|
import com.android.settings.biometrics.fingerprint2.ui.settings.binder.FingerprintSettingsViewBinder
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsNavigationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsNavigationViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsViewModel
|
||||||
@@ -227,7 +226,6 @@ class FingerprintSettingsV2Fragment :
|
|||||||
val fingerprintEnrollStateRepository =
|
val fingerprintEnrollStateRepository =
|
||||||
FingerprintEnrollInteractorImpl(
|
FingerprintEnrollInteractorImpl(
|
||||||
requireContext().applicationContext,
|
requireContext().applicationContext,
|
||||||
intent.toFingerprintEnrollOptions(),
|
|
||||||
fingerprintManager,
|
fingerprintManager,
|
||||||
Settings,
|
Settings,
|
||||||
)
|
)
|
||||||
|
@@ -52,7 +52,7 @@ class FingerprintSettingsNavigationViewModel(
|
|||||||
_nextStep.update { LaunchConfirmDeviceCredential(userId) }
|
_nextStep.update { LaunchConfirmDeviceCredential(userId) }
|
||||||
} else {
|
} else {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
if (fingerprintManagerInteractor.enrolledFingerprints.last().isEmpty()) {
|
if (fingerprintManagerInteractor.enrolledFingerprints.last()?.isEmpty() == true) {
|
||||||
_nextStep.update { EnrollFirstFingerprint(userId, null, challenge, token) }
|
_nextStep.update { EnrollFirstFingerprint(userId, null, challenge, token) }
|
||||||
} else {
|
} else {
|
||||||
showSettingsHelper()
|
showSettingsHelper()
|
||||||
@@ -149,7 +149,7 @@ class FingerprintSettingsNavigationViewModel(
|
|||||||
|
|
||||||
private suspend fun launchEnrollNextStep(gateKeeperPasswordHandle: Long?) {
|
private suspend fun launchEnrollNextStep(gateKeeperPasswordHandle: Long?) {
|
||||||
fingerprintManagerInteractor.enrolledFingerprints.collect {
|
fingerprintManagerInteractor.enrolledFingerprints.collect {
|
||||||
if (it.isEmpty()) {
|
if (it?.isEmpty() == true) {
|
||||||
_nextStep.update { EnrollFirstFingerprint(userId, gateKeeperPasswordHandle, null, null) }
|
_nextStep.update { EnrollFirstFingerprint(userId, gateKeeperPasswordHandle, null, null) }
|
||||||
} else {
|
} else {
|
||||||
viewModelScope.launch(backgroundDispatcher) {
|
viewModelScope.launch(backgroundDispatcher) {
|
||||||
|
@@ -74,7 +74,7 @@ class FingerprintSettingsViewModel(
|
|||||||
/** Represents the stream of visibility of sfps preference. */
|
/** Represents the stream of visibility of sfps preference. */
|
||||||
val isSfpsPrefVisible: Flow<Boolean> =
|
val isSfpsPrefVisible: Flow<Boolean> =
|
||||||
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().transform {
|
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().transform {
|
||||||
emit(fingerprintManagerInteractor.hasSideFps() && !it.isNullOrEmpty())
|
emit(fingerprintManagerInteractor.hasSideFps() == true && !it.isNullOrEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _isShowingDialog: MutableStateFlow<PreferenceViewModel?> = MutableStateFlow(null)
|
private val _isShowingDialog: MutableStateFlow<PreferenceViewModel?> = MutableStateFlow(null)
|
||||||
|
@@ -67,7 +67,6 @@ class FingerprintEnrollIntroFragmentTest {
|
|||||||
|
|
||||||
private val gatekeeperViewModel =
|
private val gatekeeperViewModel =
|
||||||
FingerprintGatekeeperViewModel(
|
FingerprintGatekeeperViewModel(
|
||||||
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
|
|
||||||
interactor
|
interactor
|
||||||
)
|
)
|
||||||
private val backgroundDispatcher = StandardTestDispatcher()
|
private val backgroundDispatcher = StandardTestDispatcher()
|
||||||
@@ -86,13 +85,10 @@ class FingerprintEnrollIntroFragmentTest {
|
|||||||
.toFingerprintSensor()
|
.toFingerprintSensor()
|
||||||
|
|
||||||
var enrollFlow = Default
|
var enrollFlow = Default
|
||||||
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
|
val flowViewModel = FingerprintFlowViewModel()
|
||||||
|
|
||||||
private val navigationViewModel =
|
private val navigationViewModel =
|
||||||
FingerprintNavigationViewModel(
|
FingerprintNavigationViewModel(
|
||||||
Introduction(),
|
|
||||||
false,
|
|
||||||
flowViewModel,
|
|
||||||
interactor
|
interactor
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -124,6 +120,11 @@ class FingerprintEnrollIntroFragmentTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gatekeeperViewModel.onConfirmDevice(true, 100L, false)
|
||||||
|
flowViewModel.updateFlowType(enrollFlow)
|
||||||
|
navigationViewModel.hasConfirmedDeviceCredential(true)
|
||||||
|
navigationViewModel.updateFingerprintFlow(enrollFlow)
|
||||||
|
|
||||||
fragmentScenario =
|
fragmentScenario =
|
||||||
launchFragmentInContainer(Bundle(), R.style.SudThemeGlif) {
|
launchFragmentInContainer(Bundle(), R.style.SudThemeGlif) {
|
||||||
FingerprintEnrollIntroV2Fragment(factory)
|
FingerprintEnrollIntroV2Fragment(factory)
|
||||||
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
@@ -42,7 +42,6 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
|
|||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
|
||||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -95,23 +94,27 @@ class Injector(step: FingerprintNavigationStep.UiStep) {
|
|||||||
|
|
||||||
override fun getRotationFromDefault(rotation: Int): Int = rotation
|
override fun getRotationFromDefault(rotation: Int): Int = rotation
|
||||||
}
|
}
|
||||||
var gatekeeperViewModel =
|
var gatekeeperViewModel = FingerprintGatekeeperViewModel(fingerprintManagerInteractor)
|
||||||
FingerprintGatekeeperViewModel(
|
|
||||||
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
|
|
||||||
interactor,
|
|
||||||
)
|
|
||||||
|
|
||||||
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
|
val flowViewModel = FingerprintFlowViewModel()
|
||||||
|
|
||||||
var navigationViewModel = FingerprintNavigationViewModel(step, true, flowViewModel, interactor)
|
var navigationViewModel = FingerprintNavigationViewModel(fingerprintManagerInteractor)
|
||||||
var fingerprintViewModel =
|
var fingerprintViewModel =
|
||||||
FingerprintEnrollIntroViewModel(navigationViewModel, flowViewModel, interactor)
|
FingerprintEnrollIntroViewModel(
|
||||||
|
navigationViewModel,
|
||||||
|
flowViewModel,
|
||||||
|
fingerprintManagerInteractor,
|
||||||
|
)
|
||||||
|
|
||||||
var fingerprintScrollViewModel = FingerprintScrollViewModel()
|
var fingerprintScrollViewModel = FingerprintScrollViewModel()
|
||||||
var backgroundViewModel = BackgroundViewModel()
|
var backgroundViewModel = BackgroundViewModel()
|
||||||
|
|
||||||
var fingerprintEnrollViewModel =
|
var fingerprintEnrollViewModel =
|
||||||
FingerprintEnrollViewModel(interactor, gatekeeperViewModel, navigationViewModel)
|
FingerprintEnrollViewModel(
|
||||||
|
fingerprintManagerInteractor,
|
||||||
|
gatekeeperViewModel,
|
||||||
|
navigationViewModel,
|
||||||
|
)
|
||||||
|
|
||||||
var fingerprintEnrollEnrollingViewModel =
|
var fingerprintEnrollEnrollingViewModel =
|
||||||
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
||||||
@@ -122,11 +125,11 @@ class Injector(step: FingerprintNavigationStep.UiStep) {
|
|||||||
fingerprintEnrollEnrollingViewModel,
|
fingerprintEnrollEnrollingViewModel,
|
||||||
navigationViewModel,
|
navigationViewModel,
|
||||||
orientationInteractor,
|
orientationInteractor,
|
||||||
interactor,
|
fingerprintManagerInteractor,
|
||||||
)
|
)
|
||||||
|
|
||||||
val fingerprintEnrollConfirmationViewModel =
|
val fingerprintEnrollConfirmationViewModel =
|
||||||
FingerprintEnrollConfirmationViewModel(navigationViewModel, interactor)
|
FingerprintEnrollConfirmationViewModel(navigationViewModel, fingerprintManagerInteractor)
|
||||||
|
|
||||||
var fingerprintFindSensorViewModel =
|
var fingerprintFindSensorViewModel =
|
||||||
FingerprintEnrollFindSensorViewModel(
|
FingerprintEnrollFindSensorViewModel(
|
||||||
@@ -134,11 +137,11 @@ class Injector(step: FingerprintNavigationStep.UiStep) {
|
|||||||
fingerprintEnrollViewModel,
|
fingerprintEnrollViewModel,
|
||||||
gatekeeperViewModel,
|
gatekeeperViewModel,
|
||||||
backgroundViewModel,
|
backgroundViewModel,
|
||||||
|
flowViewModel,
|
||||||
accessibilityInteractor,
|
accessibilityInteractor,
|
||||||
foldStateInteractor,
|
foldStateInteractor,
|
||||||
orientationInteractor,
|
orientationInteractor,
|
||||||
flowViewModel,
|
fingerprintManagerInteractor,
|
||||||
interactor,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
val factory =
|
val factory =
|
||||||
@@ -166,12 +169,16 @@ class Injector(step: FingerprintNavigationStep.UiStep) {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
fingerprintEnrollViewModel.sensorTypeCached = fingerprintSensor.sensorType
|
fingerprintEnrollViewModel.sensorTypeCached = fingerprintSensor.sensorType
|
||||||
|
gatekeeperViewModel.onConfirmDevice(true, 100L)
|
||||||
|
navigationViewModel.updateFingerprintFlow(enrollFlow)
|
||||||
|
navigationViewModel.hasConfirmedDeviceCredential(true)
|
||||||
|
flowViewModel.updateFlowType(enrollFlow)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val Phone = DisplaySpec("phone", width = 1080, height = 2340, densityDpi = 420)
|
private val Phone = DisplaySpec("phone", width = 1080, height = 2340, densityDpi = 420)
|
||||||
private const val screenshotPath = "/settings_screenshots"
|
private const val screenshotPath = "/settings_screenshots"
|
||||||
val interactor = FakeFingerprintManagerInteractor()
|
val fingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
||||||
|
|
||||||
fun BiometricFragmentScreenShotRule() =
|
fun BiometricFragmentScreenShotRule() =
|
||||||
FragmentScreenshotTestRule(
|
FragmentScreenshotTestRule(
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
package com.android.settings.tests.screenshot.biometrics.fingerprint.fragment
|
package com.android.settings.tests.screenshot.biometrics.fingerprint.fragment
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
||||||
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector
|
import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector
|
||||||
@@ -28,17 +27,15 @@ import platform.test.screenshot.FragmentScreenshotTestRule
|
|||||||
import platform.test.screenshot.ViewScreenshotTestRule.Mode
|
import platform.test.screenshot.ViewScreenshotTestRule.Mode
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class FingerprintEnrollConfirmationScreenshotTest {
|
class RfpsEnrollConfirmationScreenshotTest {
|
||||||
private val injector: Injector = Injector(FingerprintNavigationStep.Confirmation)
|
private val injector: Injector = Injector(FingerprintNavigationStep.Confirmation)
|
||||||
|
|
||||||
@Rule
|
@Rule @JvmField var rule: FragmentScreenshotTestRule = Injector.BiometricFragmentScreenShotRule()
|
||||||
@JvmField
|
|
||||||
var rule: FragmentScreenshotTestRule = Injector.BiometricFragmentScreenShotRule()
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testConfirmation() {
|
fun testConfirmation() {
|
||||||
rule.screenshotTest(
|
rule.screenshotTest(
|
||||||
"fp_enroll_confirmation",
|
"rfps_enroll_confirmation",
|
||||||
Mode.MatchSize,
|
Mode.MatchSize,
|
||||||
FingerprintEnrollConfirmationV2Fragment(injector.factory),
|
FingerprintEnrollConfirmationV2Fragment(injector.factory),
|
||||||
)
|
)
|
@@ -27,14 +27,14 @@ import platform.test.screenshot.FragmentScreenshotTestRule
|
|||||||
import platform.test.screenshot.ViewScreenshotTestRule.Mode
|
import platform.test.screenshot.ViewScreenshotTestRule.Mode
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class FingerprintEnrollEnrollingScreenshotTest {
|
class RfpsEnrollEnrollingScreenshotTest {
|
||||||
private val injector: Injector =
|
private val injector: Injector =
|
||||||
Injector(FingerprintNavigationStep.Enrollment(Injector.interactor.sensorProp))
|
Injector(FingerprintNavigationStep.Enrollment(Injector.fingerprintManagerInteractor.sensorProp))
|
||||||
|
|
||||||
@Rule @JvmField var rule: FragmentScreenshotTestRule = BiometricFragmentScreenShotRule()
|
@Rule @JvmField var rule: FragmentScreenshotTestRule = BiometricFragmentScreenShotRule()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEnrollEnrolling() {
|
fun testEnrollEnrolling() {
|
||||||
rule.screenshotTest("fp_enroll_enrolling", Mode.MatchSize, RFPSEnrollFragment(injector.factory))
|
rule.screenshotTest("rfps_enroll_enrolling", Mode.MatchSize, RFPSEnrollFragment(injector.factory))
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -31,10 +31,6 @@ class RfpsEnrollFindSensorScreenshotTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEnrollFindSensor() {
|
fun testEnrollFindSensor() {
|
||||||
rule.screenshotTest(
|
rule.screenshotTest("rfps_enroll_find_sensor", Mode.MatchSize, RfpsEnrollFindSensorFragment())
|
||||||
"fp_enroll_find_sensor",
|
|
||||||
Mode.MatchSize,
|
|
||||||
RfpsEnrollFindSensorFragment(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,17 +27,15 @@ import platform.test.screenshot.FragmentScreenshotTestRule
|
|||||||
import platform.test.screenshot.ViewScreenshotTestRule.Mode
|
import platform.test.screenshot.ViewScreenshotTestRule.Mode
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class FingerprintEnrollIntroScreenshotTest {
|
class RfpsEnrollIntroScreenshotTest {
|
||||||
private val injector: Injector = Injector(FingerprintNavigationStep.Introduction())
|
private val injector: Injector = Injector(FingerprintNavigationStep.Introduction())
|
||||||
|
|
||||||
@Rule
|
@Rule @JvmField var rule: FragmentScreenshotTestRule = Injector.BiometricFragmentScreenShotRule()
|
||||||
@JvmField
|
|
||||||
var rule: FragmentScreenshotTestRule = Injector.BiometricFragmentScreenShotRule()
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEnrollIntro() {
|
fun testEnrollIntro() {
|
||||||
rule.screenshotTest(
|
rule.screenshotTest(
|
||||||
"fp_enroll_intro",
|
"rfps_enroll_intro",
|
||||||
Mode.MatchSize,
|
Mode.MatchSize,
|
||||||
FingerprintEnrollIntroV2Fragment(injector.factory),
|
FingerprintEnrollIntroV2Fragment(injector.factory),
|
||||||
)
|
)
|
@@ -19,6 +19,7 @@ package com.android.settings.testutils2
|
|||||||
import android.hardware.biometrics.ComponentInfoInternal
|
import android.hardware.biometrics.ComponentInfoInternal
|
||||||
import android.hardware.biometrics.SensorLocationInternal
|
import android.hardware.biometrics.SensorLocationInternal
|
||||||
import android.hardware.biometrics.SensorProperties
|
import android.hardware.biometrics.SensorProperties
|
||||||
|
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||||
@@ -78,6 +79,7 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
|||||||
override suspend fun enroll(
|
override suspend fun enroll(
|
||||||
hardwareAuthToken: ByteArray?,
|
hardwareAuthToken: ByteArray?,
|
||||||
enrollReason: EnrollReason,
|
enrollReason: EnrollReason,
|
||||||
|
fingerprintEnrollOptions: FingerprintEnrollOptions
|
||||||
): Flow<FingerEnrollState> = flowOf(*enrollStateViewModel.toTypedArray())
|
): Flow<FingerEnrollState> = flowOf(*enrollStateViewModel.toTypedArray())
|
||||||
|
|
||||||
override suspend fun removeFingerprint(fp: FingerprintData): Boolean {
|
override suspend fun removeFingerprint(fp: FingerprintData): Boolean {
|
||||||
|
@@ -109,12 +109,7 @@ class FingerprintManagerInteractorTest {
|
|||||||
fingerprintManager,
|
fingerprintManager,
|
||||||
fingerprintSensorRepository,
|
fingerprintSensorRepository,
|
||||||
gateKeeperPasswordProvider,
|
gateKeeperPasswordProvider,
|
||||||
FingerprintEnrollInteractorImpl(
|
FingerprintEnrollInteractorImpl(context, fingerprintManager, Default),
|
||||||
context,
|
|
||||||
FingerprintEnrollOptions.Builder().build(),
|
|
||||||
fingerprintManager,
|
|
||||||
Default,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +130,7 @@ class FingerprintManagerInteractorTest {
|
|||||||
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
|
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
|
||||||
|
|
||||||
val list = underTest.enrolledFingerprints.last()
|
val list = underTest.enrolledFingerprints.last()
|
||||||
assertThat(list.size).isEqualTo(fingerprintList.size)
|
assertThat(list!!.size).isEqualTo(fingerprintList.size)
|
||||||
val actual = list[0]
|
val actual = list[0]
|
||||||
assertThat(actual.name).isEqualTo(expected.name)
|
assertThat(actual.name).isEqualTo(expected.name)
|
||||||
assertThat(actual.fingerId).isEqualTo(expected.biometricId)
|
assertThat(actual.fingerId).isEqualTo(expected.biometricId)
|
||||||
@@ -318,7 +313,11 @@ class FingerprintManagerInteractorTest {
|
|||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
val token = byteArrayOf(5, 3, 2)
|
val token = byteArrayOf(5, 3, 2)
|
||||||
var result: FingerEnrollState? = null
|
var result: FingerEnrollState? = null
|
||||||
val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
|
val job = launch {
|
||||||
|
underTest
|
||||||
|
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
|
||||||
|
.collect { result = it }
|
||||||
|
}
|
||||||
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
||||||
runCurrent()
|
runCurrent()
|
||||||
|
|
||||||
@@ -343,7 +342,11 @@ class FingerprintManagerInteractorTest {
|
|||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
val token = byteArrayOf(5, 3, 2)
|
val token = byteArrayOf(5, 3, 2)
|
||||||
var result: FingerEnrollState? = null
|
var result: FingerEnrollState? = null
|
||||||
val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
|
val job = launch {
|
||||||
|
underTest
|
||||||
|
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
|
||||||
|
.collect { result = it }
|
||||||
|
}
|
||||||
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
||||||
runCurrent()
|
runCurrent()
|
||||||
|
|
||||||
@@ -368,7 +371,11 @@ class FingerprintManagerInteractorTest {
|
|||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
val token = byteArrayOf(5, 3, 2)
|
val token = byteArrayOf(5, 3, 2)
|
||||||
var result: FingerEnrollState? = null
|
var result: FingerEnrollState? = null
|
||||||
val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
|
val job = launch {
|
||||||
|
underTest
|
||||||
|
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
|
||||||
|
.collect { result = it }
|
||||||
|
}
|
||||||
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
||||||
runCurrent()
|
runCurrent()
|
||||||
|
|
||||||
|
@@ -35,7 +35,6 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
|
|||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||||
@@ -90,45 +89,20 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
|||||||
Dispatchers.setMain(backgroundDispatcher)
|
Dispatchers.setMain(backgroundDispatcher)
|
||||||
|
|
||||||
fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
||||||
gatekeeperViewModel =
|
gatekeeperViewModel = FingerprintGatekeeperViewModel(fakeFingerprintManagerInteractor)
|
||||||
FingerprintGatekeeperViewModel.FingerprintGatekeeperViewModelFactory(
|
|
||||||
null,
|
|
||||||
fakeFingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
.create(FingerprintGatekeeperViewModel::class.java)
|
|
||||||
|
|
||||||
val sensor =
|
val fingerprintFlowViewModel = FingerprintFlowViewModel()
|
||||||
FingerprintSensorPropertiesInternal(
|
fingerprintFlowViewModel.updateFlowType(Default)
|
||||||
0 /* sensorId */,
|
navigationViewModel = FingerprintNavigationViewModel(fakeFingerprintManagerInteractor)
|
||||||
SensorProperties.STRENGTH_STRONG,
|
|
||||||
5 /* maxEnrollmentsPerUser */,
|
|
||||||
listOf<ComponentInfoInternal>(),
|
|
||||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
|
||||||
false /* halControlsIllumination */,
|
|
||||||
true /* resetLockoutRequiresHardwareAuthToken */,
|
|
||||||
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
|
|
||||||
)
|
|
||||||
.toFingerprintSensor()
|
|
||||||
|
|
||||||
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
|
backgroundViewModel = BackgroundViewModel()
|
||||||
navigationViewModel =
|
|
||||||
FingerprintNavigationViewModel(
|
|
||||||
FingerprintNavigationStep.Education(sensor),
|
|
||||||
false,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fakeFingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
|
|
||||||
backgroundViewModel =
|
|
||||||
BackgroundViewModel.BackgroundViewModelFactory().create(BackgroundViewModel::class.java)
|
|
||||||
backgroundViewModel.inForeground()
|
backgroundViewModel.inForeground()
|
||||||
enrollViewModel =
|
enrollViewModel =
|
||||||
FingerprintEnrollViewModel.FingerprintEnrollViewModelFactory(
|
FingerprintEnrollViewModel(
|
||||||
fakeFingerprintManagerInteractor,
|
fakeFingerprintManagerInteractor,
|
||||||
gatekeeperViewModel,
|
gatekeeperViewModel,
|
||||||
navigationViewModel,
|
navigationViewModel,
|
||||||
)
|
)
|
||||||
.create(FingerprintEnrollViewModel::class.java)
|
|
||||||
accessibilityInteractor =
|
accessibilityInteractor =
|
||||||
object : AccessibilityInteractor {
|
object : AccessibilityInteractor {
|
||||||
override val isAccessibilityEnabled: Flow<Boolean> = flowOf(false)
|
override val isAccessibilityEnabled: Flow<Boolean> = flowOf(false)
|
||||||
@@ -147,21 +121,21 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
|||||||
override val orientation: Flow<Int> = flowOf(Configuration.ORIENTATION_LANDSCAPE)
|
override val orientation: Flow<Int> = flowOf(Configuration.ORIENTATION_LANDSCAPE)
|
||||||
override val rotation: Flow<Int> = flowOf(Surface.ROTATION_0)
|
override val rotation: Flow<Int> = flowOf(Surface.ROTATION_0)
|
||||||
override val rotationFromDefault: Flow<Int> = flowOf(Surface.ROTATION_0)
|
override val rotationFromDefault: Flow<Int> = flowOf(Surface.ROTATION_0)
|
||||||
|
|
||||||
override fun getRotationFromDefault(rotation: Int): Int = rotation
|
override fun getRotationFromDefault(rotation: Int): Int = rotation
|
||||||
}
|
}
|
||||||
underTest =
|
underTest =
|
||||||
FingerprintEnrollFindSensorViewModel.FingerprintEnrollFindSensorViewModelFactory(
|
FingerprintEnrollFindSensorViewModel(
|
||||||
navigationViewModel,
|
navigationViewModel,
|
||||||
enrollViewModel,
|
enrollViewModel,
|
||||||
gatekeeperViewModel,
|
gatekeeperViewModel,
|
||||||
backgroundViewModel,
|
backgroundViewModel,
|
||||||
|
fingerprintFlowViewModel,
|
||||||
accessibilityInteractor,
|
accessibilityInteractor,
|
||||||
foldStateInteractor,
|
foldStateInteractor,
|
||||||
orientationInteractor,
|
orientationInteractor,
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fakeFingerprintManagerInteractor,
|
fakeFingerprintManagerInteractor,
|
||||||
)
|
)
|
||||||
.create(FingerprintEnrollFindSensorViewModel::class.java)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@@ -23,22 +23,23 @@ import android.hardware.fingerprint.FingerprintSensorProperties
|
|||||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintAction
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
|
||||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
|
||||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
|
||||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.TestScope
|
import kotlinx.coroutines.test.TestScope
|
||||||
import kotlinx.coroutines.test.advanceUntilIdle
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.runCurrent
|
import kotlinx.coroutines.test.resetMain
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import kotlinx.coroutines.test.setMain
|
||||||
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -53,28 +54,52 @@ class FingerprintEnrollConfirmationViewModelTest {
|
|||||||
@get:Rule val instantTaskRule = InstantTaskExecutorRule()
|
@get:Rule val instantTaskRule = InstantTaskExecutorRule()
|
||||||
private var backgroundDispatcher = StandardTestDispatcher()
|
private var backgroundDispatcher = StandardTestDispatcher()
|
||||||
private var testScope = TestScope(backgroundDispatcher)
|
private var testScope = TestScope(backgroundDispatcher)
|
||||||
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
|
val fingerprintFlowViewModel = FingerprintFlowViewModel()
|
||||||
val fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
val fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
||||||
lateinit var navigationViewModel: FingerprintNavigationViewModel
|
lateinit var navigationViewModel: FingerprintNavigationViewModel
|
||||||
lateinit var underTest: FingerprintEnrollConfirmationViewModel
|
lateinit var underTest: FingerprintEnrollConfirmationViewModel
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
navigationViewModel =
|
Dispatchers.setMain(backgroundDispatcher)
|
||||||
FingerprintNavigationViewModel(
|
fingerprintFlowViewModel.updateFlowType(Default)
|
||||||
FingerprintNavigationStep.Confirmation,
|
navigationViewModel = FingerprintNavigationViewModel(fakeFingerprintManagerInteractor)
|
||||||
false,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fakeFingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
underTest =
|
underTest =
|
||||||
FingerprintEnrollConfirmationViewModel(navigationViewModel, fakeFingerprintManagerInteractor)
|
FingerprintEnrollConfirmationViewModel(navigationViewModel, fakeFingerprintManagerInteractor)
|
||||||
|
navigationViewModel.updateFingerprintFlow(Default)
|
||||||
|
navigationViewModel.hasConfirmedDeviceCredential(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
Dispatchers.resetMain()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun bringToConfirmation() {
|
||||||
|
navigationViewModel.update(
|
||||||
|
FingerprintAction.NEXT,
|
||||||
|
FingerprintNavigationStep.Introduction::class,
|
||||||
|
"Intro.Test.NEXT",
|
||||||
|
)
|
||||||
|
navigationViewModel.update(
|
||||||
|
FingerprintAction.NEXT,
|
||||||
|
FingerprintNavigationStep.Education::class,
|
||||||
|
"Edu.Test.NEXT",
|
||||||
|
)
|
||||||
|
navigationViewModel.update(
|
||||||
|
FingerprintAction.NEXT,
|
||||||
|
FingerprintNavigationStep.Enrollment::class,
|
||||||
|
"Enrollment.Test.NEXT",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCanEnrollFingerprints() =
|
fun testCanEnrollFingerprints() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
fakeFingerprintManagerInteractor.sensorProp = FingerprintSensorPropertiesInternal(
|
advanceUntilIdle()
|
||||||
|
bringToConfirmation()
|
||||||
|
fakeFingerprintManagerInteractor.sensorProp =
|
||||||
|
FingerprintSensorPropertiesInternal(
|
||||||
0 /* sensorId */,
|
0 /* sensorId */,
|
||||||
SensorProperties.STRENGTH_STRONG,
|
SensorProperties.STRENGTH_STRONG,
|
||||||
5 /* maxEnrollmentsPerUser */,
|
5 /* maxEnrollmentsPerUser */,
|
||||||
@@ -90,7 +115,9 @@ class FingerprintEnrollConfirmationViewModelTest {
|
|||||||
fakeFingerprintManagerInteractor.enrollableFingerprints = 5
|
fakeFingerprintManagerInteractor.enrollableFingerprints = 5
|
||||||
|
|
||||||
var canEnrollFingerprints: Boolean = false
|
var canEnrollFingerprints: Boolean = false
|
||||||
val job = launch { underTest.isAddAnotherButtonVisible.collect { canEnrollFingerprints = it } }
|
val job = launch {
|
||||||
|
underTest.isAddAnotherButtonVisible.collect { canEnrollFingerprints = it }
|
||||||
|
}
|
||||||
|
|
||||||
advanceUntilIdle()
|
advanceUntilIdle()
|
||||||
assertThat(canEnrollFingerprints).isTrue()
|
assertThat(canEnrollFingerprints).isTrue()
|
||||||
@@ -100,12 +127,14 @@ class FingerprintEnrollConfirmationViewModelTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testNextButtonSendsNextStep() =
|
fun testNextButtonSendsNextStep() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
|
advanceUntilIdle()
|
||||||
|
bringToConfirmation()
|
||||||
var step: FingerprintNavigationStep.UiStep? = null
|
var step: FingerprintNavigationStep.UiStep? = null
|
||||||
val job = launch { navigationViewModel.navigateTo.collect { step = it } }
|
val job = launch { navigationViewModel.navigateTo.collect { step = it } }
|
||||||
|
|
||||||
underTest.onNextButtonClicked()
|
underTest.onNextButtonClicked()
|
||||||
|
|
||||||
runCurrent()
|
advanceUntilIdle()
|
||||||
|
|
||||||
assertThat(step).isNull()
|
assertThat(step).isNull()
|
||||||
job.cancel()
|
job.cancel()
|
||||||
@@ -114,14 +143,18 @@ class FingerprintEnrollConfirmationViewModelTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testAddAnotherSendsAction() =
|
fun testAddAnotherSendsAction() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
|
advanceUntilIdle()
|
||||||
|
bringToConfirmation()
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
var step: FingerprintNavigationStep.UiStep? = null
|
var step: FingerprintNavigationStep.UiStep? = null
|
||||||
val job = launch { navigationViewModel.navigateTo.collect { step = it } }
|
val job = launch { navigationViewModel.navigateTo.collect { step = it } }
|
||||||
|
|
||||||
underTest.onAddAnotherButtonClicked()
|
underTest.onAddAnotherButtonClicked()
|
||||||
|
|
||||||
runCurrent()
|
advanceUntilIdle()
|
||||||
|
|
||||||
assertThat(step).isInstanceOf(FingerprintNavigationStep.Enrollment::class.java)
|
assertThat(step).isNull()
|
||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,9 +28,7 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Fing
|
|||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
|
||||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
@@ -61,20 +59,15 @@ class FingerprintEnrollEnrollingViewModelTest {
|
|||||||
private lateinit var backgroundViewModel: BackgroundViewModel
|
private lateinit var backgroundViewModel: BackgroundViewModel
|
||||||
private lateinit var gateKeeperViewModel: FingerprintGatekeeperViewModel
|
private lateinit var gateKeeperViewModel: FingerprintGatekeeperViewModel
|
||||||
private lateinit var navigationViewModel: FingerprintNavigationViewModel
|
private lateinit var navigationViewModel: FingerprintNavigationViewModel
|
||||||
private val defaultGatekeeperInfo = GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 3), 3)
|
|
||||||
private var testScope = TestScope(backgroundDispatcher)
|
private var testScope = TestScope(backgroundDispatcher)
|
||||||
|
|
||||||
private lateinit var fakeFingerprintManagerInteractor: FakeFingerprintManagerInteractor
|
private lateinit var fakeFingerprintManagerInteractor: FakeFingerprintManagerInteractor
|
||||||
|
|
||||||
private fun initialize(gatekeeperInfo: GatekeeperInfo = defaultGatekeeperInfo) {
|
private fun initialize() {
|
||||||
fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
|
||||||
gateKeeperViewModel =
|
|
||||||
FingerprintGatekeeperViewModel.FingerprintGatekeeperViewModelFactory(
|
gateKeeperViewModel = FingerprintGatekeeperViewModel(fakeFingerprintManagerInteractor)
|
||||||
gatekeeperInfo,
|
fakeFingerprintManagerInteractor.sensorProp =
|
||||||
fakeFingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
.create(FingerprintGatekeeperViewModel::class.java)
|
|
||||||
val sensor =
|
|
||||||
FingerprintSensorPropertiesInternal(
|
FingerprintSensorPropertiesInternal(
|
||||||
1 /* sensorId */,
|
1 /* sensorId */,
|
||||||
SensorProperties.STRENGTH_STRONG,
|
SensorProperties.STRENGTH_STRONG,
|
||||||
@@ -86,32 +79,21 @@ class FingerprintEnrollEnrollingViewModelTest {
|
|||||||
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
|
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
|
||||||
)
|
)
|
||||||
.toFingerprintSensor()
|
.toFingerprintSensor()
|
||||||
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
|
val fingerprintFlowViewModel = FingerprintFlowViewModel()
|
||||||
|
fingerprintFlowViewModel.updateFlowType(Default)
|
||||||
|
|
||||||
navigationViewModel =
|
navigationViewModel = FingerprintNavigationViewModel(fakeFingerprintManagerInteractor)
|
||||||
FingerprintNavigationViewModel(
|
|
||||||
Enrollment(sensor),
|
|
||||||
false,
|
|
||||||
fingerprintFlowViewModel,
|
|
||||||
fakeFingerprintManagerInteractor,
|
|
||||||
)
|
|
||||||
|
|
||||||
backgroundViewModel =
|
backgroundViewModel = BackgroundViewModel()
|
||||||
BackgroundViewModel.BackgroundViewModelFactory().create(BackgroundViewModel::class.java)
|
|
||||||
backgroundViewModel.inForeground()
|
backgroundViewModel.inForeground()
|
||||||
val fingerprintEnrollViewModel =
|
val fingerprintEnrollViewModel =
|
||||||
FingerprintEnrollViewModel.FingerprintEnrollViewModelFactory(
|
FingerprintEnrollViewModel(
|
||||||
fakeFingerprintManagerInteractor,
|
fakeFingerprintManagerInteractor,
|
||||||
gateKeeperViewModel,
|
gateKeeperViewModel,
|
||||||
navigationViewModel,
|
navigationViewModel,
|
||||||
)
|
)
|
||||||
.create(FingerprintEnrollViewModel::class.java)
|
|
||||||
enrollEnrollingViewModel =
|
enrollEnrollingViewModel =
|
||||||
FingerprintEnrollEnrollingViewModel.FingerprintEnrollEnrollingViewModelFactory(
|
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
||||||
fingerprintEnrollViewModel,
|
|
||||||
backgroundViewModel,
|
|
||||||
)
|
|
||||||
.create(FingerprintEnrollEnrollingViewModel::class.java)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -128,6 +110,7 @@ class FingerprintEnrollEnrollingViewModelTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testEnrollShouldBeFalse() =
|
fun testEnrollShouldBeFalse() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
|
gateKeeperViewModel.onConfirmDevice(true, 3L, false)
|
||||||
var shouldEnroll = false
|
var shouldEnroll = false
|
||||||
|
|
||||||
val job = launch {
|
val job = launch {
|
||||||
@@ -147,6 +130,7 @@ class FingerprintEnrollEnrollingViewModelTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testEnrollShouldBeFalseWhenBackground() =
|
fun testEnrollShouldBeFalseWhenBackground() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
|
gateKeeperViewModel.onConfirmDevice(true, 3L, false)
|
||||||
var shouldEnroll = false
|
var shouldEnroll = false
|
||||||
|
|
||||||
val job = launch {
|
val job = launch {
|
||||||
|