Merge "Added UI tests for FingerprintEnrollIntro" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
c320afa70d
@@ -17,9 +17,8 @@
|
|||||||
|
|
||||||
<com.google.android.setupdesign.GlifLayout
|
<com.google.android.setupdesign.GlifLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
style="?attr/fingerprint_layout_theme"
|
|
||||||
android:id="@+id/setup_wizard_layout"
|
android:id="@+id/setup_wizard_layout"
|
||||||
|
style="?attr/fingerprint_layout_theme"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@@ -58,9 +57,9 @@ android:layout_height="match_parent">
|
|||||||
|
|
||||||
<!-- How it works -->
|
<!-- How it works -->
|
||||||
<TextView
|
<TextView
|
||||||
|
style="@style/BiometricEnrollIntroTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/BiometricEnrollIntroTitle"
|
|
||||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />
|
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -74,14 +73,16 @@ android:layout_height="match_parent">
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_fingerprint_24dp" />
|
android:src="@drawable/ic_fingerprint_24dp" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_message_2"
|
android:id="@+id/footer_message_2"
|
||||||
|
style="@style/BiometricEnrollIntroMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
style="@style/BiometricEnrollIntroMessage" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -95,22 +96,24 @@ android:layout_height="match_parent">
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_lock_24dp" />
|
android:src="@drawable/ic_lock_24dp" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_message_3"
|
android:id="@+id/footer_message_3"
|
||||||
|
style="@style/BiometricEnrollIntroMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
style="@style/BiometricEnrollIntroMessage" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- You're in control -->
|
<!-- You're in control -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_title_1"
|
android:id="@+id/footer_title_1"
|
||||||
|
style="@style/BiometricEnrollIntroTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
style="@style/BiometricEnrollIntroTitle" />
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -123,22 +126,24 @@ android:layout_height="match_parent">
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_trash_can" />
|
android:src="@drawable/ic_trash_can" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_message_4"
|
android:id="@+id/footer_message_4"
|
||||||
|
style="@style/BiometricEnrollIntroMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
style="@style/BiometricEnrollIntroMessage" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<!-- Keep in mind -->
|
<!-- Keep in mind -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_title_2"
|
android:id="@+id/footer_title_2"
|
||||||
|
style="@style/BiometricEnrollIntroTitle"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/BiometricEnrollIntroTitle"
|
|
||||||
android:text="@string/security_settings_face_enroll_introduction_info_title" />
|
android:text="@string/security_settings_face_enroll_introduction_info_title" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -152,14 +157,16 @@ android:layout_height="match_parent">
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_info_outline_24dp" />
|
android:src="@drawable/ic_info_outline_24dp" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_message_5"
|
android:id="@+id/footer_message_5"
|
||||||
|
style="@style/BiometricEnrollIntroMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
style="@style/BiometricEnrollIntroMessage" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -173,14 +180,16 @@ android:layout_height="match_parent">
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_guarantee" />
|
android:src="@drawable/ic_guarantee" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_message_6"
|
android:id="@+id/footer_message_6"
|
||||||
|
style="@style/BiometricEnrollIntroMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content" />
|
||||||
style="@style/BiometricEnrollIntroMessage" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -194,15 +203,17 @@ android:layout_height="match_parent">
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
android:src="@drawable/ic_link_24dp" />
|
android:src="@drawable/ic_link_24dp" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="16dp"
|
android:layout_width="16dp"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/footer_learn_more"
|
android:id="@+id/footer_learn_more"
|
||||||
android:linksClickable="true"
|
style="@style/BiometricEnrollIntroMessage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/BiometricEnrollIntroMessage"
|
android:linksClickable="true"
|
||||||
android:paddingBottom="0dp"
|
android:paddingBottom="0dp"
|
||||||
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
|
android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@@ -42,6 +42,7 @@ 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.GatekeeperPasswordProvider
|
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||||
|
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||||
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
|
||||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollFindSensorV2Fragment
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollFindSensorV2Fragment
|
||||||
@@ -82,6 +83,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
|||||||
private lateinit var accessibilityViewModel: AccessibilityViewModel
|
private lateinit var accessibilityViewModel: AccessibilityViewModel
|
||||||
private lateinit var foldStateViewModel: FoldStateViewModel
|
private lateinit var foldStateViewModel: FoldStateViewModel
|
||||||
private lateinit var orientationStateViewModel: OrientationStateViewModel
|
private lateinit var orientationStateViewModel: OrientationStateViewModel
|
||||||
|
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
|
||||||
private val coroutineDispatcher = Dispatchers.Default
|
private val coroutineDispatcher = Dispatchers.Default
|
||||||
|
|
||||||
/** Result listener for ChooseLock activity flow. */
|
/** Result listener for ChooseLock activity flow. */
|
||||||
@@ -210,6 +212,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
|||||||
)[FingerprintEnrollViewModel::class.java]
|
)[FingerprintEnrollViewModel::class.java]
|
||||||
|
|
||||||
// Initialize scroll view model
|
// Initialize scroll view model
|
||||||
|
fingerprintScrollViewModel =
|
||||||
ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
|
ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
|
||||||
FingerprintScrollViewModel::class.java]
|
FingerprintScrollViewModel::class.java]
|
||||||
|
|
||||||
|
@@ -25,10 +25,13 @@ import android.os.Bundle
|
|||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
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.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@@ -72,33 +75,53 @@ 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() : Fragment(R.layout.fingerprint_v2_enroll_introduction) {
|
||||||
private lateinit var footerBarMixin: FooterBarMixin
|
|
||||||
private lateinit var textModel: TextModel
|
|
||||||
private lateinit var navigationViewModel: FingerprintEnrollNavigationViewModel
|
|
||||||
private lateinit var fingerprintEnrollViewModel: FingerprintEnrollViewModel
|
|
||||||
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
|
|
||||||
private lateinit var gateKeeperViewModel: FingerprintGatekeeperViewModel
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
/** Used for testing purposes */
|
||||||
super.onCreate(savedInstanceState)
|
private var factory: ViewModelProvider.Factory? = null
|
||||||
navigationViewModel =
|
|
||||||
ViewModelProvider(requireActivity())[FingerprintEnrollNavigationViewModel::class.java]
|
@VisibleForTesting
|
||||||
fingerprintEnrollViewModel =
|
constructor(theFactory: ViewModelProvider.Factory) : this() {
|
||||||
ViewModelProvider(requireActivity())[FingerprintEnrollViewModel::class.java]
|
factory = theFactory
|
||||||
fingerprintScrollViewModel =
|
|
||||||
ViewModelProvider(requireActivity())[FingerprintScrollViewModel::class.java]
|
|
||||||
gateKeeperViewModel =
|
|
||||||
ViewModelProvider(requireActivity())[FingerprintGatekeeperViewModel::class.java]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
private val viewModelProvider: ViewModelProvider by lazy {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
if (factory != null) {
|
||||||
|
ViewModelProvider(requireActivity(), factory!!)
|
||||||
|
} else {
|
||||||
|
ViewModelProvider(requireActivity())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lifecycleScope.launch {
|
private lateinit var footerBarMixin: FooterBarMixin
|
||||||
|
private lateinit var textModel: TextModel
|
||||||
|
|
||||||
|
// Note that the ViewModels cannot be requested before the onCreate call
|
||||||
|
private val navigationViewModel: FingerprintEnrollNavigationViewModel by lazy {
|
||||||
|
viewModelProvider[FingerprintEnrollNavigationViewModel::class.java]
|
||||||
|
}
|
||||||
|
private val fingerprintViewModel: FingerprintEnrollViewModel by lazy {
|
||||||
|
viewModelProvider[FingerprintEnrollViewModel::class.java]
|
||||||
|
}
|
||||||
|
private val fingerprintScrollViewModel: FingerprintScrollViewModel by lazy {
|
||||||
|
viewModelProvider[FingerprintScrollViewModel::class.java]
|
||||||
|
}
|
||||||
|
private val gateKeeperViewModel: FingerprintGatekeeperViewModel by lazy {
|
||||||
|
viewModelProvider[FingerprintGatekeeperViewModel::class.java]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? =
|
||||||
|
super.onCreateView(inflater, container, savedInstanceState).also { theView ->
|
||||||
|
val view = theView!!
|
||||||
|
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
combine(
|
combine(
|
||||||
navigationViewModel.enrollType,
|
navigationViewModel.enrollType,
|
||||||
fingerprintEnrollViewModel.sensorType,
|
fingerprintViewModel.sensorType,
|
||||||
) { enrollType, sensorType ->
|
) { enrollType, sensorType ->
|
||||||
Pair(enrollType, sensorType)
|
Pair(enrollType, sensorType)
|
||||||
}
|
}
|
||||||
@@ -111,9 +134,10 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
|
|
||||||
setupFooterBarAndScrollView(view)
|
setupFooterBarAndScrollView(view)
|
||||||
|
|
||||||
if (savedInstanceState == null) {
|
val layout = view as GlifLayout
|
||||||
getLayout()?.setHeaderText(textModel.headerText)
|
|
||||||
getLayout()?.setDescriptionText(textModel.descriptionText)
|
layout.setHeaderText(textModel.headerText)
|
||||||
|
layout.setDescriptionText(textModel.descriptionText)
|
||||||
|
|
||||||
// Set color filter for the following icons.
|
// Set color filter for the following icons.
|
||||||
val colorFilter = getIconColorFilter()
|
val colorFilter = getIconColorFilter()
|
||||||
@@ -159,7 +183,7 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
view.requireViewById<TextView?>(R.id.footer_title_2).setText(textModel.footerTitleOne)
|
view.requireViewById<TextView?>(R.id.footer_title_2).setText(textModel.footerTitleOne)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setFooterLink(view: View) {
|
private fun setFooterLink(view: View) {
|
||||||
@@ -185,17 +209,18 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
navigationViewModel.nextStep()
|
navigationViewModel.nextStep()
|
||||||
}
|
}
|
||||||
|
|
||||||
val layout: GlifLayout = requireActivity().requireViewById(R.id.setup_wizard_layout)
|
val layout: GlifLayout = view.findViewById(R.id.setup_wizard_layout)!!
|
||||||
footerBarMixin = layout.getMixin(FooterBarMixin::class.java)
|
footerBarMixin = layout.getMixin(FooterBarMixin::class.java)
|
||||||
footerBarMixin.primaryButton =
|
footerBarMixin.primaryButton =
|
||||||
FooterButton.Builder(requireActivity())
|
FooterButton.Builder(requireContext())
|
||||||
.setText(R.string.security_settings_face_enroll_introduction_more)
|
.setText(R.string.security_settings_face_enroll_introduction_more)
|
||||||
.setListener(onNextButtonClick)
|
.setListener(onNextButtonClick)
|
||||||
.setButtonType(FooterButton.ButtonType.OPT_IN)
|
.setButtonType(FooterButton.ButtonType.OPT_IN)
|
||||||
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
|
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
footerBarMixin.setSecondaryButton(
|
footerBarMixin.setSecondaryButton(
|
||||||
FooterButton.Builder(requireActivity())
|
FooterButton.Builder(requireContext())
|
||||||
.setText(textModel.negativeButton)
|
.setText(textModel.negativeButton)
|
||||||
.setListener({ Log.d(TAG, "prevClicked") })
|
.setListener({ Log.d(TAG, "prevClicked") })
|
||||||
.setButtonType(FooterButton.ButtonType.NEXT)
|
.setButtonType(FooterButton.ButtonType.NEXT)
|
||||||
@@ -211,8 +236,8 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
|
|
||||||
val requireScrollMixin = layout.getMixin(RequireScrollMixin::class.java)
|
val requireScrollMixin = layout.getMixin(RequireScrollMixin::class.java)
|
||||||
requireScrollMixin.requireScrollWithButton(
|
requireScrollMixin.requireScrollWithButton(
|
||||||
requireActivity(),
|
requireContext(),
|
||||||
footerBarMixin.primaryButton,
|
primaryButton,
|
||||||
R.string.security_settings_face_enroll_introduction_more,
|
R.string.security_settings_face_enroll_introduction_more,
|
||||||
onNextButtonClick
|
onNextButtonClick
|
||||||
)
|
)
|
||||||
@@ -224,7 +249,7 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
fingerprintScrollViewModel.hasReadConsentScreen.collect { consented ->
|
fingerprintScrollViewModel.hasReadConsentScreen.collect { consented ->
|
||||||
if (consented) {
|
if (consented) {
|
||||||
primaryButton.setText(
|
primaryButton.setText(
|
||||||
@@ -244,7 +269,7 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
// the flow. For instance if someone launches the activity with an invalid challenge, it
|
// the flow. For instance if someone launches the activity with an invalid challenge, it
|
||||||
// either 1) Fails or 2) Launched confirmDeviceCredential
|
// either 1) Fails or 2) Launched confirmDeviceCredential
|
||||||
primaryButton.isEnabled = false
|
primaryButton.isEnabled = false
|
||||||
lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
gateKeeperViewModel.hasValidGatekeeperInfo.collect { primaryButton.isEnabled = it }
|
gateKeeperViewModel.hasValidGatekeeperInfo.collect { primaryButton.isEnabled = it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,8 +309,4 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
|||||||
PorterDuff.Mode.SRC_IN
|
PorterDuff.Mode.SRC_IN
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLayout(): GlifLayout? {
|
|
||||||
return requireView().findViewById(R.id.setup_wizard_layout) as GlifLayout?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -31,11 +31,6 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
private const val TAG = "FingerprintEnrollNavigationViewModel"
|
private const val TAG = "FingerprintEnrollNavigationViewModel"
|
||||||
|
|
||||||
/** Interface to validate a gatekeeper hat */
|
|
||||||
interface Validator {
|
|
||||||
fun validateGateKeeper(challenge: Long?): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [EnrollType] for fingerprint enrollment indicates information on how the flow should behave.
|
* The [EnrollType] for fingerprint enrollment indicates information on how the flow should behave.
|
||||||
*/
|
*/
|
||||||
@@ -56,7 +51,6 @@ object Unicorn : EnrollType()
|
|||||||
*/
|
*/
|
||||||
class FingerprintEnrollNavigationViewModel(
|
class FingerprintEnrollNavigationViewModel(
|
||||||
private val dispatcher: CoroutineDispatcher,
|
private val dispatcher: CoroutineDispatcher,
|
||||||
private val validator: Validator,
|
|
||||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||||
private val canSkipConfirm: Boolean
|
private val canSkipConfirm: Boolean
|
||||||
@@ -145,11 +139,6 @@ class FingerprintEnrollNavigationViewModel(
|
|||||||
|
|
||||||
return FingerprintEnrollNavigationViewModel(
|
return FingerprintEnrollNavigationViewModel(
|
||||||
backgroundDispatcher,
|
backgroundDispatcher,
|
||||||
object : Validator {
|
|
||||||
override fun validateGateKeeper(challenge: Long?): Boolean {
|
|
||||||
return challenge != null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fingerprintManagerInteractor,
|
fingerprintManagerInteractor,
|
||||||
fingerprintGatekeeperViewModel,
|
fingerprintGatekeeperViewModel,
|
||||||
canSkipConfirm,
|
canSkipConfirm,
|
||||||
|
@@ -25,6 +25,8 @@ android_app {
|
|||||||
"androidx.fragment_fragment-testing",
|
"androidx.fragment_fragment-testing",
|
||||||
"frameworks-base-testutils",
|
"frameworks-base-testutils",
|
||||||
"androidx.fragment_fragment",
|
"androidx.fragment_fragment",
|
||||||
|
"androidx.lifecycle_lifecycle-runtime-testing",
|
||||||
|
"kotlinx_coroutines_test",
|
||||||
],
|
],
|
||||||
|
|
||||||
aaptflags: ["--extra-packages com.android.settings"],
|
aaptflags: ["--extra-packages com.android.settings"],
|
||||||
|
@@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.biometrics.fingerprint2.fragment
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.fragment.app.testing.FragmentScenario
|
||||||
|
import androidx.fragment.app.testing.launchFragmentInContainer
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.espresso.Espresso.onView
|
||||||
|
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
|
||||||
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.Visibility
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withEffectiveVisibility
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||||
|
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||||
|
import androidx.test.runner.AndroidJUnit4
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||||
|
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||||
|
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.google.android.setupdesign.GlifLayout
|
||||||
|
import com.google.android.setupdesign.template.RequireScrollMixin
|
||||||
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class FingerprintEnrollIntroFragmentTest {
|
||||||
|
private var context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
private var interactor = FakeFingerprintManagerInteractor()
|
||||||
|
|
||||||
|
private val gatekeeperViewModel =
|
||||||
|
FingerprintGatekeeperViewModel(
|
||||||
|
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
|
||||||
|
interactor
|
||||||
|
)
|
||||||
|
private val backgroundDispatcher = StandardTestDispatcher()
|
||||||
|
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
|
||||||
|
|
||||||
|
private val navigationViewModel =
|
||||||
|
FingerprintEnrollNavigationViewModel(
|
||||||
|
backgroundDispatcher,
|
||||||
|
interactor,
|
||||||
|
gatekeeperViewModel,
|
||||||
|
canSkipConfirm = true,
|
||||||
|
)
|
||||||
|
private var fingerprintViewModel = FingerprintEnrollViewModel(interactor, backgroundDispatcher)
|
||||||
|
private var fingerprintScrollViewModel = FingerprintScrollViewModel()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
val factory =
|
||||||
|
object : ViewModelProvider.Factory {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel> create(
|
||||||
|
modelClass: Class<T>,
|
||||||
|
): T {
|
||||||
|
return when (modelClass) {
|
||||||
|
FingerprintEnrollViewModel::class.java -> fingerprintViewModel
|
||||||
|
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
|
||||||
|
FingerprintEnrollNavigationViewModel::class.java -> navigationViewModel
|
||||||
|
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
as T
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentScenario =
|
||||||
|
launchFragmentInContainer(Bundle(), R.style.SudThemeGlif) {
|
||||||
|
FingerprintEnrollIntroV2Fragment(factory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testScrollToBottomButtonChangesText() {
|
||||||
|
fragmentScenario.onFragment { fragment ->
|
||||||
|
onView(withText("I agree")).check(doesNotExist())
|
||||||
|
val someView = (fragment.requireView().findViewById<GlifLayout>(R.id.setup_wizard_layout))!!
|
||||||
|
val scrollMixin = someView.getMixin(RequireScrollMixin::class.java)!!
|
||||||
|
val listener = scrollMixin.onRequireScrollStateChangedListener
|
||||||
|
// This actually changes the button text
|
||||||
|
listener.onRequireScrollStateChanged(false)
|
||||||
|
|
||||||
|
onView(withText("I agree")).check(matches(isDisplayed()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testBasicTitle() {
|
||||||
|
onView(withText(R.string.security_settings_fingerprint_enroll_introduction_title))
|
||||||
|
.check(matches(withEffectiveVisibility(Visibility.VISIBLE)))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFooterMessageTwo() {
|
||||||
|
onView(withId(R.id.footer_message_2))
|
||||||
|
.check(
|
||||||
|
matches(
|
||||||
|
withText(
|
||||||
|
context.getString(
|
||||||
|
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFooterMessageThree() {
|
||||||
|
onView(withId(R.id.footer_message_3))
|
||||||
|
.check(
|
||||||
|
matches(
|
||||||
|
withText(
|
||||||
|
context.getString(
|
||||||
|
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFooterMessageFour() {
|
||||||
|
onView(withId(R.id.footer_message_4))
|
||||||
|
.check(
|
||||||
|
matches(
|
||||||
|
withText(
|
||||||
|
context.getString(
|
||||||
|
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFooterMessageFive() {
|
||||||
|
onView(withId(R.id.footer_message_5))
|
||||||
|
.check(
|
||||||
|
matches(
|
||||||
|
withText(
|
||||||
|
context.getString(
|
||||||
|
(R.string.security_settings_fingerprint_v2_enroll_introduction_footer_message_5)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user