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

Commit 00f29b70 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Remove multi-biometric interstitial screen in SUW" into sc-dev

parents 704d86ba 5f1d13e3
Loading
Loading
Loading
Loading
+0 −64
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <!-- Icon -->
    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_alignParentStart="true" />

    <!-- Title -->
    <com.google.android.setupdesign.view.RichTextView
        style="@style/SudDescription.Glif"
        android:id="@+id/title"
        android:paddingHorizontal="8dp"
        android:paddingTop="16dp"
        android:layout_marginBottom="4dp"
        android:gravity="start"
        android:layout_toEndOf="@+id/icon"
        android:layout_toStartOf="@+id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <!-- Description -->
    <TextView
        android:id="@+id/description"
        android:paddingHorizontal="8dp"
        android:paddingBottom="16dp"
        android:layout_toEndOf="@+id/icon"
        android:layout_toStartOf="@+id/checkbox"
        android:layout_below="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <!-- Check Box -->
    <CheckBox
        android:layout_alignParentEnd="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/checkbox"
        android:layout_centerVertical="true"
        android:checked="true"/>

</RelativeLayout>
 No newline at end of file
+0 −79
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2020 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.
  -->

<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/face_layout_theme"
    app:sucHeaderText="@string/multi_biometric_enroll_title"
    android:id="@+id/setup_wizard_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        style="@style/SudContentFrame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.google.android.setupdesign.view.RichTextView
            android:id="@+id/sud_layout_description"
            style="@style/SudDescription.Glif"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/multi_biometric_enroll_subtitle"/>

        <com.google.android.setupdesign.view.IllustrationVideoView
            android:id="@+id/illustration_normal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/SudContentIllustration"
            app:sudVideo="@raw/face_settings"/>

        <TextView
            style="@style/SudDescription.Glif"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/setup_with"
            android:text="@string/multi_biometric_enroll_setup_with"
            android:gravity="start"/>

        <include layout="@layout/horizontal_divider"/>

        <com.android.settings.biometrics.BiometricEnrollCheckbox
            android:id="@+id/checkbox_face"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:title="@string/multi_biometric_enroll_face_unlock_title"
            app:description="@string/multi_biometric_enroll_face_unlock_description"
            app:icon="@drawable/ic_face_24dp"/>

        <include layout="@layout/horizontal_divider"/>

        <com.android.settings.biometrics.BiometricEnrollCheckbox
            android:id="@+id/checkbox_fingerprint"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:title="@string/multi_biometric_enroll_fingerprint_unlock_title"
            app:description="@string/multi_biometric_enroll_fingerprint_unlock_description"
            app:icon="@drawable/ic_fingerprint_24dp"/>

        <include layout="@layout/horizontal_divider"/>

    </LinearLayout>

</com.google.android.setupdesign.GlifLayout>
+0 −20
Original line number Diff line number Diff line
@@ -740,26 +740,6 @@
    <!-- Summary for Security settings when fingerprint is not supported [CHAR LIMIT=NONE]-->
    <string name="security_dashboard_summary_no_fingerprint">Screen lock</string>
    <!-- Biometric enrollment for devices with multiple sensors --><skip />
    <!-- Introduction title shown in biometric enrollment screen for devices that have both fingerprint and face. [CHAR LIMIT=60] -->
    <string name="multi_biometric_enroll_title">Unlock your phone securely with your face and fingerprint</string>
    <!-- Introduction subtitle shown in the biometric enrollment screen. [CHAR LIMIT=60] -->
    <string name="multi_biometric_enroll_subtitle">You can also sign in to apps and confirm payments</string>
    <!-- Section description preceding the biometric sensors available for the user to select for enrollment. [CHAR LIMIT=40] -->
    <string name="multi_biometric_enroll_setup_with">Set up unlock with:</string>
    <!-- Title for a preference containing a checkbox which if selected will allow the user to proceed to set up face unlock. [CHAR LIMIT=32] -->
    <string name="multi_biometric_enroll_face_unlock_title">Face unlock</string>
    <!-- Description for a preference containing a checkbox which if selected will allow the user to set up face unlock. [CHAR LIMIT=40] -->
    <string name="multi_biometric_enroll_face_unlock_description">Make unlocking your phone a breeze</string>
    <!-- Title for a preference containing a checkbox which if selected will allow the user to proceed to set up fingerprint unlock. [CHAR LIMIT=32] -->
    <string name="multi_biometric_enroll_fingerprint_unlock_title">Fingerprint</string>
    <!-- Description for a preference containing a checkbox which if selected will allow the user to set up fingerprint unlock. [CHAR LIMIT=40] -->
    <string name="multi_biometric_enroll_fingerprint_unlock_description">Save time unlocking phone in your pocket</string>
    <!-- Button for skipping biometric enrollment. [CHAR LIMIT=30] -->
    <string name="multi_biometric_enroll_skip">Skip</string>
    <!-- Button for starting biometric enrollment. [CHAR LIMIT=30] -->
    <string name="multi_biometric_enroll_next">Next</string>
    <!-- Face enrollment and settings --><skip />
    <!-- Message shown in summary field when face unlock is set up. [CHAR LIMIT=40] -->
    <string name="security_settings_face_preference_summary">Face added</string>
