Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b7021c8e authored by Joshua McCloskey's avatar Joshua McCloskey
Browse files

Added UI tests for FingerprintEnrollIntro

Test: m -j40 RunSettingsRoboTests ROBOTEST_FILTER=FingerprintEnrollmentIntroFragmentTest
Bug: 295206367
Change-Id: I70f6b50dd2604e01805df04ffb1c07a9134ba065
parent 9952d054
Loading
Loading
Loading
Loading
+166 −155
Original line number Diff line number Diff line
@@ -17,9 +17,8 @@

<com.google.android.setupdesign.GlifLayout
    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"
    style="?attr/fingerprint_layout_theme"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

@@ -58,9 +57,9 @@ android:layout_height="match_parent">

            <!-- How it works -->
            <TextView
                style="@style/BiometricEnrollIntroTitle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
            style="@style/BiometricEnrollIntroTitle"
                android:text="@string/security_settings_fingerprint_v2_enroll_introduction_footer_title_2" />

            <LinearLayout
@@ -74,14 +73,16 @@ android:layout_height="match_parent">
                    android:layout_height="wrap_content"
                    android:contentDescription="@null"
                    android:src="@drawable/ic_fingerprint_24dp" />

                <Space
                    android:layout_width="16dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/footer_message_2"
                    style="@style/BiometricEnrollIntroMessage"
                    android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/BiometricEnrollIntroMessage" />
                    android:layout_height="wrap_content" />
            </LinearLayout>

            <LinearLayout
@@ -95,22 +96,24 @@ android:layout_height="match_parent">
                    android:layout_height="wrap_content"
                    android:contentDescription="@null"
                    android:src="@drawable/ic_lock_24dp" />

                <Space
                    android:layout_width="16dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/footer_message_3"
                    style="@style/BiometricEnrollIntroMessage"
                    android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/BiometricEnrollIntroMessage" />
                    android:layout_height="wrap_content" />
            </LinearLayout>

            <!-- You're in control -->
            <TextView
                android:id="@+id/footer_title_1"
                style="@style/BiometricEnrollIntroTitle"
                android:layout_width="match_parent"
            android:layout_height="wrap_content"
            style="@style/BiometricEnrollIntroTitle" />
                android:layout_height="wrap_content" />

            <LinearLayout
                android:layout_width="match_parent"
@@ -123,22 +126,24 @@ android:layout_height="match_parent">
                    android:layout_height="wrap_content"
                    android:contentDescription="@null"
                    android:src="@drawable/ic_trash_can" />

                <Space
                    android:layout_width="16dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/footer_message_4"
                    style="@style/BiometricEnrollIntroMessage"
                    android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/BiometricEnrollIntroMessage" />
                    android:layout_height="wrap_content" />
            </LinearLayout>

            <!-- Keep in mind -->
            <TextView
                android:id="@+id/footer_title_2"
                style="@style/BiometricEnrollIntroTitle"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
            style="@style/BiometricEnrollIntroTitle"
                android:text="@string/security_settings_face_enroll_introduction_info_title" />

            <LinearLayout
@@ -152,14 +157,16 @@ android:layout_height="match_parent">
                    android:layout_height="wrap_content"
                    android:contentDescription="@null"
                    android:src="@drawable/ic_info_outline_24dp" />

                <Space
                    android:layout_width="16dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/footer_message_5"
                    style="@style/BiometricEnrollIntroMessage"
                    android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/BiometricEnrollIntroMessage" />
                    android:layout_height="wrap_content" />
            </LinearLayout>

            <LinearLayout
@@ -173,14 +180,16 @@ android:layout_height="match_parent">
                    android:layout_height="wrap_content"
                    android:contentDescription="@null"
                    android:src="@drawable/ic_guarantee" />

                <Space
                    android:layout_width="16dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/footer_message_6"
                    style="@style/BiometricEnrollIntroMessage"
                    android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/BiometricEnrollIntroMessage" />
                    android:layout_height="wrap_content" />
            </LinearLayout>

            <LinearLayout
@@ -194,15 +203,17 @@ android:layout_height="match_parent">
                    android:layout_height="wrap_content"
                    android:contentDescription="@null"
                    android:src="@drawable/ic_link_24dp" />

                <Space
                    android:layout_width="16dp"
                    android:layout_height="wrap_content" />

                <TextView
                    android:id="@+id/footer_learn_more"
                android:linksClickable="true"
                    style="@style/BiometricEnrollIntroMessage"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                style="@style/BiometricEnrollIntroMessage"
                    android:linksClickable="true"
                    android:paddingBottom="0dp"
                    android:text="@string/security_settings_fingerprint_v2_enroll_introduction_message_learn_more" />
            </LinearLayout>
+5 −2
Original line number Diff line number Diff line
@@ -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.GatekeeperPasswordProvider
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.FingerprintEnrollEnrollingV2Fragment
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 foldStateViewModel: FoldStateViewModel
  private lateinit var orientationStateViewModel: OrientationStateViewModel
  private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
  private val coroutineDispatcher = Dispatchers.Default

  /** Result listener for ChooseLock activity flow. */
