diff options
20 files changed, 226 insertions, 73 deletions
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING index 3ffbe1d1c71b..2ea6513c4d77 100644 --- a/core/java/android/content/pm/TEST_MAPPING +++ b/core/java/android/content/pm/TEST_MAPPING @@ -101,20 +101,6 @@ ], "presubmit-large":[ { - "name":"CtsContentTestCases", - "options":[ - { - "exclude-annotation":"androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation":"org.junit.Ignore" - }, - { - "include-filter":"android.content.pm.cts" - } - ] - }, - { "name":"CtsUsesNativeLibraryTest", "options":[ { @@ -156,6 +142,20 @@ ], "postsubmit":[ { + "name":"CtsContentTestCases", + "options":[ + { + "exclude-annotation":"androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation":"org.junit.Ignore" + }, + { + "include-filter":"android.content.pm.cts" + } + ] + }, + { "name":"CtsAppSecurityHostTestCases", "options":[ { diff --git a/core/java/android/hardware/usb/UsbConfiguration.java b/core/java/android/hardware/usb/UsbConfiguration.java index 66269cb772f8..b25f47b11532 100644 --- a/core/java/android/hardware/usb/UsbConfiguration.java +++ b/core/java/android/hardware/usb/UsbConfiguration.java @@ -172,7 +172,8 @@ public class UsbConfiguration implements Parcelable { String name = in.readString(); int attributes = in.readInt(); int maxPower = in.readInt(); - Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader()); + Parcelable[] interfaces = in.readParcelableArray( + UsbInterface.class.getClassLoader(), UsbInterface.class); UsbConfiguration configuration = new UsbConfiguration(id, name, attributes, maxPower); configuration.setInterfaces(interfaces); return configuration; diff --git a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp index a95b6e37f5de..76f5c107c970 100644 --- a/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp +++ b/core/jni/com_android_internal_os_LongArrayMultiStateCounter.cpp @@ -127,16 +127,17 @@ static void native_writeToParcel(JNIEnv *env, jobject self, jlong nativePtr, job } } -static void throwReadRE(JNIEnv *env, binder_status_t status) { +static void throwReadException(JNIEnv *env, binder_status_t status) { ALOGE("Could not read LongArrayMultiStateCounter from Parcel, status = %d", status); - jniThrowRuntimeException(env, "Could not read LongArrayMultiStateCounter from Parcel"); + jniThrowException(env, "android.os.BadParcelableException", + "Could not read LongArrayMultiStateCounter from Parcel"); } #define THROW_AND_RETURN_ON_READ_ERROR(expr) \ { \ binder_status_t status = expr; \ if (status != STATUS_OK) { \ - throwReadRE(env, status); \ + throwReadException(env, status); \ return 0L; \ } \ } @@ -147,6 +148,11 @@ static jlong native_initFromParcel(JNIEnv *env, jclass theClass, jobject jParcel int32_t stateCount; THROW_AND_RETURN_ON_READ_ERROR(AParcel_readInt32(parcel.get(), &stateCount)); + if (stateCount < 0 || stateCount > 0xEFFF) { + throwReadException(env, STATUS_INVALID_OPERATION); + return 0L; + } + int32_t arrayLength; THROW_AND_RETURN_ON_READ_ERROR(AParcel_readInt32(parcel.get(), &arrayLength)); diff --git a/core/jni/com_android_internal_os_LongMultiStateCounter.cpp b/core/jni/com_android_internal_os_LongMultiStateCounter.cpp index 1712b3a8512b..ddf7a67e00ce 100644 --- a/core/jni/com_android_internal_os_LongMultiStateCounter.cpp +++ b/core/jni/com_android_internal_os_LongMultiStateCounter.cpp @@ -131,16 +131,17 @@ static void native_writeToParcel(JNIEnv *env, jobject self, jlong nativePtr, job } } -static void throwReadRE(JNIEnv *env, binder_status_t status) { +static void throwReadException(JNIEnv *env, binder_status_t status) { ALOGE("Could not read LongMultiStateCounter from Parcel, status = %d", status); - jniThrowRuntimeException(env, "Could not read LongMultiStateCounter from Parcel"); + jniThrowException(env, "android.os.BadParcelableException", + "Could not read LongMultiStateCounter from Parcel"); } #define THROW_AND_RETURN_ON_READ_ERROR(expr) \ { \ binder_status_t status = expr; \ if (status != STATUS_OK) { \ - throwReadRE(env, status); \ + throwReadException(env, status); \ return 0L; \ } \ } @@ -151,6 +152,11 @@ static jlong native_initFromParcel(JNIEnv *env, jclass theClass, jobject jParcel int32_t stateCount; THROW_AND_RETURN_ON_READ_ERROR(AParcel_readInt32(parcel.get(), &stateCount)); + if (stateCount < 0 || stateCount > 0xEFFF) { + throwReadException(env, STATUS_INVALID_OPERATION); + return 0L; + } + auto counter = std::make_unique<battery::LongMultiStateCounter>(stateCount, 0); for (battery::state_t state = 0; state < stateCount; state++) { diff --git a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java index 516dee7dc9aa..faccf1ad19a1 100644 --- a/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LongArrayMultiStateCounterTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import android.os.BadParcelableException; import android.os.Parcel; import androidx.test.filters.SmallTest; @@ -163,6 +164,45 @@ public class LongArrayMultiStateCounterTest { } @Test + public void createFromBadBundle() { + Parcel data = Parcel.obtain(); + int bundleLenPos = data.dataPosition(); + data.writeInt(0); + data.writeInt(0x4C444E42); // BaseBundle.BUNDLE_MAGIC + + int bundleStart = data.dataPosition(); + + data.writeInt(1); + data.writeString("key"); + data.writeInt(4); + int lazyValueLenPos = data.dataPosition(); + data.writeInt(0); + int lazyValueStart = data.dataPosition(); + data.writeString("com.android.internal.os.LongArrayMultiStateCounter"); + + // Invalid int16 value + data.writeInt(0x10000); // stateCount + data.writeInt(10); // arrayLength + for (int i = 0; i < 0x10000; ++i) { + data.writeLong(0); + } + + backPatchLength(data, lazyValueLenPos, lazyValueStart); + backPatchLength(data, bundleLenPos, bundleStart); + data.setDataPosition(0); + + assertThrows(BadParcelableException.class, + () -> data.readBundle().getParcelable("key", LongArrayMultiStateCounter.class)); + } + + private static void backPatchLength(Parcel parcel, int lengthPos, int startPos) { + int endPos = parcel.dataPosition(); + parcel.setDataPosition(lengthPos); + parcel.writeInt(endPos - startPos); + parcel.setDataPosition(endPos); + } + + @Test public void combineValues() { long[] values = new long[] {0, 1, 2, 3, 42}; LongArrayMultiStateCounter.LongArrayContainer container = diff --git a/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java b/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java index fc86ebe1c10e..341375357902 100644 --- a/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java +++ b/core/tests/coretests/src/com/android/internal/os/LongMultiStateCounterTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; +import android.os.BadParcelableException; import android.os.Parcel; import androidx.test.filters.SmallTest; @@ -210,4 +211,42 @@ public class LongMultiStateCounterTest { assertThrows(RuntimeException.class, () -> LongMultiStateCounter.CREATOR.createFromParcel(parcel)); } + + @Test + public void createFromBadBundle() { + Parcel data = Parcel.obtain(); + int bundleLenPos = data.dataPosition(); + data.writeInt(0); + data.writeInt(0x4C444E42); // BaseBundle.BUNDLE_MAGIC + + int bundleStart = data.dataPosition(); + + data.writeInt(1); + data.writeString("key"); + data.writeInt(4); + int lazyValueLenPos = data.dataPosition(); + data.writeInt(0); + int lazyValueStart = data.dataPosition(); + data.writeString("com.android.internal.os.LongMultiStateCounter"); + + // Invalid int16 value + data.writeInt(0x10000); // stateCount + for (int i = 0; i < 0x10000; ++i) { + data.writeLong(0); + } + + backPatchLength(data, lazyValueLenPos, lazyValueStart); + backPatchLength(data, bundleLenPos, bundleStart); + data.setDataPosition(0); + + assertThrows(BadParcelableException.class, + () -> data.readBundle().getParcelable("key", LongMultiStateCounter.class)); + } + + private static void backPatchLength(Parcel parcel, int lengthPos, int startPos) { + int endPos = parcel.dataPosition(); + parcel.setDataPosition(lengthPos); + parcel.writeInt(endPos - startPos); + parcel.setDataPosition(endPos); + } } diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml index c2dba6c41d12..261b08d4356f 100644 --- a/packages/SystemUI/res/values/flags.xml +++ b/packages/SystemUI/res/values/flags.xml @@ -40,4 +40,7 @@ <!-- Whether face auth will immediately stop when the display state is OFF --> <bool name="flag_stop_face_auth_on_display_off">false</bool> + + <!-- Whether we want to stop pulsing while running the face scanning animation --> + <bool name="flag_stop_pulsing_face_scanning_animation">true</bool> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt index 403c80985377..95e2dba88b90 100644 --- a/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt +++ b/packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt @@ -36,6 +36,8 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.settingslib.Utils import com.android.systemui.biometrics.AuthController +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.log.ScreenDecorationsLogger import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.util.asIndenting @@ -54,6 +56,7 @@ class FaceScanningOverlay( val mainExecutor: Executor, val logger: ScreenDecorationsLogger, val authController: AuthController, + val featureFlags: FeatureFlags, ) : ScreenDecorations.DisplayCutoutView(context, pos) { private var showScanningAnim = false private val rimPaint = Paint() @@ -294,6 +297,15 @@ class FaceScanningOverlay( } private fun createFaceScanningRimAnimator(): AnimatorSet { + val dontPulse = featureFlags.isEnabled(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION) + if (dontPulse) { + return AnimatorSet().apply { + playSequentially( + cameraProtectionAnimator, + createRimAppearAnimator(), + ) + } + } return AnimatorSet().apply { playSequentially( cameraProtectionAnimator, diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt index b538085fa40d..1ca57e77034c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt @@ -60,6 +60,13 @@ object Utils { return dp * (density / DisplayMetrics.DENSITY_DEFAULT) } + /** + * Note: Talkback 14.0 has new rate-limitation design to reduce frequency + * of TYPE_WINDOW_CONTENT_CHANGED events to once every 30 seconds. + * (context: b/281765653#comment18) + * Using {@link View#announceForAccessibility} instead as workaround when sending events + * exceeding this frequency is required. + */ @JvmStatic fun notifyAccessibilityContentChanged(am: AccessibilityManager, view: ViewGroup) { if (!am.isEnabled) { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt index 40bb8715f8c5..1bf7ffa8cff6 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt @@ -47,7 +47,6 @@ import com.android.systemui.biometrics.AuthBiometricView.Callback import com.android.systemui.biometrics.AuthBiometricViewAdapter import com.android.systemui.biometrics.AuthIconController import com.android.systemui.biometrics.AuthPanelController -import com.android.systemui.biometrics.Utils import com.android.systemui.biometrics.domain.model.BiometricModalities import com.android.systemui.biometrics.shared.model.BiometricModality import com.android.systemui.biometrics.shared.model.PromptKind @@ -83,9 +82,6 @@ object BiometricViewBinder { applicationScope: CoroutineScope, ): AuthBiometricViewAdapter { val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!! - fun notifyAccessibilityChanged() { - Utils.notifyAccessibilityContentChanged(accessibilityManager, view) - } val textColorError = view.resources.getColor(R.color.biometric_dialog_error, view.context.theme) @@ -327,21 +323,14 @@ object BiometricViewBinder { } } - // not sure why this is here, but the legacy code did it probably needed? - launch { - viewModel.isAuthenticating.collect { isAuthenticating -> - if (isAuthenticating) { - notifyAccessibilityChanged() - } - } - } - // dismiss prompt when authenticated and confirmed launch { viewModel.isAuthenticated.collect { authState -> // Disable background view for cancelling authentication once authenticated, // and remove from talkback if (authState.isAuthenticated) { + // Prevents Talkback from speaking subtitle after already authenticated + subtitleView.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO backgroundView.setOnClickListener(null) backgroundView.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO @@ -358,7 +347,6 @@ object BiometricViewBinder { view.announceForAccessibility( view.resources.getString(R.string.biometric_dialog_authenticated) ) - notifyAccessibilityChanged() launch { delay(authState.delay) @@ -390,7 +378,18 @@ object BiometricViewBinder { !accessibilityManager.isEnabled || !accessibilityManager.isTouchExplorationEnabled - notifyAccessibilityChanged() + /** + * Note: Talkback 14.0 has new rate-limitation design to reduce frequency of + * TYPE_WINDOW_CONTENT_CHANGED events to once every 30 seconds. (context: + * b/281765653#comment18) Using {@link View#announceForAccessibility} + * instead as workaround since sending events exceeding this frequency is + * required. + */ + indicatorMessageView?.text?.let { + if (it.isNotBlank()) { + view.announceForAccessibility(it) + } + } } } } diff --git a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt index 4e62104034ee..ac0d3c8f3d36 100644 --- a/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt @@ -34,6 +34,7 @@ import com.android.systemui.FaceScanningOverlay import com.android.systemui.biometrics.AuthController import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.flags.FeatureFlags import com.android.systemui.log.ScreenDecorationsLogger import com.android.systemui.plugins.statusbar.StatusBarStateController import java.util.concurrent.Executor @@ -47,6 +48,7 @@ class FaceScanningProviderFactory @Inject constructor( private val keyguardUpdateMonitor: KeyguardUpdateMonitor, @Main private val mainExecutor: Executor, private val logger: ScreenDecorationsLogger, + private val featureFlags: FeatureFlags, ) : DecorProviderFactory() { private val display = context.display private val displayInfo = DisplayInfo() @@ -86,6 +88,7 @@ class FaceScanningProviderFactory @Inject constructor( keyguardUpdateMonitor, mainExecutor, logger, + featureFlags, ) ) } @@ -110,6 +113,7 @@ class FaceScanningOverlayProviderImpl( private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val mainExecutor: Executor, private val logger: ScreenDecorationsLogger, + private val featureFlags: FeatureFlags, ) : BoundDecorProvider() { override val viewId: Int = com.android.systemui.R.id.face_scanning_anim @@ -144,6 +148,7 @@ class FaceScanningOverlayProviderImpl( mainExecutor, logger, authController, + featureFlags ) view.id = viewId view.setColor(tintColor) diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index ee9482c730af..ee8fae599d41 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -273,6 +273,12 @@ object Flags { @JvmField val STOP_FACE_AUTH_ON_DISPLAY_OFF = resourceBooleanFlag(245, R.bool.flag_stop_face_auth_on_display_off, "stop_face_auth_on_display_off") + /** Flag to disable the face scanning animation pulsing. */ + // TODO(b/295245791): Tracking bug. + @JvmField val STOP_PULSING_FACE_SCANNING_ANIMATION = resourceBooleanFlag(246, + R.bool.flag_stop_pulsing_face_scanning_animation, + "stop_pulsing_face_scanning_animation") + // 300 - power menu // TODO(b/254512600): Tracking Bug @JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite") diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index 68e72c58972b..4418740e545f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -934,28 +934,41 @@ class KeyguardUnlockAnimationController @Inject constructor( /** * Called by [KeyguardViewMediator] to let us know that the remote animation has finished, and - * we should clean up all of our state. + * we should clean up all of our state. [showKeyguard] will tell us which surface should be + * visible after the animation has been completed or canceled. * * This is generally triggered by us, calling * [KeyguardViewMediator.finishSurfaceBehindRemoteAnimation]. */ - fun notifyFinishedKeyguardExitAnimation(cancelled: Boolean) { + fun notifyFinishedKeyguardExitAnimation(showKeyguard: Boolean) { // Cancel any pending actions. handler.removeCallbacksAndMessages(null) - // Make sure we made the surface behind fully visible, just in case. It should already be - // fully visible. The exit animation is finished, and we should not hold the leash anymore, - // so forcing it to 1f. - surfaceBehindAlpha = 1f - setSurfaceBehindAppearAmount(1f) + // The lockscreen surface is gone, so it is now safe to re-show the smartspace. + if (lockscreenSmartspace?.visibility == View.INVISIBLE) { + lockscreenSmartspace?.visibility = View.VISIBLE + } + + if (!showKeyguard) { + // Make sure we made the surface behind fully visible, just in case. It should already be + // fully visible. The exit animation is finished, and we should not hold the leash anymore, + // so forcing it to 1f. + surfaceBehindAlpha = 1f + setSurfaceBehindAppearAmount(1f) + + try { + launcherUnlockController?.setUnlockAmount(1f, false /* forceIfAnimating */) + } catch (e: RemoteException) { + Log.e(TAG, "Remote exception in notifyFinishedKeyguardExitAnimation", e) + } + } + + listeners.forEach { it.onUnlockAnimationFinished() } + + // Reset all state surfaceBehindAlphaAnimator.cancel() surfaceBehindEntryAnimator.cancel() wallpaperCannedUnlockAnimator.cancel() - try { - launcherUnlockController?.setUnlockAmount(1f, false /* forceIfAnimating */) - } catch (e: RemoteException) { - Log.e(TAG, "Remote exception in notifyFinishedKeyguardExitAnimation", e) - } // That target is no longer valid since the animation finished, null it out. surfaceBehindRemoteAnimationTargets = null @@ -965,13 +978,6 @@ class KeyguardUnlockAnimationController @Inject constructor( dismissAmountThresholdsReached = false willUnlockWithInWindowLauncherAnimations = false willUnlockWithSmartspaceTransition = false - - // The lockscreen surface is gone, so it is now safe to re-show the smartspace. - if (lockscreenSmartspace?.visibility == View.INVISIBLE) { - lockscreenSmartspace?.visibility = View.VISIBLE - } - - listeners.forEach { it.onUnlockAnimationFinished() } } /** diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 1a06b0184bc5..49ae876b677e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -2520,7 +2520,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, } else if (mSurfaceBehindRemoteAnimationRunning) { // We're already running the keyguard exit animation, likely due to an in-progress swipe // to unlock. - exitKeyguardAndFinishSurfaceBehindRemoteAnimation(false /* cancelled */); + exitKeyguardAndFinishSurfaceBehindRemoteAnimation(false /* showKeyguard */); } else if (!mHideAnimationRun) { if (DEBUG) Log.d(TAG, "tryKeyguardDone: starting pre-hide animation"); mHideAnimationRun = true; @@ -2966,7 +2966,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mContext.getMainExecutor().execute(() -> { if (finishedCallback == null) { mKeyguardUnlockAnimationControllerLazy.get() - .notifyFinishedKeyguardExitAnimation(false /* cancelled */); + .notifyFinishedKeyguardExitAnimation(false /* showKeyguard */); mInteractionJankMonitor.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION); return; } @@ -3083,7 +3083,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // A lock is pending, meaning the keyguard exit animation was cancelled because we're // re-locking. We should just end the surface-behind animation without exiting the // keyguard. The pending lock will be handled by onFinishedGoingToSleep(). - finishSurfaceBehindRemoteAnimation(true); + finishSurfaceBehindRemoteAnimation(true /* showKeyguard */); maybeHandlePendingLock(); } else { Log.d(TAG, "#handleCancelKeyguardExitAnimation: keyguard exit animation cancelled. " @@ -3092,7 +3092,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, // No lock is pending, so the animation was cancelled during the unlock sequence, but // we should end up unlocked. Show the surface and exit the keyguard. showSurfaceBehindKeyguard(); - exitKeyguardAndFinishSurfaceBehindRemoteAnimation(true /* cancelled */); + exitKeyguardAndFinishSurfaceBehindRemoteAnimation(false /* showKeyguard */); } } @@ -3103,12 +3103,13 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, * with the RemoteAnimation, actually hide the keyguard, and clean up state related to the * keyguard exit animation. * - * @param cancelled {@code true} if the animation was cancelled before it finishes. + * @param showKeyguard {@code true} if the animation was cancelled and keyguard should remain + * visible */ - public void exitKeyguardAndFinishSurfaceBehindRemoteAnimation(boolean cancelled) { + public void exitKeyguardAndFinishSurfaceBehindRemoteAnimation(boolean showKeyguard) { Log.d(TAG, "onKeyguardExitRemoteAnimationFinished"); if (!mSurfaceBehindRemoteAnimationRunning && !mSurfaceBehindRemoteAnimationRequested) { - Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished cancelled=" + cancelled + Log.d(TAG, "skip onKeyguardExitRemoteAnimationFinished showKeyguard=" + showKeyguard + " surfaceAnimationRunning=" + mSurfaceBehindRemoteAnimationRunning + " surfaceAnimationRequested=" + mSurfaceBehindRemoteAnimationRequested); return; @@ -3133,9 +3134,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, + " wasShowing=" + wasShowing); } - mKeyguardUnlockAnimationControllerLazy.get() - .notifyFinishedKeyguardExitAnimation(cancelled); - finishSurfaceBehindRemoteAnimation(cancelled); + finishSurfaceBehindRemoteAnimation(showKeyguard); // Dispatch the callback on animation finishes. mUpdateMonitor.dispatchKeyguardDismissAnimationFinished(); @@ -3199,7 +3198,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, * This does not set keyguard state to either locked or unlocked, it simply ends the remote * animation on the surface behind the keyguard. This can be called by */ - void finishSurfaceBehindRemoteAnimation(boolean cancelled) { + void finishSurfaceBehindRemoteAnimation(boolean showKeyguard) { + mKeyguardUnlockAnimationControllerLazy.get() + .notifyFinishedKeyguardExitAnimation(showKeyguard); + mSurfaceBehindRemoteAnimationRequested = false; mSurfaceBehindRemoteAnimationRunning = false; mKeyguardStateController.notifyKeyguardGoingAway(false); diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index 2f7644eb5c82..c7a7d97aff4f 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -499,6 +499,7 @@ public class NotificationShadeWindowViewController { MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0); event.setSource(InputDevice.SOURCE_TOUCHSCREEN); } + Log.w(TAG, "Canceling current touch event (should be very rare)"); mView.dispatchTouchEvent(event); event.recycle(); mTouchCancelled = true; diff --git a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt index 01d3a3931052..ea7cc3dcd119 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/FaceScanningProviderFactoryTest.kt @@ -27,6 +27,8 @@ import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.biometrics.AuthController import com.android.systemui.decor.FaceScanningProviderFactory import com.android.systemui.dump.logcatLogBuffer +import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.log.ScreenDecorationsLogger import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.util.mockito.whenever @@ -80,6 +82,8 @@ class FaceScanningProviderFactoryTest : SysuiTestCase() { R.bool.config_fillMainBuiltInDisplayCutout, true ) + val featureFlags = FakeFeatureFlags() + featureFlags.set(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION, true) underTest = FaceScanningProviderFactory( authController, @@ -87,7 +91,8 @@ class FaceScanningProviderFactoryTest : SysuiTestCase() { statusBarStateController, keyguardUpdateMonitor, mock(Executor::class.java), - ScreenDecorationsLogger(logcatLogBuffer("FaceScanningProviderFactoryTest")) + ScreenDecorationsLogger(logcatLogBuffer("FaceScanningProviderFactoryTest")), + featureFlags, ) whenever(authController.faceSensorLocation).thenReturn(Point(10, 10)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 4cf5a4be0b60..13a1fe969ac8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -91,6 +91,8 @@ import com.android.systemui.decor.OverlayWindow; import com.android.systemui.decor.PrivacyDotCornerDecorProviderImpl; import com.android.systemui.decor.PrivacyDotDecorProviderFactory; import com.android.systemui.decor.RoundedCornerResDelegate; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.log.ScreenDecorationsLogger; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.settings.FakeDisplayTracker; @@ -225,13 +227,16 @@ public class ScreenDecorationsTest extends SysuiTestCase { doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders(); doReturn(mMockCutoutList).when(mCutoutFactory).getProviders(); + FakeFeatureFlags featureFlags = new FakeFeatureFlags(); + featureFlags.set(Flags.STOP_PULSING_FACE_SCANNING_ANIMATION, true); mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl( BOUNDS_POSITION_TOP, mAuthController, mStatusBarStateController, mKeyguardUpdateMonitor, mExecutor, - new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")))); + new ScreenDecorationsLogger(logcatLogBuffer("TestLogBuffer")), + featureFlags)); mScreenDecorations = spy(new ScreenDecorations(mContext, mExecutor, mSecureSettings, mTunerService, mUserTracker, mDisplayTracker, mDotViewController, mThreadFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 34ea91b94414..cb2daca1fe97 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -480,6 +480,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { TestableLooper.get(this).processAllMessages(); assertFalse(mViewMediator.isShowingAndNotOccluded()); + verify(mKeyguardUnlockAnimationController).notifyFinishedKeyguardExitAnimation(false); } @Test @@ -496,6 +497,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { TestableLooper.get(this).processAllMessages(); assertTrue(mViewMediator.isShowingAndNotOccluded()); + verify(mKeyguardUnlockAnimationController).notifyFinishedKeyguardExitAnimation(true); } @Test @@ -504,6 +506,9 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { startMockKeyguardExitAnimation(); cancelMockKeyguardExitAnimation(); + // Calling cancel above results in keyguard not visible, as there is no pending lock + verify(mKeyguardUnlockAnimationController).notifyFinishedKeyguardExitAnimation(false); + mViewMediator.maybeHandlePendingLock(); TestableLooper.get(this).processAllMessages(); @@ -518,9 +523,15 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { @Test @TestableLooper.RunWithLooper(setAsMainLooper = true) - public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimation() { + public void testStartKeyguardExitAnimation_expectSurfaceBehindRemoteAnimationAndExits() { startMockKeyguardExitAnimation(); assertTrue(mViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()); + + mViewMediator.mViewMediatorCallback.keyguardDonePending(true, + mUpdateMonitor.getCurrentUser()); + mViewMediator.mViewMediatorCallback.readyForKeyguardDone(); + TestableLooper.get(this).processAllMessages(); + verify(mKeyguardUnlockAnimationController).notifyFinishedKeyguardExitAnimation(false); } /** diff --git a/services/core/java/com/android/server/PendingIntentUtils.java b/services/core/java/com/android/server/PendingIntentUtils.java index 1600101b20f4..a72a4d254a2a 100644 --- a/services/core/java/com/android/server/PendingIntentUtils.java +++ b/services/core/java/com/android/server/PendingIntentUtils.java @@ -34,6 +34,7 @@ public class PendingIntentUtils { public static Bundle createDontSendToRestrictedAppsBundle(@Nullable Bundle bundle) { final BroadcastOptions options = BroadcastOptions.makeBasic(); options.setDontSendToRestrictedApps(true); + options.setPendingIntentBackgroundActivityLaunchAllowed(false); if (bundle == null) { return options.toBundle(); } diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index a622d0743bbb..bb6e11dcf8d4 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -90,7 +90,7 @@ ] } ], - "presubmit-large": [ + "postsubmit": [ { "name": "CtsContentTestCases", "options": [ @@ -104,9 +104,7 @@ "include-filter": "android.content.pm.cts" } ] - } - ], - "postsubmit": [ + }, { "name": "CtsPermissionTestCases", "options": [ |