+10 −71
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

@@ -45,10 +44,7 @@ import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.password.ChooseLockSettingsHelper;

import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.GlifLayout;

import java.util.List;

@@ -78,9 +74,9 @@ public class BiometricEnrollActivity extends InstrumentedActivity {

    private int mUserId = UserHandle.myUserId();
    private boolean mConfirmingCredentials;
    private boolean mIsFaceEnrollable;
    private boolean mIsFingerprintEnrollable;
    @Nullable private Long mGkPwHandle;
    private BiometricEnrollCheckbox mCheckboxFace;
    private BiometricEnrollCheckbox mCheckboxFingerprint;
    @Nullable private MultiBiometricEnrollHelper mMultiBiometricEnrollHelper;

    @Override
@@ -180,6 +176,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
                    mConfirmingCredentials = false;
                    if (resultCode == ChooseLockPattern.RESULT_FINISHED) {
                        mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
                        startMultiBiometricEnroll();
                    } else {
                        Log.d(TAG, "Unknown result for chooseLock: " + resultCode);
                        setResult(resultCode);
@@ -190,6 +187,7 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
                    mConfirmingCredentials = false;
                    if (resultCode == RESULT_OK) {
                        mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
                        startMultiBiometricEnroll();
                    } else {
                        Log.d(TAG, "Unknown result for confirmLock: " + resultCode);
                        finish();
@@ -226,14 +224,6 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
    }

    private void setupForMultiBiometricEnroll() {
        setContentView(R.layout.biometric_enroll_layout);

        mCheckboxFace = findViewById(R.id.checkbox_face);
        mCheckboxFingerprint = findViewById(R.id.checkbox_fingerprint);

        mCheckboxFace.setListener(this::updateNextButton);
        mCheckboxFingerprint.setListener(this::updateNextButton);

        final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
        final FaceManager faceManager = getSystemService(FaceManager.class);
        final List<FingerprintSensorPropertiesInternal> fpProperties =
@@ -242,39 +232,10 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
                faceManager.getSensorPropertiesInternal();

        // This would need to be updated for devices with multiple sensors of the same modality
        final boolean maxFacesEnrolled = faceManager.getEnrolledFaces(mUserId).size()
                >= faceProperties.get(0).maxEnrollmentsPerUser;
        final boolean maxFingerprintsEnrolled = fingerprintManager.getEnrolledFingerprints(mUserId)
                .size() >= fpProperties.get(0).maxEnrollmentsPerUser;

        if (maxFacesEnrolled) {
            mCheckboxFace.setEnabled(false);
            mCheckboxFace.setDescription(R.string.face_intro_error_max);
        }

        if (maxFingerprintsEnrolled) {
            mCheckboxFingerprint.setEnabled(false);
            mCheckboxFingerprint.setDescription(R.string.fingerprint_intro_error_max);
        }

        final FooterBarMixin footerBarMixin = ((GlifLayout) findViewById(R.id.setup_wizard_layout))
                .getMixin(FooterBarMixin.class);
        footerBarMixin.setSecondaryButton(new FooterButton.Builder(this)
                .setText(R.string.multi_biometric_enroll_skip)
                .setListener(this::onButtonNegative)
                .setButtonType(FooterButton.ButtonType.SKIP)
                .setTheme(R.style.SudGlifButton_Secondary)
                .build());

        footerBarMixin.setPrimaryButton(new FooterButton.Builder(this)
                .setText(R.string.multi_biometric_enroll_next)
                .setListener(this::onButtonPositive)
                .setButtonType(FooterButton.ButtonType.NEXT)
                .setTheme(R.style.SudGlifButton_Primary)
                .build());

        footerBarMixin.getSecondaryButton().setVisibility(View.VISIBLE);
        footerBarMixin.getPrimaryButton().setVisibility(View.VISIBLE);
        mIsFaceEnrollable = faceManager.getEnrolledFaces(mUserId).size()
                < faceProperties.get(0).maxEnrollmentsPerUser;
        mIsFingerprintEnrollable = fingerprintManager.getEnrolledFingerprints(mUserId).size()
                < fpProperties.get(0).maxEnrollmentsPerUser;

        if (!mConfirmingCredentials && mGkPwHandle == null) {
            mConfirmingCredentials = true;
@@ -286,34 +247,12 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
        }
    }

    private void updateNextButton(View view) {
        final boolean canEnrollAny = canEnrollFace() || canEnrollFingerprint();

        final FooterBarMixin footerBarMixin = ((GlifLayout) findViewById(R.id.setup_wizard_layout))
                .getMixin(FooterBarMixin.class);
        footerBarMixin.getPrimaryButton().setEnabled(canEnrollAny);
    }

    private void onButtonPositive(View view) {
        // Start the state machine according to checkboxes, taking max enrolled into account
    private void startMultiBiometricEnroll() {
        mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper(this, mUserId,
                canEnrollFace(), canEnrollFingerprint(), mGkPwHandle);
                mIsFaceEnrollable, mIsFingerprintEnrollable, mGkPwHandle);
        mMultiBiometricEnrollHelper.startNextStep();
    }

    private void onButtonNegative(View view) {
        setResult(RESULT_SKIP);
        finish();
    }

    private boolean canEnrollFace() {
        return mCheckboxFace.isEnabled() && mCheckboxFace.isChecked();
    }

    private boolean canEnrollFingerprint() {
        return mCheckboxFingerprint.isEnabled() && mCheckboxFingerprint.isChecked();
    }

    private boolean userHasPassword(int userId) {
        final UserManager userManager = getSystemService(UserManager.class);
        final int passwordQuality = new LockPatternUtils(this)
+0 −115
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;

import com.android.settings.R;

/**
 * Widget contain space for an icon, title, description, and checkbox. On devices with multiple
 * biometric sensors, allows users to choose sensors during {@link BiometricEnrollActivity}.
 */
public class BiometricEnrollCheckbox extends LinearLayout {

    @NonNull private final CheckBox mCheckBox;
    @NonNull private final TextView mDescriptionView;
    @Nullable private View.OnClickListener mListener;

    public BiometricEnrollCheckbox(Context context) {
        this(context, null /* attrs */);
    }

    public BiometricEnrollCheckbox(Context context,
            @Nullable AttributeSet attrs) {
        this(context, attrs, 0 /* defStyleAttr */);
    }

    public BiometricEnrollCheckbox(Context context, @Nullable AttributeSet attrs,
            int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
    }

    public BiometricEnrollCheckbox(Context context, AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        LayoutInflater.from(context).inflate(R.layout.biometric_enroll_checkbox,
                this, true /* attachToRoot */);

        mCheckBox = findViewById(R.id.checkbox);
        final ImageView iconView = findViewById(R.id.icon);
        final TextView titleView = findViewById(R.id.title);
        mDescriptionView = findViewById(R.id.description);

        setOnClickListener(view -> {
            if (isEnabled()) {
                mCheckBox.toggle();
            }
            if (mListener != null) {
                mListener.onClick(view);
            }
        });

        final TypedArray a = context
                .obtainStyledAttributes(attrs, R.styleable.BiometricEnrollCheckbox);
        try {
            final Drawable icon =
                    a.getDrawable(R.styleable.BiometricEnrollCheckbox_icon);
            final CharSequence title =
                    a.getText(R.styleable.BiometricEnrollCheckbox_title);
            final CharSequence description =
                    a.getText(R.styleable.BiometricEnrollCheckbox_description);
            iconView.setImageDrawable(icon);
            titleView.setText(title);
            mDescriptionView.setText(description);
        } finally {
            a.recycle();
        }
    }

    public void setListener(View.OnClickListener listener) {
        mListener = listener;
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        mCheckBox.setEnabled(enabled);
    }

    public boolean isChecked() {
        return mCheckBox.isChecked();
    }

    public void setDescription(@StringRes int resId) {
        mDescriptionView.setText(resId);
    }
}
Loading