@@ -210,6 +212,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
      )[FingerprintEnrollViewModel::class.java]

    // Initialize scroll view model
    fingerprintScrollViewModel =
      ViewModelProvider(this, FingerprintScrollViewModel.FingerprintScrollViewModelFactory())[
        FingerprintScrollViewModel::class.java]

+69 −48
Original line number Diff line number Diff line
@@ -25,10 +25,13 @@ import android.os.Bundle
import android.text.Html
import android.text.method.LinkMovementMethod
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ScrollView
import android.widget.TextView
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
@@ -72,33 +75,53 @@ private data class TextModel(
 * 2. How the data will be stored
 * 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) {

  /** 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 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?) {
    super.onCreate(savedInstanceState)
    navigationViewModel =
      ViewModelProvider(requireActivity())[FingerprintEnrollNavigationViewModel::class.java]
    fingerprintEnrollViewModel =
      ViewModelProvider(requireActivity())[FingerprintEnrollViewModel::class.java]
    fingerprintScrollViewModel =
      ViewModelProvider(requireActivity())[FingerprintScrollViewModel::class.java]
    gateKeeperViewModel =
      ViewModelProvider(requireActivity())[FingerprintGatekeeperViewModel::class.java]

  // 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 onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
  override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View? =
    super.onCreateView(inflater, container, savedInstanceState).also { theView ->
      val view = theView!!

    lifecycleScope.launch {
      viewLifecycleOwner.lifecycleScope.launch {
        combine(
            navigationViewModel.enrollType,
          fingerprintEnrollViewModel.sensorType,
            fingerprintViewModel.sensorType,
          ) { enrollType, sensorType ->
            Pair(enrollType, sensorType)
          }
@@ -111,9 +134,10 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll

            setupFooterBarAndScrollView(view)

          if (savedInstanceState == null) {
            getLayout()?.setHeaderText(textModel.headerText)
            getLayout()?.setDescriptionText(textModel.descriptionText)
            val layout = view as GlifLayout

            layout.setHeaderText(textModel.headerText)
            layout.setDescriptionText(textModel.descriptionText)

            // Set color filter for the following icons.
            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)
          }
      }
    }
      return view
    }

  private fun setFooterLink(view: View) {
@@ -185,17 +209,18 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
        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.primaryButton =
      FooterButton.Builder(requireActivity())
      FooterButton.Builder(requireContext())
        .setText(R.string.security_settings_face_enroll_introduction_more)
        .setListener(onNextButtonClick)
        .setButtonType(FooterButton.ButtonType.OPT_IN)
        .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
        .build()

    footerBarMixin.setSecondaryButton(
      FooterButton.Builder(requireActivity())
      FooterButton.Builder(requireContext())
        .setText(textModel.negativeButton)
        .setListener({ Log.d(TAG, "prevClicked") })
        .setButtonType(FooterButton.ButtonType.NEXT)
@@ -211,8 +236,8 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll

    val requireScrollMixin = layout.getMixin(RequireScrollMixin::class.java)
    requireScrollMixin.requireScrollWithButton(
      requireActivity(),
      footerBarMixin.primaryButton,
      requireContext(),
      primaryButton,
      R.string.security_settings_face_enroll_introduction_more,
      onNextButtonClick
    )
@@ -224,7 +249,7 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
      }
    }

    lifecycleScope.launch {
    viewLifecycleOwner.lifecycleScope.launch {
      fingerprintScrollViewModel.hasReadConsentScreen.collect { consented ->
        if (consented) {
          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
    // either 1) Fails or 2) Launched confirmDeviceCredential
    primaryButton.isEnabled = false
    lifecycleScope.launch {
    viewLifecycleOwner.lifecycleScope.launch {
      gateKeeperViewModel.hasValidGatekeeperInfo.collect { primaryButton.isEnabled = it }
    }
  }
@@ -284,8 +309,4 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
      PorterDuff.Mode.SRC_IN
    )
  }

  private fun getLayout(): GlifLayout? {
    return requireView().findViewById(R.id.setup_wizard_layout) as GlifLayout?
  }
}
+0 −11
Original line number Diff line number Diff line
@@ -31,11 +31,6 @@ import kotlinx.coroutines.launch

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.
 */
@@ -56,7 +51,6 @@ object Unicorn : EnrollType()
 */
class FingerprintEnrollNavigationViewModel(
  private val dispatcher: CoroutineDispatcher,
  private val validator: Validator,
  private val fingerprintManagerInteractor: FingerprintManagerInteractor,
  private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
  private val canSkipConfirm: Boolean
@@ -145,11 +139,6 @@ class FingerprintEnrollNavigationViewModel(

      return FingerprintEnrollNavigationViewModel(
        backgroundDispatcher,
        object : Validator {
          override fun validateGateKeeper(challenge: Long?): Boolean {
            return challenge != null
          }
        },
        fingerprintManagerInteractor,
        fingerprintGatekeeperViewModel,
        canSkipConfirm,
+2 −0
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ android_app {
        "androidx.fragment_fragment-testing",
        "frameworks-base-testutils",
        "androidx.fragment_fragment",
        "androidx.lifecycle_lifecycle-runtime-testing",
        "kotlinx_coroutines_test",
    ],

    aaptflags: ["--extra-packages com.android.settings"],
Loading