Loading packages/SystemUI/res/layout/status_bar_expanded.xml +0 −12 Original line number Diff line number Diff line Loading @@ -65,18 +65,6 @@ android:layout_gravity="center" android:scaleType="centerCrop"/> <!-- Fingerprint --> <!-- AOD dashed fingerprint icon with moving dashes --> <com.airbnb.lottie.LottieAnimationView android:id="@+id/lock_udfps_aod_fp" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/lock_icon_padding" android:layout_gravity="center" android:scaleType="centerCrop" systemui:lottie_autoPlay="false" systemui:lottie_loop="true" systemui:lottie_rawRes="@raw/udfps_aod_fp"/> </com.android.keyguard.LockIconView> <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer Loading packages/SystemUI/res/layout/udfps_aod_lock_icon.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <!-- ~ 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.airbnb.lottie.LottieAnimationView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:id="@+id/lock_udfps_aod_fp" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/lock_icon_padding" android:layout_gravity="center" android:scaleType="centerCrop" systemui:lottie_autoPlay="false" systemui:lottie_loop="true" systemui:lottie_rawRes="@raw/udfps_aod_fp"/> No newline at end of file packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +30 −28 Original line number Diff line number Diff line Loading @@ -22,8 +22,8 @@ import static com.android.systemui.classifier.Classifier.LOCK_ICON; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInProgressOffset; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; Loading @@ -38,6 +38,7 @@ import android.util.DisplayMetrics; import android.util.MathUtils; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -98,9 +99,10 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull private final AccessibilityManager mAccessibilityManager; @NonNull private final ConfigurationController mConfigurationController; @NonNull private final DelayableExecutor mExecutor; @NonNull private final LayoutInflater mLayoutInflater; private boolean mUdfpsEnrolled; @NonNull private LottieAnimationView mAodFp; @Nullable private LottieAnimationView mAodFp; @NonNull private final AnimatedVectorDrawable mFpToUnlockIcon; @NonNull private final AnimatedVectorDrawable mLockToUnlockIcon; Loading Loading @@ -154,7 +156,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull ConfigurationController configurationController, @NonNull @Main DelayableExecutor executor, @Nullable Vibrator vibrator, @Nullable AuthRippleController authRippleController @Nullable AuthRippleController authRippleController, @NonNull @Main Resources resources, @NonNull LayoutInflater inflater ) { super(view); mStatusBarStateController = statusBarStateController; Loading @@ -168,27 +172,19 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mExecutor = executor; mVibrator = vibrator; mAuthRippleController = authRippleController; mLayoutInflater = inflater; final Context context = view.getContext(); mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp); mMaxBurnInOffsetX = context.getResources() .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x); mMaxBurnInOffsetY = context.getResources() .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); mMaxBurnInOffsetX = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x); mMaxBurnInOffsetY = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); mUnlockIcon = mView.getContext().getResources().getDrawable( R.drawable.ic_unlock, mView.getContext().getTheme()); mLockIcon = mView.getContext().getResources().getDrawable( R.anim.lock_to_unlock, mView.getContext().getTheme()); mFpToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable( mUnlockIcon = resources.getDrawable(R.drawable.ic_unlock, mView.getContext().getTheme()); mLockIcon = resources.getDrawable(R.anim.lock_to_unlock, mView.getContext().getTheme()); mFpToUnlockIcon = (AnimatedVectorDrawable) resources.getDrawable( R.anim.fp_to_unlock, mView.getContext().getTheme()); mLockToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable( R.anim.lock_to_unlock, mLockToUnlockIcon = (AnimatedVectorDrawable) resources.getDrawable(R.anim.lock_to_unlock, mView.getContext().getTheme()); mUnlockedLabel = context.getResources().getString(R.string.accessibility_unlock_button); mLockedLabel = context.getResources().getString(R.string.accessibility_lock_icon); mUnlockedLabel = resources.getString(R.string.accessibility_unlock_button); mLockedLabel = resources.getString(R.string.accessibility_lock_icon); dumpManager.registerDumpable("LockIconViewController", this); } Loading Loading @@ -300,7 +296,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mView.setContentDescription(null); } if (!mShowAODFpIcon) { if (!mShowAODFpIcon && mAodFp != null) { mAodFp.setVisibility(View.INVISIBLE); mAodFp.setContentDescription(null); } Loading Loading @@ -416,11 +412,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme - mMaxBurnInOffsetY, mInterpolatedDarkAmount); float progress = MathUtils.lerp(0f, getBurnInProgressOffset(), mInterpolatedDarkAmount); if (mAodFp != null) { mAodFp.setTranslationX(offsetX); mAodFp.setTranslationY(offsetY); mAodFp.setProgress(progress); mAodFp.setAlpha(255 * mInterpolatedDarkAmount); } } private void updateIsUdfpsEnrolled() { boolean wasUdfpsSupported = mUdfpsSupported; Loading @@ -430,6 +428,10 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mView.setUseBackground(mUdfpsSupported); mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled(); if (!wasUdfpsEnrolled && mUdfpsEnrolled && mAodFp == null) { mLayoutInflater.inflate(R.layout.udfps_aod_lock_icon, mView); mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp); } if (wasUdfpsSupported != mUdfpsSupported || wasUdfpsEnrolled != mUdfpsEnrolled) { updateVisibility(); } Loading Loading @@ -651,7 +653,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme public boolean onTouchEvent(MotionEvent event, Runnable onGestureDetectedRunnable) { if (mSensorTouchLocation.contains((int) event.getX(), (int) event.getY()) && (mView.getVisibility() == View.VISIBLE || mAodFp.getVisibility() == View.VISIBLE)) { || (mAodFp != null && mAodFp.getVisibility() == View.VISIBLE))) { mOnGestureDetectedRunnable = onGestureDetectedRunnable; mGestureDetector.onTouchEvent(event); } Loading packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java +38 −4 Original line number Diff line number Diff line Loading @@ -18,9 +18,10 @@ package com.android.systemui.keyguard; import static junit.framework.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -37,6 +38,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.DisplayMetrics; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -96,6 +98,7 @@ public class LockIconViewControllerTest extends SysuiTestCase { private @Mock Vibrator mVibrator; private @Mock AuthRippleController mAuthRippleController; private @Mock LottieAnimationView mAodFp; private @Mock LayoutInflater mLayoutInflater; private LockIconViewController mLockIconViewController; Loading @@ -120,11 +123,11 @@ public class LockIconViewControllerTest extends SysuiTestCase { when(mLockIconView.getResources()).thenReturn(mResources); when(mLockIconView.getContext()).thenReturn(mContext); when(mLockIconView.findViewById(R.layout.udfps_aod_lock_icon)).thenReturn(mAodFp); when(mContext.getResources()).thenReturn(mResources); when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics); when(mLockIconView.findViewById(anyInt())).thenReturn(mAodFp); when(mResources.getString(R.string.accessibility_unlock_button)).thenReturn(UNLOCKED_LABEL); when(mResources.getDrawable(anyInt(), anyObject())).thenReturn(mIconDrawable); when(mResources.getDrawable(anyInt(), any())).thenReturn(mIconDrawable); when(mKeyguardStateController.isShowing()).thenReturn(true); when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false); Loading @@ -144,10 +147,41 @@ public class LockIconViewControllerTest extends SysuiTestCase { mConfigurationController, mDelayableExecutor, mVibrator, mAuthRippleController mAuthRippleController, mResources, mLayoutInflater ); } @Test public void testIgnoreUdfpsWhenNotSupported() { // GIVEN Udpfs sensor is NOT available mLockIconViewController.init(); captureAttachListener(); // WHEN the view is attached mAttachListener.onViewAttachedToWindow(mLockIconView); // THEN lottie animation should NOT be inflated verify(mLayoutInflater, never()).inflate(eq(R.layout.udfps_aod_lock_icon), any()); } @Test public void testInflateUdfpsWhenSupported() { // GIVEN Udpfs sensor is available setupUdfps(); when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(true); mLockIconViewController.init(); captureAttachListener(); // WHEN the view is attached mAttachListener.onViewAttachedToWindow(mLockIconView); // THEN lottie animation should be inflated verify(mLayoutInflater).inflate(eq(R.layout.udfps_aod_lock_icon), any()); } @Test public void testUpdateFingerprintLocationOnInit() { // GIVEN fp sensor location is available pre-attached Loading Loading
packages/SystemUI/res/layout/status_bar_expanded.xml +0 −12 Original line number Diff line number Diff line Loading @@ -65,18 +65,6 @@ android:layout_gravity="center" android:scaleType="centerCrop"/> <!-- Fingerprint --> <!-- AOD dashed fingerprint icon with moving dashes --> <com.airbnb.lottie.LottieAnimationView android:id="@+id/lock_udfps_aod_fp" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/lock_icon_padding" android:layout_gravity="center" android:scaleType="centerCrop" systemui:lottie_autoPlay="false" systemui:lottie_loop="true" systemui:lottie_rawRes="@raw/udfps_aod_fp"/> </com.android.keyguard.LockIconView> <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer Loading
packages/SystemUI/res/layout/udfps_aod_lock_icon.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <!-- ~ 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.airbnb.lottie.LottieAnimationView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:systemui="http://schemas.android.com/apk/res-auto" android:id="@+id/lock_udfps_aod_fp" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="@dimen/lock_icon_padding" android:layout_gravity="center" android:scaleType="centerCrop" systemui:lottie_autoPlay="false" systemui:lottie_loop="true" systemui:lottie_rawRes="@raw/udfps_aod_fp"/> No newline at end of file
packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +30 −28 Original line number Diff line number Diff line Loading @@ -22,8 +22,8 @@ import static com.android.systemui.classifier.Classifier.LOCK_ICON; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInProgressOffset; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.AnimatedVectorDrawable; Loading @@ -38,6 +38,7 @@ import android.util.DisplayMetrics; import android.util.MathUtils; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -98,9 +99,10 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull private final AccessibilityManager mAccessibilityManager; @NonNull private final ConfigurationController mConfigurationController; @NonNull private final DelayableExecutor mExecutor; @NonNull private final LayoutInflater mLayoutInflater; private boolean mUdfpsEnrolled; @NonNull private LottieAnimationView mAodFp; @Nullable private LottieAnimationView mAodFp; @NonNull private final AnimatedVectorDrawable mFpToUnlockIcon; @NonNull private final AnimatedVectorDrawable mLockToUnlockIcon; Loading Loading @@ -154,7 +156,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme @NonNull ConfigurationController configurationController, @NonNull @Main DelayableExecutor executor, @Nullable Vibrator vibrator, @Nullable AuthRippleController authRippleController @Nullable AuthRippleController authRippleController, @NonNull @Main Resources resources, @NonNull LayoutInflater inflater ) { super(view); mStatusBarStateController = statusBarStateController; Loading @@ -168,27 +172,19 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mExecutor = executor; mVibrator = vibrator; mAuthRippleController = authRippleController; mLayoutInflater = inflater; final Context context = view.getContext(); mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp); mMaxBurnInOffsetX = context.getResources() .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x); mMaxBurnInOffsetY = context.getResources() .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); mMaxBurnInOffsetX = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x); mMaxBurnInOffsetY = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); mUnlockIcon = mView.getContext().getResources().getDrawable( R.drawable.ic_unlock, mView.getContext().getTheme()); mLockIcon = mView.getContext().getResources().getDrawable( R.anim.lock_to_unlock, mView.getContext().getTheme()); mFpToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable( mUnlockIcon = resources.getDrawable(R.drawable.ic_unlock, mView.getContext().getTheme()); mLockIcon = resources.getDrawable(R.anim.lock_to_unlock, mView.getContext().getTheme()); mFpToUnlockIcon = (AnimatedVectorDrawable) resources.getDrawable( R.anim.fp_to_unlock, mView.getContext().getTheme()); mLockToUnlockIcon = (AnimatedVectorDrawable) mView.getContext().getResources().getDrawable( R.anim.lock_to_unlock, mLockToUnlockIcon = (AnimatedVectorDrawable) resources.getDrawable(R.anim.lock_to_unlock, mView.getContext().getTheme()); mUnlockedLabel = context.getResources().getString(R.string.accessibility_unlock_button); mLockedLabel = context.getResources().getString(R.string.accessibility_lock_icon); mUnlockedLabel = resources.getString(R.string.accessibility_unlock_button); mLockedLabel = resources.getString(R.string.accessibility_lock_icon); dumpManager.registerDumpable("LockIconViewController", this); } Loading Loading @@ -300,7 +296,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mView.setContentDescription(null); } if (!mShowAODFpIcon) { if (!mShowAODFpIcon && mAodFp != null) { mAodFp.setVisibility(View.INVISIBLE); mAodFp.setContentDescription(null); } Loading Loading @@ -416,11 +412,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme - mMaxBurnInOffsetY, mInterpolatedDarkAmount); float progress = MathUtils.lerp(0f, getBurnInProgressOffset(), mInterpolatedDarkAmount); if (mAodFp != null) { mAodFp.setTranslationX(offsetX); mAodFp.setTranslationY(offsetY); mAodFp.setProgress(progress); mAodFp.setAlpha(255 * mInterpolatedDarkAmount); } } private void updateIsUdfpsEnrolled() { boolean wasUdfpsSupported = mUdfpsSupported; Loading @@ -430,6 +428,10 @@ public class LockIconViewController extends ViewController<LockIconView> impleme mView.setUseBackground(mUdfpsSupported); mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled(); if (!wasUdfpsEnrolled && mUdfpsEnrolled && mAodFp == null) { mLayoutInflater.inflate(R.layout.udfps_aod_lock_icon, mView); mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp); } if (wasUdfpsSupported != mUdfpsSupported || wasUdfpsEnrolled != mUdfpsEnrolled) { updateVisibility(); } Loading Loading @@ -651,7 +653,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme public boolean onTouchEvent(MotionEvent event, Runnable onGestureDetectedRunnable) { if (mSensorTouchLocation.contains((int) event.getX(), (int) event.getY()) && (mView.getVisibility() == View.VISIBLE || mAodFp.getVisibility() == View.VISIBLE)) { || (mAodFp != null && mAodFp.getVisibility() == View.VISIBLE))) { mOnGestureDetectedRunnable = onGestureDetectedRunnable; mGestureDetector.onTouchEvent(event); } Loading
packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java +38 −4 Original line number Diff line number Diff line Loading @@ -18,9 +18,10 @@ package com.android.systemui.keyguard; import static junit.framework.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; Loading @@ -37,6 +38,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.DisplayMetrics; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.accessibility.AccessibilityManager; Loading Loading @@ -96,6 +98,7 @@ public class LockIconViewControllerTest extends SysuiTestCase { private @Mock Vibrator mVibrator; private @Mock AuthRippleController mAuthRippleController; private @Mock LottieAnimationView mAodFp; private @Mock LayoutInflater mLayoutInflater; private LockIconViewController mLockIconViewController; Loading @@ -120,11 +123,11 @@ public class LockIconViewControllerTest extends SysuiTestCase { when(mLockIconView.getResources()).thenReturn(mResources); when(mLockIconView.getContext()).thenReturn(mContext); when(mLockIconView.findViewById(R.layout.udfps_aod_lock_icon)).thenReturn(mAodFp); when(mContext.getResources()).thenReturn(mResources); when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics); when(mLockIconView.findViewById(anyInt())).thenReturn(mAodFp); when(mResources.getString(R.string.accessibility_unlock_button)).thenReturn(UNLOCKED_LABEL); when(mResources.getDrawable(anyInt(), anyObject())).thenReturn(mIconDrawable); when(mResources.getDrawable(anyInt(), any())).thenReturn(mIconDrawable); when(mKeyguardStateController.isShowing()).thenReturn(true); when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false); Loading @@ -144,10 +147,41 @@ public class LockIconViewControllerTest extends SysuiTestCase { mConfigurationController, mDelayableExecutor, mVibrator, mAuthRippleController mAuthRippleController, mResources, mLayoutInflater ); } @Test public void testIgnoreUdfpsWhenNotSupported() { // GIVEN Udpfs sensor is NOT available mLockIconViewController.init(); captureAttachListener(); // WHEN the view is attached mAttachListener.onViewAttachedToWindow(mLockIconView); // THEN lottie animation should NOT be inflated verify(mLayoutInflater, never()).inflate(eq(R.layout.udfps_aod_lock_icon), any()); } @Test public void testInflateUdfpsWhenSupported() { // GIVEN Udpfs sensor is available setupUdfps(); when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(true); mLockIconViewController.init(); captureAttachListener(); // WHEN the view is attached mAttachListener.onViewAttachedToWindow(mLockIconView); // THEN lottie animation should be inflated verify(mLayoutInflater).inflate(eq(R.layout.udfps_aod_lock_icon), any()); } @Test public void testUpdateFingerprintLocationOnInit() { // GIVEN fp sensor location is available pre-attached Loading