Loading res/layout-land/udfps_enroll_enrolling.xmldeleted 100644 → 0 +0 −101 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2021 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" android:id="@+id/setup_wizard_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/sud_glif_blank_template" style="?attr/fingerprint_layout_theme"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:clipToPadding="false" android:clipChildren="false"> <!-- Both texts are kept as separate text views so it doesn't jump around in portrait. See layouts/fingerprint_enroll_enrolling_base.xml. --> <LinearLayout android:id="@+id/layout_container" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:layout_marginStart="?attr/sudMarginStart" android:layout_marginEnd="@dimen/enroll_margin_end" android:layout_marginBottom="@dimen/sud_content_frame_padding_bottom" android:paddingStart="@dimen/enroll_padding_start" android:paddingEnd="@dimen/enroll_padding_end" android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:clipChildren="false" android:clipToPadding="false"> <ImageView android:id="@+id/sud_layout_icon" style="@style/SudGlifIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitStart" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" android:src="@drawable/ic_lock" /> <TextView android:id="@+id/suc_layout_title" style="@style/SudGlifHeaderTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" /> <TextView style="@style/SudDescription.Glif" android:id="@+id/sud_layout_subtitle" android:layout_width="match_parent" android:layout_height="wrap_content"/> <Space android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout> </ScrollView> </LinearLayout> </LinearLayout> <include layout="@layout/udfps_enroll_view" /> </com.google.android.setupdesign.GlifLayout> No newline at end of file res/layout/udfps_enroll_enrolling.xml +2 −2 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ ~ limitations under the License. --> <com.google.android.setupdesign.GlifLayout <com.android.settings.biometrics.fingerprint.UdfpsEnrollEnrollingView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" Loading Loading @@ -78,4 +78,4 @@ </LinearLayout> </LinearLayout> </com.google.android.setupdesign.GlifLayout> </com.android.settings.biometrics.fingerprint.UdfpsEnrollEnrollingView> src/com/android/settings/biometrics/BiometricEnrollBase.java +10 −7 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { protected long mChallenge; protected boolean mFromSettingsSummary; protected FooterBarMixin mFooterBarMixin; protected boolean mShouldSetFooterBarBackground = true; @Nullable protected ScreenSizeFoldProvider mScreenSizeFoldProvider; @Nullable Loading Loading @@ -191,6 +192,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { super.onPostCreate(savedInstanceState); initViews(); if (mShouldSetFooterBarBackground) { @SuppressLint("VisibleForTests") final LinearLayout buttonContainer = mFooterBarMixin != null ? mFooterBarMixin.getButtonContainer() Loading @@ -199,6 +201,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { buttonContainer.setBackgroundColor(getBackgroundColor()); } } } @Override public void onAttachedToWindow() { Loading Loading @@ -331,7 +334,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { } @ColorInt private int getBackgroundColor() { public int getBackgroundColor() { final ColorStateList stateList = Utils.getColorAttr(this, android.R.attr.windowBackground); return stateList != null ? stateList.getDefaultColor() : Color.TRANSPARENT; } Loading src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +13 −184 Original line number Diff line number Diff line Loading @@ -32,10 +32,8 @@ import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.Animatable2; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; Loading @@ -48,22 +46,16 @@ import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; import android.view.DisplayInfo; import android.view.MotionEvent; import android.view.OrientationEventListener; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; Loading @@ -79,25 +71,20 @@ import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.BiometricsEnrollEnrolling; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settingslib.display.DisplayDensityUtils; import com.android.settingslib.udfps.UdfpsOverlayParams; import com.android.settingslib.udfps.UdfpsUtils; import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieCompositionFactory; import com.airbnb.lottie.LottieProperty; import com.airbnb.lottie.model.KeyPath; import com.google.android.setupcompat.template.FooterActionButton; 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 com.google.android.setupdesign.template.DescriptionMixin; import com.google.android.setupdesign.template.HeaderMixin; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Locale; /** * Activity which handles the actual enrolling for fingerprint. Loading Loading @@ -176,8 +163,6 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { @VisibleForTesting @Nullable UdfpsEnrollHelper mUdfpsEnrollHelper; // TODO(b/260617060): Do not hard-code mScaleFactor, referring to AuthController. private float mScaleFactor = 1.0f; private ObjectAnimator mProgressAnim; private TextView mErrorText; private Interpolator mFastOutSlowInInterpolator; Loading Loading @@ -206,7 +191,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { private boolean mHaveShownSfpsLeftEdgeLottie; private boolean mHaveShownSfpsRightEdgeLottie; private boolean mShouldShowLottie; private UdfpsUtils mUdfpsUtils; private ObjectAnimator mHelpAnimation; private OrientationEventListener mOrientationEventListener; Loading Loading @@ -251,88 +236,17 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { mAccessibilityManager = getSystemService(AccessibilityManager.class); mIsAccessibilityEnabled = mAccessibilityManager.isEnabled(); mUdfpsUtils = new UdfpsUtils(); final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale( Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL); listenOrientationEvent(); if (mCanAssumeUdfps) { int rotation = getApplicationContext().getDisplay().getRotation(); final GlifLayout layout = (GlifLayout) getLayoutInflater().inflate( final UdfpsEnrollEnrollingView layout = (UdfpsEnrollEnrollingView) getLayoutInflater().inflate( R.layout.udfps_enroll_enrolling, null, false); final UdfpsEnrollView udfpsEnrollView = layout.findViewById(R.id.udfps_animation_view); updateUdfpsEnrollView(udfpsEnrollView, props.get(0)); switch (rotation) { case Surface.ROTATION_90: final View sudContent = layout.findViewById(R.id.sud_layout_content); if (sudContent != null) { sudContent.setPadding(sudContent.getPaddingLeft(), 0, sudContent.getPaddingRight(), sudContent.getPaddingBottom()); } final LinearLayout layoutContainer = layout.findViewById( R.id.layout_container); final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); lp.setMarginEnd((int) getResources().getDimension( R.dimen.rotation_90_enroll_margin_end)); layoutContainer.setPaddingRelative((int) getResources().getDimension( R.dimen.rotation_90_enroll_padding_start), 0, isLayoutRtl ? 0 : (int) getResources().getDimension( R.dimen.rotation_90_enroll_padding_end), 0); layoutContainer.setLayoutParams(lp); setOnHoverListener(true, layout, udfpsEnrollView); setContentView(layout, lp); break; case Surface.ROTATION_0: case Surface.ROTATION_180: // In the portrait mode, layout_container's height is 0, so it's // always shown at the bottom of the screen. final FrameLayout portraitLayoutContainer = layout.findViewById( R.id.layout_container); // In the portrait mode, the title and lottie animation view may // overlap when title needs three lines, so adding some paddings // between them, and adjusting the fp progress view here accordingly. final int layoutLottieAnimationPadding = (int) getResources() .getDimension(R.dimen.udfps_lottie_padding_top); portraitLayoutContainer.setPadding(0, layoutLottieAnimationPadding, 0, 0); final ImageView progressView = udfpsEnrollView.findViewById( R.id.udfps_enroll_animation_fp_progress_view); progressView.setPadding(0, -(layoutLottieAnimationPadding), 0, layoutLottieAnimationPadding); final ImageView fingerprintView = udfpsEnrollView.findViewById( R.id.udfps_enroll_animation_fp_view); fingerprintView.setPadding(0, -layoutLottieAnimationPadding, 0, layoutLottieAnimationPadding); // TODO(b/260970216) Instead of hiding the description text view, we should // make the header view scrollable if the text is too long. // If description text view has overlap with udfps progress view, hide it. View view = layout.getDescriptionTextView(); layout.getViewTreeObserver().addOnDrawListener(() -> { if (view.getVisibility() == View.VISIBLE && hasOverlap(view, udfpsEnrollView)) { view.setVisibility(View.GONE); } }); setUdfpsEnrollHelper(); layout.initView(props.get(0), mUdfpsEnrollHelper, mAccessibilityManager); setOnHoverListener(false, layout, udfpsEnrollView); setContentView(layout); break; case Surface.ROTATION_270: default: setOnHoverListener(true, layout, udfpsEnrollView); setContentView(layout); break; } setDescriptionText(R.string.security_settings_udfps_enroll_start_message); } else if (mCanAssumeSfps) { setContentView(R.layout.sfps_enroll_enrolling); Loading Loading @@ -372,22 +286,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .build() ); if (FeatureFlagUtils.isEnabled(getApplicationContext(), FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) { // Remove the space view and make the width of footer button container WRAP_CONTENT // to avoid hiding the udfps view progress bar bottom. final LinearLayout buttonContainer = mFooterBarMixin.getButtonContainer(); View spaceView = null; for (int i = 0; i < buttonContainer.getChildCount(); i++) { if (!(buttonContainer.getChildAt(i) instanceof FooterActionButton)) { spaceView = buttonContainer.getChildAt(i); break; } } if (spaceView != null) { spaceView.setVisibility(View.GONE); buttonContainer.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; } // If it's udfps, set the background color only for secondary button if necessary. if (mCanAssumeUdfps) { mShouldSetFooterBarBackground = false; ((UdfpsEnrollEnrollingView) getLayout()).setSecondaryButtonBackground( getBackgroundColor()); } final LayerDrawable fingerprintDrawable = mProgressBar != null Loading Loading @@ -1237,30 +1140,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } } private UdfpsEnrollView updateUdfpsEnrollView(UdfpsEnrollView udfpsEnrollView, FingerprintSensorPropertiesInternal udfpsProps) { DisplayInfo displayInfo = new DisplayInfo(); getDisplay().getDisplayInfo(displayInfo); mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo); Rect udfpsBounds = udfpsProps.getLocation().getRect(); udfpsBounds.scale(mScaleFactor); final Rect overlayBounds = new Rect( 0, /* left */ displayInfo.getNaturalHeight() / 2, /* top */ displayInfo.getNaturalWidth(), /* right */ displayInfo.getNaturalHeight() /* botom */); UdfpsOverlayParams params = new UdfpsOverlayParams( udfpsBounds, overlayBounds, displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(), mScaleFactor, displayInfo.rotation); udfpsEnrollView.setOverlayParams(params); private void setUdfpsEnrollHelper() { mUdfpsEnrollHelper = (UdfpsEnrollHelper) getSupportFragmentManager().findFragmentByTag( FingerprintEnrollEnrolling.TAG_UDFPS_HELPER); if (mUdfpsEnrollHelper == null) { Loading @@ -1270,57 +1150,6 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .add(mUdfpsEnrollHelper, FingerprintEnrollEnrolling.TAG_UDFPS_HELPER) .commitAllowingStateLoss(); } udfpsEnrollView.setEnrollHelper(mUdfpsEnrollHelper); return udfpsEnrollView; } private void setOnHoverListener(boolean isLandscape, GlifLayout enrollLayout, UdfpsEnrollView udfpsEnrollView) { if (!mIsAccessibilityEnabled) return; final Context context = getApplicationContext(); final View.OnHoverListener onHoverListener = (v, event) -> { // Map the touch to portrait mode if the device is in // landscape mode. final Point scaledTouch = mUdfpsUtils.getTouchInNativeCoordinates(event.getPointerId(0), event, udfpsEnrollView.getOverlayParams()); if (mUdfpsUtils.isWithinSensorArea(event.getPointerId(0), event, udfpsEnrollView.getOverlayParams())) { return false; } final String theStr = mUdfpsUtils.onTouchOutsideOfSensorArea( mAccessibilityManager.isTouchExplorationEnabled(), context, scaledTouch.x, scaledTouch.y, udfpsEnrollView.getOverlayParams()); if (theStr != null) { v.announceForAccessibility(theStr); } return false; }; enrollLayout.findManagedViewById(isLandscape ? R.id.sud_landscape_content_area : R.id.sud_layout_content).setOnHoverListener(onHoverListener); } @VisibleForTesting boolean hasOverlap(View view1, View view2) { int[] firstPosition = new int[2]; int[] secondPosition = new int[2]; view1.getLocationOnScreen(firstPosition); view2.getLocationOnScreen(secondPosition); // Rect constructor parameters: left, top, right, bottom Rect rectView1 = new Rect(firstPosition[0], firstPosition[1], firstPosition[0] + view1.getMeasuredWidth(), firstPosition[1] + view1.getMeasuredHeight()); Rect rectView2 = new Rect(secondPosition[0], secondPosition[1], secondPosition[0] + view2.getMeasuredWidth(), secondPosition[1] + view2.getMeasuredHeight()); return rectView1.intersect(rectView2); } public static class IconTouchDialog extends InstrumentedDialogFragment { Loading tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java +17 −5 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.os.Vibrator; import android.view.Display; import android.view.Surface; import android.view.View; import android.view.accessibility.AccessibilityManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; Loading Loading @@ -314,11 +315,17 @@ public class FingerprintEnrollEnrollingTest { @Test public void fingerprintUdfpsOverlayEnrollment_descriptionViewGoneWithOverlap() { initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL); doReturn(true).when(mActivity).hasOverlap(any(), any()); when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0); createActivity(); final GlifLayout defaultLayout = spy(mActivity.findViewById(R.id.setup_wizard_layout)); final UdfpsEnrollEnrollingView defaultLayout = spy( mActivity.findViewById(R.id.setup_wizard_layout)); doReturn(true).when(defaultLayout).hasOverlap(any(), any()); // Somehow spy doesn't work, and we need to call initView manually. defaultLayout.initView(mFingerprintManager.getSensorPropertiesInternal().get(0), mActivity.mUdfpsEnrollHelper, mActivity.getSystemService(AccessibilityManager.class)); final TextView descriptionTextView = defaultLayout.getDescriptionTextView(); defaultLayout.getViewTreeObserver().dispatchOnDraw(); Loading @@ -328,11 +335,17 @@ public class FingerprintEnrollEnrollingTest { @Test public void fingerprintUdfpsOverlayEnrollment_descriptionViewVisibleWithoutOverlap() { initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL); doReturn(false).when(mActivity).hasOverlap(any(), any()); when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0); createActivity(); final GlifLayout defaultLayout = spy(mActivity.findViewById(R.id.setup_wizard_layout)); final UdfpsEnrollEnrollingView defaultLayout = spy( mActivity.findViewById(R.id.setup_wizard_layout)); doReturn(false).when(defaultLayout).hasOverlap(any(), any()); // Somehow spy doesn't work, and we need to call initView manually. defaultLayout.initView(mFingerprintManager.getSensorPropertiesInternal().get(0), mActivity.mUdfpsEnrollHelper, mActivity.getSystemService(AccessibilityManager.class)); final TextView descriptionTextView = defaultLayout.getDescriptionTextView(); defaultLayout.getViewTreeObserver().dispatchOnDraw(); Loading Loading @@ -591,7 +604,6 @@ public class FingerprintEnrollEnrollingTest { mContext = spy(RuntimeEnvironment.application); mActivity = spy(FingerprintEnrollEnrolling.class); when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props); when(mContext.getDisplay()).thenReturn(mMockDisplay); when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0); Loading Loading
res/layout-land/udfps_enroll_enrolling.xmldeleted 100644 → 0 +0 −101 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2021 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" android:id="@+id/setup_wizard_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout="@layout/sud_glif_blank_template" style="?attr/fingerprint_layout_theme"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:clipToPadding="false" android:clipChildren="false"> <!-- Both texts are kept as separate text views so it doesn't jump around in portrait. See layouts/fingerprint_enroll_enrolling_base.xml. --> <LinearLayout android:id="@+id/layout_container" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:layout_marginStart="?attr/sudMarginStart" android:layout_marginEnd="@dimen/enroll_margin_end" android:layout_marginBottom="@dimen/sud_content_frame_padding_bottom" android:paddingStart="@dimen/enroll_padding_start" android:paddingEnd="@dimen/enroll_padding_end" android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false" android:fillViewport="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:clipChildren="false" android:clipToPadding="false"> <ImageView android:id="@+id/sud_layout_icon" style="@style/SudGlifIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="fitStart" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" android:src="@drawable/ic_lock" /> <TextView android:id="@+id/suc_layout_title" style="@style/SudGlifHeaderTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="0dp" android:layout_marginEnd="0dp" /> <TextView style="@style/SudDescription.Glif" android:id="@+id/sud_layout_subtitle" android:layout_width="match_parent" android:layout_height="wrap_content"/> <Space android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout> </ScrollView> </LinearLayout> </LinearLayout> <include layout="@layout/udfps_enroll_view" /> </com.google.android.setupdesign.GlifLayout> No newline at end of file
res/layout/udfps_enroll_enrolling.xml +2 −2 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ ~ limitations under the License. --> <com.google.android.setupdesign.GlifLayout <com.android.settings.biometrics.fingerprint.UdfpsEnrollEnrollingView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" Loading Loading @@ -78,4 +78,4 @@ </LinearLayout> </LinearLayout> </com.google.android.setupdesign.GlifLayout> </com.android.settings.biometrics.fingerprint.UdfpsEnrollEnrollingView>
src/com/android/settings/biometrics/BiometricEnrollBase.java +10 −7 Original line number Diff line number Diff line Loading @@ -133,6 +133,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { protected long mChallenge; protected boolean mFromSettingsSummary; protected FooterBarMixin mFooterBarMixin; protected boolean mShouldSetFooterBarBackground = true; @Nullable protected ScreenSizeFoldProvider mScreenSizeFoldProvider; @Nullable Loading Loading @@ -191,6 +192,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { super.onPostCreate(savedInstanceState); initViews(); if (mShouldSetFooterBarBackground) { @SuppressLint("VisibleForTests") final LinearLayout buttonContainer = mFooterBarMixin != null ? mFooterBarMixin.getButtonContainer() Loading @@ -199,6 +201,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { buttonContainer.setBackgroundColor(getBackgroundColor()); } } } @Override public void onAttachedToWindow() { Loading Loading @@ -331,7 +334,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity { } @ColorInt private int getBackgroundColor() { public int getBackgroundColor() { final ColorStateList stateList = Utils.getColorAttr(this, android.R.attr.windowBackground); return stateList != null ? stateList.getDefaultColor() : Color.TRANSPARENT; } Loading
src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java +13 −184 Original line number Diff line number Diff line Loading @@ -32,10 +32,8 @@ import android.content.Intent; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.Animatable2; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; Loading @@ -48,22 +46,16 @@ import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; import android.text.TextUtils; import android.util.FeatureFlagUtils; import android.util.Log; import android.view.DisplayInfo; import android.view.MotionEvent; import android.view.OrientationEventListener; import android.view.Surface; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; Loading @@ -79,25 +71,20 @@ import com.android.settings.biometrics.BiometricUtils; import com.android.settings.biometrics.BiometricsEnrollEnrolling; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settingslib.display.DisplayDensityUtils; import com.android.settingslib.udfps.UdfpsOverlayParams; import com.android.settingslib.udfps.UdfpsUtils; import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieCompositionFactory; import com.airbnb.lottie.LottieProperty; import com.airbnb.lottie.model.KeyPath; import com.google.android.setupcompat.template.FooterActionButton; 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 com.google.android.setupdesign.template.DescriptionMixin; import com.google.android.setupdesign.template.HeaderMixin; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Locale; /** * Activity which handles the actual enrolling for fingerprint. Loading Loading @@ -176,8 +163,6 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { @VisibleForTesting @Nullable UdfpsEnrollHelper mUdfpsEnrollHelper; // TODO(b/260617060): Do not hard-code mScaleFactor, referring to AuthController. private float mScaleFactor = 1.0f; private ObjectAnimator mProgressAnim; private TextView mErrorText; private Interpolator mFastOutSlowInInterpolator; Loading Loading @@ -206,7 +191,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { private boolean mHaveShownSfpsLeftEdgeLottie; private boolean mHaveShownSfpsRightEdgeLottie; private boolean mShouldShowLottie; private UdfpsUtils mUdfpsUtils; private ObjectAnimator mHelpAnimation; private OrientationEventListener mOrientationEventListener; Loading Loading @@ -251,88 +236,17 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { mAccessibilityManager = getSystemService(AccessibilityManager.class); mIsAccessibilityEnabled = mAccessibilityManager.isEnabled(); mUdfpsUtils = new UdfpsUtils(); final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale( Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL); listenOrientationEvent(); if (mCanAssumeUdfps) { int rotation = getApplicationContext().getDisplay().getRotation(); final GlifLayout layout = (GlifLayout) getLayoutInflater().inflate( final UdfpsEnrollEnrollingView layout = (UdfpsEnrollEnrollingView) getLayoutInflater().inflate( R.layout.udfps_enroll_enrolling, null, false); final UdfpsEnrollView udfpsEnrollView = layout.findViewById(R.id.udfps_animation_view); updateUdfpsEnrollView(udfpsEnrollView, props.get(0)); switch (rotation) { case Surface.ROTATION_90: final View sudContent = layout.findViewById(R.id.sud_layout_content); if (sudContent != null) { sudContent.setPadding(sudContent.getPaddingLeft(), 0, sudContent.getPaddingRight(), sudContent.getPaddingBottom()); } final LinearLayout layoutContainer = layout.findViewById( R.id.layout_container); final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); lp.setMarginEnd((int) getResources().getDimension( R.dimen.rotation_90_enroll_margin_end)); layoutContainer.setPaddingRelative((int) getResources().getDimension( R.dimen.rotation_90_enroll_padding_start), 0, isLayoutRtl ? 0 : (int) getResources().getDimension( R.dimen.rotation_90_enroll_padding_end), 0); layoutContainer.setLayoutParams(lp); setOnHoverListener(true, layout, udfpsEnrollView); setContentView(layout, lp); break; case Surface.ROTATION_0: case Surface.ROTATION_180: // In the portrait mode, layout_container's height is 0, so it's // always shown at the bottom of the screen. final FrameLayout portraitLayoutContainer = layout.findViewById( R.id.layout_container); // In the portrait mode, the title and lottie animation view may // overlap when title needs three lines, so adding some paddings // between them, and adjusting the fp progress view here accordingly. final int layoutLottieAnimationPadding = (int) getResources() .getDimension(R.dimen.udfps_lottie_padding_top); portraitLayoutContainer.setPadding(0, layoutLottieAnimationPadding, 0, 0); final ImageView progressView = udfpsEnrollView.findViewById( R.id.udfps_enroll_animation_fp_progress_view); progressView.setPadding(0, -(layoutLottieAnimationPadding), 0, layoutLottieAnimationPadding); final ImageView fingerprintView = udfpsEnrollView.findViewById( R.id.udfps_enroll_animation_fp_view); fingerprintView.setPadding(0, -layoutLottieAnimationPadding, 0, layoutLottieAnimationPadding); // TODO(b/260970216) Instead of hiding the description text view, we should // make the header view scrollable if the text is too long. // If description text view has overlap with udfps progress view, hide it. View view = layout.getDescriptionTextView(); layout.getViewTreeObserver().addOnDrawListener(() -> { if (view.getVisibility() == View.VISIBLE && hasOverlap(view, udfpsEnrollView)) { view.setVisibility(View.GONE); } }); setUdfpsEnrollHelper(); layout.initView(props.get(0), mUdfpsEnrollHelper, mAccessibilityManager); setOnHoverListener(false, layout, udfpsEnrollView); setContentView(layout); break; case Surface.ROTATION_270: default: setOnHoverListener(true, layout, udfpsEnrollView); setContentView(layout); break; } setDescriptionText(R.string.security_settings_udfps_enroll_start_message); } else if (mCanAssumeSfps) { setContentView(R.layout.sfps_enroll_enrolling); Loading Loading @@ -372,22 +286,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .build() ); if (FeatureFlagUtils.isEnabled(getApplicationContext(), FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) { // Remove the space view and make the width of footer button container WRAP_CONTENT // to avoid hiding the udfps view progress bar bottom. final LinearLayout buttonContainer = mFooterBarMixin.getButtonContainer(); View spaceView = null; for (int i = 0; i < buttonContainer.getChildCount(); i++) { if (!(buttonContainer.getChildAt(i) instanceof FooterActionButton)) { spaceView = buttonContainer.getChildAt(i); break; } } if (spaceView != null) { spaceView.setVisibility(View.GONE); buttonContainer.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; } // If it's udfps, set the background color only for secondary button if necessary. if (mCanAssumeUdfps) { mShouldSetFooterBarBackground = false; ((UdfpsEnrollEnrollingView) getLayout()).setSecondaryButtonBackground( getBackgroundColor()); } final LayerDrawable fingerprintDrawable = mProgressBar != null Loading Loading @@ -1237,30 +1140,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { } } private UdfpsEnrollView updateUdfpsEnrollView(UdfpsEnrollView udfpsEnrollView, FingerprintSensorPropertiesInternal udfpsProps) { DisplayInfo displayInfo = new DisplayInfo(); getDisplay().getDisplayInfo(displayInfo); mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo); Rect udfpsBounds = udfpsProps.getLocation().getRect(); udfpsBounds.scale(mScaleFactor); final Rect overlayBounds = new Rect( 0, /* left */ displayInfo.getNaturalHeight() / 2, /* top */ displayInfo.getNaturalWidth(), /* right */ displayInfo.getNaturalHeight() /* botom */); UdfpsOverlayParams params = new UdfpsOverlayParams( udfpsBounds, overlayBounds, displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(), mScaleFactor, displayInfo.rotation); udfpsEnrollView.setOverlayParams(params); private void setUdfpsEnrollHelper() { mUdfpsEnrollHelper = (UdfpsEnrollHelper) getSupportFragmentManager().findFragmentByTag( FingerprintEnrollEnrolling.TAG_UDFPS_HELPER); if (mUdfpsEnrollHelper == null) { Loading @@ -1270,57 +1150,6 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling { .add(mUdfpsEnrollHelper, FingerprintEnrollEnrolling.TAG_UDFPS_HELPER) .commitAllowingStateLoss(); } udfpsEnrollView.setEnrollHelper(mUdfpsEnrollHelper); return udfpsEnrollView; } private void setOnHoverListener(boolean isLandscape, GlifLayout enrollLayout, UdfpsEnrollView udfpsEnrollView) { if (!mIsAccessibilityEnabled) return; final Context context = getApplicationContext(); final View.OnHoverListener onHoverListener = (v, event) -> { // Map the touch to portrait mode if the device is in // landscape mode. final Point scaledTouch = mUdfpsUtils.getTouchInNativeCoordinates(event.getPointerId(0), event, udfpsEnrollView.getOverlayParams()); if (mUdfpsUtils.isWithinSensorArea(event.getPointerId(0), event, udfpsEnrollView.getOverlayParams())) { return false; } final String theStr = mUdfpsUtils.onTouchOutsideOfSensorArea( mAccessibilityManager.isTouchExplorationEnabled(), context, scaledTouch.x, scaledTouch.y, udfpsEnrollView.getOverlayParams()); if (theStr != null) { v.announceForAccessibility(theStr); } return false; }; enrollLayout.findManagedViewById(isLandscape ? R.id.sud_landscape_content_area : R.id.sud_layout_content).setOnHoverListener(onHoverListener); } @VisibleForTesting boolean hasOverlap(View view1, View view2) { int[] firstPosition = new int[2]; int[] secondPosition = new int[2]; view1.getLocationOnScreen(firstPosition); view2.getLocationOnScreen(secondPosition); // Rect constructor parameters: left, top, right, bottom Rect rectView1 = new Rect(firstPosition[0], firstPosition[1], firstPosition[0] + view1.getMeasuredWidth(), firstPosition[1] + view1.getMeasuredHeight()); Rect rectView2 = new Rect(secondPosition[0], secondPosition[1], secondPosition[0] + view2.getMeasuredWidth(), secondPosition[1] + view2.getMeasuredHeight()); return rectView1.intersect(rectView2); } public static class IconTouchDialog extends InstrumentedDialogFragment { Loading
tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java +17 −5 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.os.Vibrator; import android.view.Display; import android.view.Surface; import android.view.View; import android.view.accessibility.AccessibilityManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; Loading Loading @@ -314,11 +315,17 @@ public class FingerprintEnrollEnrollingTest { @Test public void fingerprintUdfpsOverlayEnrollment_descriptionViewGoneWithOverlap() { initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL); doReturn(true).when(mActivity).hasOverlap(any(), any()); when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0); createActivity(); final GlifLayout defaultLayout = spy(mActivity.findViewById(R.id.setup_wizard_layout)); final UdfpsEnrollEnrollingView defaultLayout = spy( mActivity.findViewById(R.id.setup_wizard_layout)); doReturn(true).when(defaultLayout).hasOverlap(any(), any()); // Somehow spy doesn't work, and we need to call initView manually. defaultLayout.initView(mFingerprintManager.getSensorPropertiesInternal().get(0), mActivity.mUdfpsEnrollHelper, mActivity.getSystemService(AccessibilityManager.class)); final TextView descriptionTextView = defaultLayout.getDescriptionTextView(); defaultLayout.getViewTreeObserver().dispatchOnDraw(); Loading @@ -328,11 +335,17 @@ public class FingerprintEnrollEnrollingTest { @Test public void fingerprintUdfpsOverlayEnrollment_descriptionViewVisibleWithoutOverlap() { initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL); doReturn(false).when(mActivity).hasOverlap(any(), any()); when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0); createActivity(); final GlifLayout defaultLayout = spy(mActivity.findViewById(R.id.setup_wizard_layout)); final UdfpsEnrollEnrollingView defaultLayout = spy( mActivity.findViewById(R.id.setup_wizard_layout)); doReturn(false).when(defaultLayout).hasOverlap(any(), any()); // Somehow spy doesn't work, and we need to call initView manually. defaultLayout.initView(mFingerprintManager.getSensorPropertiesInternal().get(0), mActivity.mUdfpsEnrollHelper, mActivity.getSystemService(AccessibilityManager.class)); final TextView descriptionTextView = defaultLayout.getDescriptionTextView(); defaultLayout.getViewTreeObserver().dispatchOnDraw(); Loading Loading @@ -591,7 +604,6 @@ public class FingerprintEnrollEnrollingTest { mContext = spy(RuntimeEnvironment.application); mActivity = spy(FingerprintEnrollEnrolling.class); when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props); when(mContext.getDisplay()).thenReturn(mMockDisplay); when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0); Loading