diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-06-20 19:40:56 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-06-20 19:40:56 +0000 |
commit | 9cce2855f3323d9172b2f6c5f847848eec5d4f34 (patch) | |
tree | f5407e137d3c9562439db55b4558b1f47690651f | |
parent | 5c7c66fa224bdbfed0a296dc34f105fd3ebeaeb4 (diff) | |
parent | c23024594b9199e0e52bdb6b9ed012961d3f50cc (diff) | |
download | base-9cce2855f3323d9172b2f6c5f847848eec5d4f34.tar.gz |
Snap for 10347885 from c23024594b9199e0e52bdb6b9ed012961d3f50cc to aml-frc-releasefrc_340821000frc_340819280frc_340819220frc_340819190frc_340819030frc_340819020frc_340819010frc_340818170frc_340818110
Change-Id: I6a594c7c092a465ac9f0a5a673f27069716c8751
92 files changed, 1163 insertions, 568 deletions
diff --git a/core/tests/coretests/src/android/app/KeyguardManagerTest.java b/core/tests/coretests/src/android/app/KeyguardManagerTest.java index 7231fbd3b7eb..958906c36d05 100644 --- a/core/tests/coretests/src/android/app/KeyguardManagerTest.java +++ b/core/tests/coretests/src/android/app/KeyguardManagerTest.java @@ -19,6 +19,7 @@ package android.app; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doReturn; @@ -26,6 +27,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -209,6 +211,42 @@ public class KeyguardManagerTest { verifyDeviceLockedAndRemoveLock(); } + @Test + public void createConfirmDeviceCredentialForRemoteValidationIntent() { + RemoteLockscreenValidationSession remoteLockscreenValidationSession = + new RemoteLockscreenValidationSession.Builder() + .setSourcePublicKey("sourcePublicKey".getBytes()) + .build(); + ComponentName componentName = new ComponentName("pkg", "cls"); + String title = "title"; + String description = "description"; + String checkboxLabel = "checkboxLabel"; + String alternateButtonLabel = "alternateButtonLabel"; + + Intent intent = mKeyguardManager.createConfirmDeviceCredentialForRemoteValidationIntent( + remoteLockscreenValidationSession, + componentName, + title, + description, + checkboxLabel, + alternateButtonLabel + ); + + assertNotNull(intent); + assertEquals(KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL, intent.getAction()); + assertEquals(remoteLockscreenValidationSession, + intent.getParcelableExtra( + KeyguardManager.EXTRA_REMOTE_LOCKSCREEN_VALIDATION_SESSION, + RemoteLockscreenValidationSession.class)); + assertEquals(componentName, + intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME, ComponentName.class)); + assertEquals(title, intent.getStringExtra(KeyguardManager.EXTRA_TITLE)); + assertEquals(description, intent.getStringExtra(KeyguardManager.EXTRA_DESCRIPTION)); + assertEquals(checkboxLabel, intent.getStringExtra(KeyguardManager.EXTRA_CHECKBOX_LABEL)); + assertEquals(alternateButtonLabel, + intent.getStringExtra(KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL)); + } + private void verifyDeviceLockedAndRemoveLock() { assertTrue(mKeyguardManager.isDeviceSecure()); assertTrue("Failed to remove new password that was set in the test case.", diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java index b2e42ba90152..df4fb44cd1ba 100644 --- a/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java +++ b/core/tests/coretests/src/android/content/res/FontScaleConverterActivityTest.java @@ -25,7 +25,6 @@ import static com.google.common.truth.Truth.assertThat; import android.app.Activity; import android.compat.testing.PlatformCompatChangeRule; import android.os.Bundle; -import android.platform.test.annotations.IwTest; import android.platform.test.annotations.PlatinumTest; import android.platform.test.annotations.Presubmit; import android.provider.Settings; @@ -74,7 +73,6 @@ public class FontScaleConverterActivityTest { } @PlatinumTest(focusArea = "accessibility") - @IwTest(focusArea = "accessibility") @Test public void testFontsScaleNonLinearly() { final ActivityScenario<TestActivity> scenario = rule.getScenario(); @@ -106,7 +104,6 @@ public class FontScaleConverterActivityTest { } @PlatinumTest(focusArea = "accessibility") - @IwTest(focusArea = "accessibility") @Test public void testOnConfigurationChanged_doesNotCrash() { final ActivityScenario<TestActivity> scenario = rule.getScenario(); @@ -121,7 +118,6 @@ public class FontScaleConverterActivityTest { } @PlatinumTest(focusArea = "accessibility") - @IwTest(focusArea = "accessibility") @Test public void testUpdateConfiguration_doesNotCrash() { final ActivityScenario<TestActivity> scenario = rule.getScenario(); diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java index f9aa1bd98e38..1e6e50359cf3 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java @@ -239,7 +239,7 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, // display state, so we have to look through all displays to match the address final Display[] displays = mDisplayManager.getDisplays( DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED); - final Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + for (int i = 0; i < displays.length; i++) { DisplayAddress.Physical address = @@ -255,6 +255,8 @@ public class WindowAreaComponentImpl implements WindowAreaComponent, // TODO(b/287170025): This should be something like if (!rearDisplay.isEnabled) // instead. Currently when the rear display is disabled, its state is STATE_OFF. if (rearDisplay.getDisplayId() != Display.DEFAULT_DISPLAY) { + final Display defaultDisplay = mDisplayManager + .getDisplay(Display.DEFAULT_DISPLAY); rotateRearDisplayMetricsIfNeeded(defaultDisplay.getRotation(), rearDisplay.getRotation(), rearDisplayMetrics); } diff --git a/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml b/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml index 01df006f1bd2..f75d842c0d57 100644 --- a/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml +++ b/libs/WindowManager/Shell/res/color/taskbar_background_dark.xml @@ -16,5 +16,5 @@ --> <!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="@android:color/system_neutral1_500" android:lStar="20" /> + <item android:color="@android:color/system_neutral1_500" android:lStar="6" /> </selector>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java index 55052e614458..beb1c5fa6c10 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/animation/PhysicsAnimationLayout.java @@ -523,6 +523,7 @@ public class PhysicsAnimationLayout extends FrameLayout { */ @Nullable private SpringAnimation getSpringAnimationFromView( DynamicAnimation.ViewProperty property, View view) { + if (view == null) return null; return (SpringAnimation) view.getTag(getTagIdForProperty(property)); } @@ -531,11 +532,13 @@ public class PhysicsAnimationLayout extends FrameLayout { * system. */ @Nullable private ViewPropertyAnimator getViewPropertyAnimatorFromView(View view) { + if (view == null) return null; return (ViewPropertyAnimator) view.getTag(R.id.reorder_animator_tag); } /** Retrieves the target animator from the view via the view tag system. */ @Nullable private ObjectAnimator getTargetAnimatorFromView(View view) { + if (view == null) return null; return (ObjectAnimator) view.getTag(R.id.target_animator_tag); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index acbdbf9d6769..cff317259f1e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -710,4 +710,19 @@ public abstract class WMShellModule { static DesktopModeTaskRepository provideDesktopModeTaskRepository() { return new DesktopModeTaskRepository(); } + + // + // Misc + // + + // TODO: Temporarily move dependencies to this instead of ShellInit since that is needed to add + // the callback. We will be moving to a different explicit startup mechanism in a follow- up CL. + @WMSingleton + @ShellCreateTriggerOverride + @Provides + static Object provideIndependentShellComponentsToCreate( + DefaultMixedHandler defaultMixedHandler, + Optional<DesktopModeController> desktopModeController) { + return new Object(); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 4dbb50f34a35..cf389905c526 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -534,8 +534,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return; } - final Rect displayBounds = mPipBoundsState.getDisplayBounds(); - final Rect destinationBounds = new Rect(displayBounds); + final Rect destinationBounds = new Rect(getExitDestinationBounds()); final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit) ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN : TRANSITION_DIRECTION_LEAVE_PIP; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index 86b0f33ad54c..e04e9f7caa91 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -351,7 +351,7 @@ public class PipTransition extends PipTransitionController { if (taskInfo != null) { startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(), mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), - new Rect(mExitDestinationBounds), Surface.ROTATION_0); + new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */); } mExitDestinationBounds.setEmpty(); mCurrentPipTaskToken = null; @@ -604,14 +604,8 @@ public class PipTransition extends PipTransitionController { } } - // Set the initial frame as scaling the end to the start. final Rect destinationBounds = new Rect(pipChange.getEndAbsBounds()); destinationBounds.offset(-offset.x, -offset.y); - startTransaction.setWindowCrop(pipLeash, destinationBounds.width(), - destinationBounds.height()); - mSurfaceTransactionHelper.scale(startTransaction, pipLeash, destinationBounds, - currentBounds); - startTransaction.apply(); // Check if it is fixed rotation. final int rotationDelta; @@ -641,7 +635,7 @@ public class PipTransition extends PipTransitionController { rotationDelta = Surface.ROTATION_0; } startExpandAnimation(taskInfo, pipLeash, currentBounds, currentBounds, destinationBounds, - rotationDelta); + rotationDelta, startTransaction); } private void startExpandAndRotationAnimation(@NonNull TransitionInfo info, @@ -697,7 +691,7 @@ public class PipTransition extends PipTransitionController { private void startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash, final Rect baseBounds, final Rect startBounds, final Rect endBounds, - final int rotationDelta) { + final int rotationDelta, @Nullable SurfaceControl.Transaction startTransaction) { final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( taskInfo.pictureInPictureParams, endBounds); final PipAnimationController.PipTransitionAnimator animator = @@ -705,9 +699,14 @@ public class PipTransition extends PipTransitionController { endBounds, sourceHintRect, TRANSITION_DIRECTION_LEAVE_PIP, 0 /* startingAngle */, rotationDelta); animator.setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP) - .setPipAnimationCallback(mPipAnimationCallback) + .setDuration(mEnterExitAnimationDuration); + if (startTransaction != null) { + animator.setPipTransactionHandler(mTransactionConsumer).applySurfaceControlTransaction( + leash, startTransaction, PipAnimationController.FRACTION_START); + startTransaction.apply(); + } + animator.setPipAnimationCallback(mPipAnimationCallback) .setPipTransactionHandler(mPipOrganizer.getPipTransactionHandler()) - .setDuration(mEnterExitAnimationDuration) .start(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index da14d03adb35..964ba9f9aa7c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -2365,6 +2365,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, out); } } + + // When split in the background, it should be only opening/dismissing transition and + // would keep out not empty. Prevent intercepting all transitions for split screen when + // it is in the background and not identify to handle it. + return (!out.isEmpty() || isSplitScreenVisible()) ? out : null; } else { if (isOpening && getStageOfTask(triggerTask) != null) { // One task is appearing into split, prepare to enter split screen. @@ -2373,8 +2378,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitTransitions.setEnterTransition(transition, request.getRemoteTransition(), TRANSIT_SPLIT_SCREEN_PAIR_OPEN, !mIsDropEntering); } + return out; } - return out; } /** @@ -2506,8 +2511,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, && getStageType(dismissStages.valueAt(0)) == STAGE_TYPE_MAIN) || mMainStage.getChildCount() == 0 ? STAGE_TYPE_SIDE : STAGE_TYPE_MAIN; // If there is a fullscreen opening change, we should not bring stage to top. - prepareExitSplitScreen(record.mContainShowFullscreenChange - ? STAGE_TYPE_UNDEFINED : dismissTop, wct); + prepareExitSplitScreen( + !record.mContainShowFullscreenChange && isSplitScreenVisible() + ? dismissTop : STAGE_TYPE_UNDEFINED, wct); mSplitTransitions.startDismissTransition(wct, this, dismissTop, EXIT_REASON_APP_FINISHED); // This can happen in some pathological cases. For example: diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt index 72f25f36c9d9..d1f0980786bf 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher @@ -62,7 +61,6 @@ class CopyContentInSplit(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test override fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt index ed3df9ced3b0..63c5d14d85e1 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -60,7 +59,6 @@ class DragDividerToResize(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test override fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt index b4c6afd14a90..03b8a75a1f32 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit @@ -61,7 +60,6 @@ class SwitchAppByDoubleTapDivider(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test override fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt index 2cedc3570cfd..674ba40f6a1f 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt @@ -17,7 +17,6 @@ package com.android.wm.shell.flicker.splitscreen import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -64,7 +63,6 @@ class SwitchBetweenSplitPairs(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test override fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt index a5ad97d8ad65..c3c5f88eaa29 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/CopyContentInSplitBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher @@ -64,7 +63,6 @@ open class CopyContentInSplitBenchmark(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt index fa6a4bfbcda6..37cd18fad521 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByDividerBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -70,7 +69,6 @@ open class DismissSplitScreenByDividerBenchmark(flicker: FlickerTest) : SplitScr } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = flicker.splitScreenDismissed(primaryApp, secondaryApp, toHome = false) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt index d2beb678a4d5..0ec6dc96bcd9 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DismissSplitScreenByGoHomeBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -57,7 +56,6 @@ open class DismissSplitScreenByGoHomeBenchmark(override val flicker: FlickerTest } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = flicker.splitScreenDismissed(primaryApp, secondaryApp, toHome = true) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt index e95fd947ebde..190e2e765bcc 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/DragDividerToResizeBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -60,7 +59,6 @@ open class DragDividerToResizeBenchmark(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt index 63b74e29c39c..3a1d1a4415c3 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromAllAppsBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -72,7 +71,6 @@ open class EnterSplitScreenByDragFromAllAppsBenchmark(override val flicker: Flic } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt index e94da8713b43..2033b7d64416 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromNotificationBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -69,7 +68,6 @@ open class EnterSplitScreenByDragFromNotificationBenchmark(override val flicker: } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt index f41117f0d54e..b7a7110afe25 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromShortcutBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -72,7 +71,6 @@ open class EnterSplitScreenByDragFromShortcutBenchmark(flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt index 12f610b73e13..b1ce62f99e6c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenByDragFromTaskbarBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -67,7 +66,6 @@ open class EnterSplitScreenByDragFromTaskbarBenchmark(override val flicker: Flic } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt index 77818d380053..14f07453b7d1 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/EnterSplitScreenFromOverviewBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -66,7 +65,6 @@ open class EnterSplitScreenFromOverviewBenchmark(override val flicker: FlickerTe } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt index 6ff22902667c..65fb1358a9b0 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchAppByDoubleTapDividerBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -136,7 +135,6 @@ open class SwitchAppByDoubleTapDividerBenchmark(override val flicker: FlickerTes } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt index 400adea8880d..b333aba447a2 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromAnotherAppBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -65,7 +64,6 @@ open class SwitchBackToSplitFromAnotherAppBenchmark(override val flicker: Flicke } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt index 1ec43405ee44..a27540efdad7 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromHomeBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -63,7 +62,6 @@ open class SwitchBackToSplitFromHomeBenchmark(override val flicker: FlickerTest) } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt index 9757153929ca..18bf4ff054e0 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBackToSplitFromRecentBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.NavBar @@ -63,7 +62,6 @@ open class SwitchBackToSplitFromRecentBenchmark(override val flicker: FlickerTes } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test fun cujCompleted() = flicker.splitScreenEntered(primaryApp, secondaryApp, fromOtherApp = true) diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt index c19a38dc9daf..c5fe61e26733 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/benchmark/SwitchBetweenSplitPairsBenchmark.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.splitscreen.benchmark -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.device.flicker.junit.FlickerParametersRunnerFactory @@ -66,7 +65,7 @@ open class SwitchBetweenSplitPairsBenchmark(override val flicker: FlickerTest) : } @PlatinumTest(focusArea = "sysui") - @IwTest(focusArea = "sysui") @Presubmit @Test open fun cujCompleted() {} + @Presubmit @Test open fun cujCompleted() {} companion object { @Parameterized.Parameters(name = "{0}") diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java index 094a33f3f2ba..ed68d1eb5724 100644 --- a/media/java/android/media/audiopolicy/AudioMix.java +++ b/media/java/android/media/audiopolicy/AudioMix.java @@ -455,6 +455,11 @@ public class AudioMix { if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) { throw new IllegalArgumentException("Unsupported device on non-playback mix"); } + } else if (mDeviceSystemType == AudioSystem.DEVICE_OUT_REMOTE_SUBMIX) { + if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) { + throw new IllegalArgumentException( + "DEVICE_OUT_REMOTE_SUBMIX device is not supported on non-playback mix"); + } } else { if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_RENDER) { throw new IllegalArgumentException( diff --git a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java index bbca8823dde4..ac8a7f37c527 100644 --- a/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java +++ b/media/tests/AudioPolicyTest/src/com/android/audiopolicytest/AudioMixUnitTests.java @@ -24,7 +24,11 @@ import static android.media.audiopolicy.AudioMixingRule.MIX_ROLE_PLAYERS; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_AUDIO_SESSION_ID; import static android.media.audiopolicy.AudioMixingRule.RULE_MATCH_UID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + import android.media.AudioFormat; +import android.media.AudioSystem; import android.media.audiopolicy.AudioMix; import android.media.audiopolicy.AudioMixingRule; import android.media.audiopolicy.AudioPolicyConfig; @@ -145,6 +149,84 @@ public class AudioMixUnitTests { equalsTester.testEquals(); } + @Test + public void buildRenderToRemoteSubmix_success() { + final String deviceAddress = "address"; + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER) + .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build(); + + assertEquals(deviceAddress, audioMix.getRegistration()); + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags()); + } + + @Test + public void buildLoopbackAndRenderToRemoteSubmix_success() { + final String deviceAddress = "address"; + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER) + .setDevice(AudioSystem.DEVICE_OUT_REMOTE_SUBMIX, /*address=*/deviceAddress).build(); + + assertEquals(deviceAddress, audioMix.getRegistration()); + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER, audioMix.getRouteFlags()); + } + + @Test + public void buildRenderToSpeaker_success() { + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER) + .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build(); + + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_RENDER, audioMix.getRouteFlags()); + } + + @Test + public void buildLoopbackForPlayerMix_success() { + final AudioMix audioMix = new AudioMix.Builder(new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK).build(); + + assertEquals(OUTPUT_FORMAT_MONO_16KHZ_PCM, audioMix.getFormat()); + assertEquals(AudioMix.ROUTE_FLAG_LOOP_BACK, audioMix.getRouteFlags()); + } + + @Test + public void buildLoopbackWithDevice_throws() { + assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder( + new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK) + .setDevice(AudioSystem.DEVICE_OUT_SPEAKER, /*address=*/"").build()); + } + + @Test + public void buildRenderWithoutDevice_throws() { + assertThrows(IllegalArgumentException.class, () -> new AudioMix.Builder( + new AudioMixingRule.Builder() + .setTargetMixRole(MIX_ROLE_PLAYERS) + .addMixRule(RULE_MATCH_UID, 42).build()) + .setFormat(OUTPUT_FORMAT_MONO_16KHZ_PCM) + .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER).build()); + } + + + private static AudioMix writeToAndFromParcel(AudioMix audioMix) { AudioPolicyConfig apc = new AudioPolicyConfig(new ArrayList<>(List.of(audioMix))); Parcel parcel = Parcel.obtain(); diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 0aa121dfcc49..5c036988eb30 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -362,7 +362,7 @@ android:killAfterRestore="false" android:hardwareAccelerated="true" android:label="@string/app_label" - android:icon="@drawable/icon" + android:icon="@drawable/android14_patch_adaptive" android:process="com.android.systemui" android:supportsRtl="true" android:theme="@style/Theme.SystemUI" diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt index 8cba2ab0b70b..702cc05f7f5f 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt @@ -56,7 +56,6 @@ private val KNOWN_PLUGINS = "com.android.systemui.falcon.four" to listOf(ClockMetadata("DIGITAL_CLOCK_GROWTH")), "com.android.systemui.falcon.five" to listOf(ClockMetadata("DIGITAL_CLOCK_HANDWRITTEN")), "com.android.systemui.falcon.six" to listOf(ClockMetadata("DIGITAL_CLOCK_INFLATE")), - "com.android.systemui.falcon.seven" to listOf(ClockMetadata("DIGITAL_CLOCK_METRO")), "com.android.systemui.falcon.eight" to listOf(ClockMetadata("DIGITAL_CLOCK_NUMBEROVERLAP")), "com.android.systemui.falcon.nine" to listOf(ClockMetadata("DIGITAL_CLOCK_WEATHER")), ) diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 28f5f3d9edd7..badad584824b 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -358,12 +358,12 @@ <!-- Message shown to prepare for an unattended update (OTA). Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] --> <string name="kg_prompt_unattended_update_pattern">Draw pattern to install update later</string> - <!-- Message shown after an unattended update (OTA) asking the user to enter their PIN. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] --> + <!-- Message shown after an unattended mainline (major) update asking the user to enter their PIN. [CHAR LIMIT=70] --> <string name="kg_prompt_after_update_pin">Device updated. Enter PIN to continue.</string> - <!-- Message shown after an unattended update (OTA) asking the user to enter their password. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] --> + <!-- Message shown after an unattended mainline (major) update asking the user to enter their password. [CHAR LIMIT=70] --> <string name="kg_prompt_after_update_password">Device updated. Enter password to continue.</string> - <!-- Message shown after an unattended update (OTA) asking the user to enter their pattern. Also known as an over-the-air (OTA) update. [CHAR LIMIT=70] --> + <!-- Message shown after an unattended mainline (major) update asking the user to enter their pattern. [CHAR LIMIT=70] --> <string name="kg_prompt_after_update_pattern">Device updated. Draw pattern to continue.</string> </resources> diff --git a/packages/SystemUI/res/drawable/android14_patch_adaptive.xml b/packages/SystemUI/res/drawable/android14_patch_adaptive.xml new file mode 100644 index 000000000000..423e35146c24 --- /dev/null +++ b/packages/SystemUI/res/drawable/android14_patch_adaptive.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2023 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. +--> +<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> + <background android:drawable="@drawable/android14_patch_adaptive_background"/> + <foreground android:drawable="@drawable/android14_patch_adaptive_foreground"/> + <monochrome android:drawable="@drawable/android14_patch_monochrome"/> +</adaptive-icon>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/android14_patch_adaptive_background.xml b/packages/SystemUI/res/drawable/android14_patch_adaptive_background.xml new file mode 100644 index 000000000000..afeae4bd868c --- /dev/null +++ b/packages/SystemUI/res/drawable/android14_patch_adaptive_background.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2023 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + <path + android:pathData="M0,0 L108,0 L108,108 L0,108 z" + android:fillColor="@android:color/system_neutral1_800"/> + <path + android:pathData="M44.51,43.32L44.86,42.27C47.04,54.48 52.81,86.71 52.81,50.14C52.81,49.99 52.92,49.86 53.06,49.86H55.04C55.18,49.86 55.3,49.98 55.3,50.14C55.27,114.18 44.51,43.32 44.51,43.32Z" + android:fillColor="@android:color/system_accent3_400"/> + <path + android:name="planetary head" + android:pathData="M38.81,42.23L33.63,51.21C33.33,51.72 33.51,52.38 34.02,52.68C34.54,52.98 35.2,52.8 35.49,52.28L40.74,43.2C49.22,47 58.92,47 67.4,43.2L72.65,52.28C72.96,52.79 73.62,52.96 74.13,52.65C74.62,52.35 74.79,51.71 74.51,51.21L69.33,42.23C78.23,37.39 84.32,28.38 85.21,17.74H22.93C23.82,28.38 29.91,37.39 38.81,42.23Z" + android:fillColor="#ffffff"/> + <!-- yes it's an easter egg in a vector drawable --> + <path + android:name="planetary body" + android:pathData="M22.9,0 L85.1,0 L85.1,15.5 L22.9,15.5 z" + android:fillColor="#ffffff" /> + <path + android:pathData="M54.96,43.32H53.1C52.92,43.32 52.77,43.47 52.77,43.65V48.04C52.77,48.22 52.92,48.37 53.1,48.37H54.96C55.15,48.37 55.3,48.22 55.3,48.04V43.65C55.3,43.47 55.15,43.32 54.96,43.32Z" + android:fillColor="@android:color/system_accent3_400"/> + <path + android:pathData="M54.99,40.61H53.08C52.91,40.61 52.77,40.75 52.77,40.92V41.56C52.77,41.73 52.91,41.87 53.08,41.87H54.99C55.16,41.87 55.3,41.73 55.3,41.56V40.92C55.3,40.75 55.16,40.61 54.99,40.61Z" + android:fillColor="@android:color/system_accent3_400"/> + <path + android:pathData="M41.49,47.88H40.86V48.51H41.49V47.88Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M44.13,57.08H43.5V57.71H44.13V57.08Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M72.29,66.76H71.66V67.39H72.29V66.76Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M59.31,53.41H58.68V54.04H59.31V53.41Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M64.47,48.19H63.84V48.83H64.47V48.19Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M60.58,59.09H59.95V59.72H60.58V59.09Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M66.95,56.7H65.69V57.97H66.95V56.7Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M44.13,60.71H43.5V61.34H44.13V60.71Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M49.66,51.33H48.4V52.6H49.66V51.33Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M57.78,63.83H56.52V65.09H57.78V63.83Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M61.1,68.57H59.83V69.83H61.1V68.57Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M40.43,53.73H39.16V54.99H40.43V53.73Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M74.47,44H73.21V45.26H74.47V44Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M36.8,64.58H35.54V65.84H36.8V64.58Z" + android:fillColor="#ffffff"/> +</vector> diff --git a/packages/SystemUI/res/drawable/android14_patch_adaptive_foreground.xml b/packages/SystemUI/res/drawable/android14_patch_adaptive_foreground.xml new file mode 100644 index 000000000000..ced43056d08f --- /dev/null +++ b/packages/SystemUI/res/drawable/android14_patch_adaptive_foreground.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2023 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + <path + android:pathData="M54.03,33.03C52.99,33.03 52.14,33.86 52.14,34.87V37.14C52.14,37.34 52.3,37.5 52.5,37.5C52.69,37.5 52.85,37.34 52.85,37.14V36.53C52.85,36.14 53.17,35.82 53.56,35.82H54.51C54.9,35.82 55.22,36.14 55.22,36.53V37.14C55.22,37.34 55.38,37.5 55.57,37.5C55.77,37.5 55.93,37.34 55.93,37.14V34.87C55.93,33.86 55.08,33.03 54.03,33.03H54.03Z" + android:fillColor="@android:color/system_accent3_400"/> + <path + android:pathData="M108,0H0V108H108V0ZM54,80.67C68.73,80.67 80.67,68.73 80.67,54C80.67,39.27 68.73,27.33 54,27.33C39.27,27.33 27.33,39.27 27.33,54C27.33,68.73 39.27,80.67 54,80.67Z" + android:fillColor="@android:color/system_accent1_400" + android:fillType="evenOdd"/> + <group> + <!-- the text doesn't look great everywhere but you can remove the clip to try it out. --> + <clip-path /> + <path + android:pathData="M28.58,32.18L29.18,31.5L33.82,33.02L33.12,33.81L32.15,33.48L30.92,34.87L31.37,35.8L30.68,36.58L28.58,32.18L28.58,32.18ZM31.25,33.18L29.87,32.71L30.51,34.02L31.25,33.18V33.18Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M38,29.76L34.61,28.79L36.23,31.04L35.42,31.62L32.8,27.99L33.5,27.48L36.88,28.45L35.26,26.21L36.08,25.62L38.7,29.25L38,29.76Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M39.23,23.87L40.63,23.27C41.79,22.77 43.13,23.28 43.62,24.43C44.11,25.57 43.56,26.89 42.4,27.39L40.99,27.99L39.23,23.87ZM42.03,26.54C42.73,26.24 42.96,25.49 42.68,24.83C42.4,24.17 41.69,23.82 41,24.11L40.51,24.32L41.55,26.75L42.03,26.54Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M45.91,21.43L47.64,21.09C48.47,20.93 49.12,21.41 49.27,22.15C49.38,22.72 49.15,23.14 48.63,23.45L50.57,25.08L49.39,25.31L47.57,23.79L47.41,23.82L47.76,25.63L46.78,25.83L45.91,21.43H45.91ZM47.87,22.86C48.16,22.8 48.34,22.59 48.29,22.34C48.24,22.07 48,21.96 47.71,22.02L47.07,22.14L47.24,22.98L47.87,22.86Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M52.17,22.69C52.19,21.41 53.24,20.39 54.52,20.41C55.8,20.43 56.82,21.49 56.8,22.76C56.78,24.04 55.72,25.06 54.45,25.04C53.17,25.02 52.15,23.96 52.17,22.69ZM55.79,22.75C55.8,22.02 55.23,21.39 54.51,21.38C53.78,21.37 53.19,21.98 53.18,22.7C53.17,23.43 53.73,24.06 54.47,24.07C55.19,24.08 55.78,23.47 55.79,22.75H55.79Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M60,21.01L60.98,21.2L60.12,25.6L59.14,25.41L60,21.01Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M64.3,22.03L65.73,22.58C66.91,23.03 67.51,24.32 67.07,25.49C66.62,26.65 65.31,27.22 64.13,26.77L62.71,26.22L64.3,22.03L64.3,22.03ZM64.46,25.9C65.17,26.17 65.86,25.8 66.12,25.12C66.37,24.45 66.11,23.71 65.4,23.44L64.91,23.25L63.97,25.72L64.46,25.9Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M73.59,27.94L72.94,27.44L73.51,26.69L74.92,27.77L72.2,31.34L71.45,30.76L73.59,27.94Z" + android:fillColor="#ffffff"/> + <path + android:pathData="M76.18,33.75L74.69,32.14L75.25,31.62L78.81,31.42L79.4,32.05L77.47,33.85L77.86,34.27L77.22,34.86L76.83,34.44L76.12,35.11L75.47,34.41L76.18,33.75ZM77.72,32.31L76.12,32.4L76.82,33.15L77.72,32.31Z" + android:fillColor="#ffffff"/> + </group> +</vector> diff --git a/packages/SystemUI/res/drawable/android14_patch_monochrome.xml b/packages/SystemUI/res/drawable/android14_patch_monochrome.xml new file mode 100644 index 000000000000..beef85ce3b3f --- /dev/null +++ b/packages/SystemUI/res/drawable/android14_patch_monochrome.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright (C) 2023 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="108dp" + android:height="108dp" + android:viewportWidth="108" + android:viewportHeight="108"> + <group> + <clip-path + android:pathData="M0,0h108v108h-108z"/> + <group> + <clip-path + android:pathData="M22,22h64v64h-64z"/> + <path + android:pathData="M54,78C67.25,78 78,67.25 78,54C78,40.75 67.25,30 54,30C40.75,30 30,40.75 30,54C30,67.25 40.75,78 54,78Z" + android:strokeWidth="5" + android:fillColor="#00000000" + android:strokeColor="#000000"/> + <group> + <clip-path + android:pathData="M77.5,54C77.5,66.98 66.98,77.5 54,77.5C41.02,77.5 30.5,66.98 30.5,54C30.5,41.02 41.02,30.5 54,30.5C66.98,30.5 77.5,41.02 77.5,54Z"/> + <path + android:pathData="M61.5,46.06C56.7,47.89 51.4,47.89 46.61,46.06L44.04,50.51C43.49,51.46 42.28,51.79 41.33,51.24C40.39,50.69 40.06,49.48 40.61,48.53L43.06,44.28C37.97,41.03 34.54,35.56 34,29.19L33.88,27.74H74.22L74.1,29.19C73.57,35.56 70.14,41.03 65.04,44.28L67.51,48.56C68.03,49.49 67.71,50.66 66.8,51.21C65.87,51.77 64.65,51.47 64.08,50.54L64.07,50.51L61.5,46.06Z" + android:fillColor="#000000"/> + </group> + <path + android:pathData="M51.33,67.33h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M48.67,62h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M56.67,70h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M56.67,62h2.67v2.67h-2.67z" + android:fillColor="#000000"/> + <path + android:pathData="M67.33,62h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M59.33,51.33h2.67v2.67h-2.67z" + android:fillColor="#000000"/> + <path + android:pathData="M62,59.33h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M70,54h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M35.33,56.67h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M35.33,48.67h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M40.67,59.33h2.67v2.67h-2.67z" + android:fillColor="#000000"/> + <path + android:pathData="M46,51.33h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M43.33,67.33h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + <path + android:pathData="M54,54h1.33v1.33h-1.33z" + android:fillColor="#000000"/> + </group> + </group> +</vector> diff --git a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml index a2250b1975a3..0fd3c5b16435 100644 --- a/packages/SystemUI/res/layout/qs_customize_tile_frame.xml +++ b/packages/SystemUI/res/layout/qs_customize_tile_frame.xml @@ -17,7 +17,7 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="@dimen/qs_tile_height" + android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_marginTop="@dimen/qs_tile_margin_top_bottom" android:layout_marginBottom="@dimen/qs_tile_margin_top_bottom" diff --git a/packages/SystemUI/res/xml/combined_qs_header_scene.xml b/packages/SystemUI/res/xml/combined_qs_header_scene.xml index 38c164023315..8512f6fada43 100644 --- a/packages/SystemUI/res/xml/combined_qs_header_scene.xml +++ b/packages/SystemUI/res/xml/combined_qs_header_scene.xml @@ -16,12 +16,14 @@ --> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition android:id="@+id/header_transition" app:constraintSetEnd="@id/qs_header_constraint" - app:constraintSetStart="@id/qqs_header_constraint"> + app:constraintSetStart="@id/qqs_header_constraint" + motion:layoutDuringTransition="honorRequest"> <KeyFrameSet> <!-- These positions are to prevent visual movement of @id/date --> <KeyPosition diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java index e057188851f6..d7e8616d17e7 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java @@ -53,6 +53,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey private boolean mDismissing; protected AsyncTask<?, ?, ?> mPendingLockCheck; protected boolean mResumed; + protected boolean mLockedOut; private final KeyDownListener mKeyDownListener = (keyCode, keyEvent) -> { // Fingerprint sensor sends a KeyEvent.KEYCODE_UNKNOWN. @@ -137,6 +138,8 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey // Prevent user from using the PIN/Password entry until scheduled deadline. protected void handleAttemptLockout(long elapsedRealtimeDeadline) { mView.setPasswordEntryEnabled(false); + mView.setPasswordEntryInputEnabled(false); + mLockedOut = true; long elapsedRealtime = SystemClock.elapsedRealtime(); long secondsInFuture = (long) Math.ceil( (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0); @@ -158,6 +161,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey @Override public void onFinish() { mMessageAreaController.setMessage(""); + mLockedOut = false; resetState(); } }.start(); @@ -193,6 +197,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey protected void verifyPasswordAndUnlock() { if (mDismissing) return; // already verified but haven't been dismissed; don't do it again. + if (mLockedOut) return; final LockscreenCredential password = mView.getEnteredCredential(); mView.setPasswordEntryInputEnabled(false); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java index 7a0a24a85eaf..03d9eb3455fd 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java @@ -23,6 +23,7 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART; +import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; @@ -99,6 +100,8 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { switch (reason) { case PROMPT_REASON_RESTART: return R.string.kg_prompt_reason_restart_password; + case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE: + return R.string.kg_prompt_after_update_password; case PROMPT_REASON_TIMEOUT: return R.string.kg_prompt_reason_timeout_password; case PROMPT_REASON_DEVICE_ADMIN: @@ -106,7 +109,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView { case PROMPT_REASON_USER_REQUEST: return R.string.kg_prompt_after_user_lockdown_password; case PROMPT_REASON_PREPARE_FOR_UPDATE: - return R.string.kg_prompt_reason_timeout_password; + return R.string.kg_prompt_unattended_update_password; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: return R.string.kg_prompt_reason_timeout_password; case PROMPT_REASON_TRUSTAGENT_EXPIRED: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index be423767e6d0..3d255a58cf8e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -304,6 +304,9 @@ public class KeyguardPatternViewController case PROMPT_REASON_RESTART: resId = R.string.kg_prompt_reason_restart_pattern; break; + case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE: + resId = R.string.kg_prompt_after_update_pattern; + break; case PROMPT_REASON_TIMEOUT: resId = R.string.kg_prompt_reason_timeout_pattern; break; @@ -314,7 +317,7 @@ public class KeyguardPatternViewController resId = R.string.kg_prompt_after_user_lockdown_pattern; break; case PROMPT_REASON_PREPARE_FOR_UPDATE: - resId = R.string.kg_prompt_reason_timeout_pattern; + resId = R.string.kg_prompt_unattended_update_pattern; break; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: resId = R.string.kg_prompt_reason_timeout_pattern; diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java index 687436c5d388..38e5dc57d316 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -21,6 +21,7 @@ import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART; +import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED; import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; @@ -113,6 +114,8 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView switch (reason) { case PROMPT_REASON_RESTART: return R.string.kg_prompt_reason_restart_pin; + case PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE: + return R.string.kg_prompt_after_update_pin; case PROMPT_REASON_TIMEOUT: return R.string.kg_prompt_reason_timeout_pin; case PROMPT_REASON_DEVICE_ADMIN: @@ -120,7 +123,7 @@ public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView case PROMPT_REASON_USER_REQUEST: return R.string.kg_prompt_after_user_lockdown_pin; case PROMPT_REASON_PREPARE_FOR_UPDATE: - return R.string.kg_prompt_reason_timeout_pin; + return R.string.kg_prompt_unattended_update_pin; case PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT: return R.string.kg_prompt_reason_timeout_pin; case PROMPT_REASON_TRUSTAGENT_EXPIRED: diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index 4211f55787d9..841b5b3a1e82 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -474,7 +474,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout { return false; } // Avoid dragging the pattern view - if (mSecurityViewFlipper.getSecurityView().disallowInterceptTouch(event)) { + if (mSecurityViewFlipper.getSecurityView() != null + && mSecurityViewFlipper.getSecurityView().disallowInterceptTouch(event)) { return false; } int index = event.findPointerIndex(mActivePointerId); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java index 419303d71f97..21960e219fc9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java @@ -103,6 +103,12 @@ public interface KeyguardSecurityView { int PROMPT_REASON_PRIMARY_AUTH_LOCKED_OUT = 15; /** + * Strong auth is required because the device has just booted because of an automatic + * mainline update. + */ + int PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE = 16; + + /** * Reset the view and prepare to take input. This should do things like clearing the * password or pattern and clear error messages. */ diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 3f2054029459..10cacb201c29 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -740,6 +740,12 @@ object Flags { val ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD = releasedFlag(2900, "zj_285570694_lockscreen_transition_from_aod") + // 3000 - dream + // TODO(b/285059790) : Tracking Bug + @JvmField + val LOCKSCREEN_WALLPAPER_DREAM_ENABLED = + unreleasedFlag(3000, name = "enable_lockscreen_wallpaper_dream") + // TODO(b/283084712): Tracking Bug @JvmField val IMPROVED_HUN_ANIMATIONS = unreleasedFlag(283084712, "improved_hun_animations") diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index a2c940bd298c..e6053fb3e352 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -80,6 +80,8 @@ import com.android.wm.shell.util.CounterRotator; import com.android.wm.shell.util.TransitionUtil; import java.util.ArrayList; +import java.util.Map; +import java.util.WeakHashMap; import javax.inject.Inject; @@ -192,7 +194,8 @@ public class KeyguardService extends Service { private final CounterRotator mCounterRotator = new CounterRotator(); @GuardedBy("mLeashMap") - private IRemoteTransitionFinishedCallback mFinishCallback = null; + private final Map<IBinder, IRemoteTransitionFinishedCallback> mFinishCallbacks = + new WeakHashMap<>(); @Override public void startAnimation(IBinder transition, TransitionInfo info, @@ -206,7 +209,7 @@ public class KeyguardService extends Service { synchronized (mLeashMap) { apps = wrap(info, false /* wallpapers */, t, mLeashMap, mCounterRotator); wallpapers = wrap(info, true /* wallpapers */, t, mLeashMap, mCounterRotator); - mFinishCallback = finishCallback; + mFinishCallbacks.put(transition, finishCallback); } // Set alpha back to 1 for the independent changes because we will be animating @@ -229,7 +232,7 @@ public class KeyguardService extends Service { @Override public void onAnimationFinished() throws RemoteException { Slog.d(TAG, "Finish IRemoteAnimationRunner."); - finish(); + finish(transition); } }); } @@ -246,7 +249,7 @@ public class KeyguardService extends Service { try { runner.onAnimationCancelled(); - finish(); + finish(currentTransition); } catch (RemoteException e) { // nothing, we'll just let it finish on its own I guess. } @@ -260,7 +263,7 @@ public class KeyguardService extends Service { } } - private void finish() throws RemoteException { + private void finish(IBinder transition) throws RemoteException { IRemoteTransitionFinishedCallback finishCallback = null; SurfaceControl.Transaction finishTransaction = null; @@ -271,8 +274,7 @@ public class KeyguardService extends Service { mCounterRotator.cleanUp(finishTransaction); } mLeashMap.clear(); - finishCallback = mFinishCallback; - mFinishCallback = null; + finishCallback = mFinishCallbacks.remove(transition); } if (finishCallback != null) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 5bf56a1da32f..bc41ab3156df 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -137,6 +137,7 @@ import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; +import com.android.systemui.flags.SystemPropertiesHelper; import com.android.systemui.keyguard.dagger.KeyguardModule; import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel; import com.android.systemui.log.SessionTracker; @@ -167,6 +168,7 @@ import dagger.Lazy; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -280,6 +282,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, * keyguard to show even if it is disabled for the current user. */ public static final String OPTION_FORCE_SHOW = "force_show"; + public static final String SYS_BOOT_REASON_PROP = "sys.boot.reason.last"; + public static final String REBOOT_MAINLINE_UPDATE = "reboot,mainline_update"; private final DreamOverlayStateController mDreamOverlayStateController; /** The stream type that the lock sounds are tied to. */ @@ -315,6 +319,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, /** UserSwitcherController for creating guest user on boot complete */ private final UserSwitcherController mUserSwitcherController; + private SystemPropertiesHelper mSystemPropertiesHelper; /** * Used to keep the device awake while to ensure the keyguard finishes opening before @@ -846,7 +851,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, strongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(currentUser); if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) { - return KeyguardSecurityView.PROMPT_REASON_RESTART; + String reasonForReboot = mSystemPropertiesHelper.get(SYS_BOOT_REASON_PROP); + if (Objects.equals(reasonForReboot, REBOOT_MAINLINE_UPDATE)) { + return KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE; + } else { + return KeyguardSecurityView.PROMPT_REASON_RESTART; + } } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) != 0) { return KeyguardSecurityView.PROMPT_REASON_TIMEOUT; } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN) != 0) { @@ -1243,7 +1253,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, @Override public void onPrimaryBouncerShowingChanged() { synchronized (KeyguardViewMediator.this) { - if (mKeyguardStateController.isPrimaryBouncerShowing()) { + if (mKeyguardStateController.isPrimaryBouncerShowing() + && !mKeyguardStateController.isKeyguardGoingAway()) { mPendingPinLock = false; } adjustStatusBarLocked(mKeyguardStateController.isPrimaryBouncerShowing(), false); @@ -1304,7 +1315,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, Lazy<ScrimController> scrimControllerLazy, FeatureFlags featureFlags, @Main CoroutineDispatcher mainDispatcher, - Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) { + Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel, + SystemPropertiesHelper systemPropertiesHelper) { mContext = context; mUserTracker = userTracker; mFalsingCollector = falsingCollector; @@ -1318,6 +1330,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable, mPM = powerManager; mTrustManager = trustManager; mUserSwitcherController = userSwitcherController; + mSystemPropertiesHelper = systemPropertiesHelper; mStatusBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); mKeyguardDisplayManager = keyguardDisplayManager; diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt index 4085dab39300..11bc88a01027 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactory.kt @@ -36,43 +36,9 @@ import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TIMEOUT import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED import com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_USER_REQUEST import com.android.keyguard.KeyguardUpdateMonitor -import com.android.systemui.R.string.bouncer_face_not_recognized import com.android.systemui.R.string.keyguard_enter_password import com.android.systemui.R.string.keyguard_enter_pattern import com.android.systemui.R.string.keyguard_enter_pin -import com.android.systemui.R.string.kg_bio_too_many_attempts_password -import com.android.systemui.R.string.kg_bio_too_many_attempts_pattern -import com.android.systemui.R.string.kg_bio_too_many_attempts_pin -import com.android.systemui.R.string.kg_bio_try_again_or_password -import com.android.systemui.R.string.kg_bio_try_again_or_pattern -import com.android.systemui.R.string.kg_bio_try_again_or_pin -import com.android.systemui.R.string.kg_face_locked_out -import com.android.systemui.R.string.kg_fp_locked_out -import com.android.systemui.R.string.kg_fp_not_recognized -import com.android.systemui.R.string.kg_primary_auth_locked_out_password -import com.android.systemui.R.string.kg_primary_auth_locked_out_pattern -import com.android.systemui.R.string.kg_primary_auth_locked_out_pin -import com.android.systemui.R.string.kg_prompt_after_dpm_lock -import com.android.systemui.R.string.kg_prompt_after_user_lockdown_password -import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pattern -import com.android.systemui.R.string.kg_prompt_after_user_lockdown_pin -import com.android.systemui.R.string.kg_prompt_auth_timeout -import com.android.systemui.R.string.kg_prompt_password_auth_timeout -import com.android.systemui.R.string.kg_prompt_pattern_auth_timeout -import com.android.systemui.R.string.kg_prompt_pin_auth_timeout -import com.android.systemui.R.string.kg_prompt_reason_restart_password -import com.android.systemui.R.string.kg_prompt_reason_restart_pattern -import com.android.systemui.R.string.kg_prompt_reason_restart_pin -import com.android.systemui.R.string.kg_prompt_unattended_update -import com.android.systemui.R.string.kg_too_many_failed_attempts_countdown -import com.android.systemui.R.string.kg_trust_agent_disabled -import com.android.systemui.R.string.kg_unlock_with_password_or_fp -import com.android.systemui.R.string.kg_unlock_with_pattern_or_fp -import com.android.systemui.R.string.kg_unlock_with_pin_or_fp -import com.android.systemui.R.string.kg_wrong_input_try_fp_suggestion -import com.android.systemui.R.string.kg_wrong_password_try_again -import com.android.systemui.R.string.kg_wrong_pattern_try_again -import com.android.systemui.R.string.kg_wrong_pin_try_again import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.bouncer.shared.model.BouncerMessageModel import com.android.systemui.keyguard.bouncer.shared.model.Message @@ -186,175 +152,171 @@ private fun defaultMessage(securityMode: SecurityMode): Pair<Int, Int> { private fun defaultMessageWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, 0) - SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, 0) - SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, 0) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun incorrectSecurityInput(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, 0) - SecurityMode.Password -> Pair(kg_wrong_password_try_again, 0) - SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, 0) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun incorrectSecurityInputWithFingerprint(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_wrong_pattern_try_again, kg_wrong_input_try_fp_suggestion) - SecurityMode.Password -> Pair(kg_wrong_password_try_again, kg_wrong_input_try_fp_suggestion) - SecurityMode.PIN -> Pair(kg_wrong_pin_try_again, kg_wrong_input_try_fp_suggestion) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun incorrectFingerprintInput(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pattern) - SecurityMode.Password -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_password) - SecurityMode.PIN -> Pair(kg_fp_not_recognized, kg_bio_try_again_or_pin) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun incorrectFaceInput(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pattern) - SecurityMode.Password -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_password) - SecurityMode.PIN -> Pair(bouncer_face_not_recognized, kg_bio_try_again_or_pin) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun incorrectFaceInputWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, bouncer_face_not_recognized) - SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, bouncer_face_not_recognized) - SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, bouncer_face_not_recognized) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun biometricLockout(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_bio_too_many_attempts_pattern) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_bio_too_many_attempts_password) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_bio_too_many_attempts_pin) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun authRequiredAfterReboot(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_reason_restart_pattern) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_reason_restart_password) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_reason_restart_pin) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun authRequiredAfterAdminLockdown(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_dpm_lock) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_after_dpm_lock) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_dpm_lock) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern) - SecurityMode.Password -> - Pair(keyguard_enter_password, kg_prompt_after_user_lockdown_password) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_user_lockdown_pin) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun authRequiredForUnattendedUpdate(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_unattended_update) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_unattended_update) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_unattended_update) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun authRequiredAfterPrimaryAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_pattern_auth_timeout) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_password_auth_timeout) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_pin_auth_timeout) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun nonStrongAuthTimeout(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_auth_timeout) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_prompt_auth_timeout) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_auth_timeout) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun nonStrongAuthTimeoutWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_prompt_auth_timeout) - SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_prompt_auth_timeout) - SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_auth_timeout) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun faceUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_face_locked_out) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_face_locked_out) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_face_locked_out) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun fingerprintUnlockUnavailable(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_fp_locked_out) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_fp_locked_out) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_fp_locked_out) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun trustAgentDisabled(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_trust_agent_disabled) - SecurityMode.Password -> Pair(keyguard_enter_password, kg_trust_agent_disabled) - SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_trust_agent_disabled) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun trustAgentDisabledWithFingerprintAllowed(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> Pair(kg_unlock_with_pattern_or_fp, kg_trust_agent_disabled) - SecurityMode.Password -> Pair(kg_unlock_with_password_or_fp, kg_trust_agent_disabled) - SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_trust_agent_disabled) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } private fun primaryAuthLockedOut(securityMode: SecurityMode): Pair<Int, Int> { return when (securityMode) { - SecurityMode.Pattern -> - Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pattern) - SecurityMode.Password -> - Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_password) - SecurityMode.PIN -> - Pair(kg_too_many_failed_attempts_countdown, kg_primary_auth_locked_out_pin) + SecurityMode.Pattern -> Pair(keyguard_enter_pattern, 0) + SecurityMode.Password -> Pair(keyguard_enter_password, 0) + SecurityMode.PIN -> Pair(keyguard_enter_pin, 0) else -> Pair(0, 0) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index ab79c8067cd5..1f121e92d7d0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -42,6 +42,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.SystemPropertiesHelper; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; @@ -134,7 +135,8 @@ public class KeyguardModule { Lazy<ScrimController> scrimControllerLazy, FeatureFlags featureFlags, @Main CoroutineDispatcher mainDispatcher, - Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel) { + Lazy<DreamingToLockscreenTransitionViewModel> dreamingToLockscreenTransitionViewModel, + SystemPropertiesHelper systemPropertiesHelper) { return new KeyguardViewMediator( context, uiEventLogger, @@ -170,7 +172,8 @@ public class KeyguardModule { scrimControllerLazy, featureFlags, mainDispatcher, - dreamingToLockscreenTransitionViewModel); + dreamingToLockscreenTransitionViewModel, + systemPropertiesHelper); } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index b96ca7ac2961..3b32313e76a0 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -224,7 +224,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION; } }); - controller.overrideIconTintForNavMode(true); return controller; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index 17124901e4de..d511d8aea019 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -114,11 +114,18 @@ public class QSCustomizer extends LinearLayout { mQs = qs; } + private void reloadAdapterTileHeight(@Nullable RecyclerView.Adapter adapter) { + if (adapter instanceof TileAdapter) { + ((TileAdapter) adapter).reloadTileHeight(); + } + } + /** Animate and show QSCustomizer panel. * @param x,y Location on screen of {@code edit} button to determine center of animation. */ void show(int x, int y, TileAdapter tileAdapter) { if (!isShown) { + reloadAdapterTileHeight(tileAdapter); mRecyclerView.getLayoutManager().scrollToPosition(0); int[] containerLocation = findViewById(R.id.customize_container).getLocationOnScreen(); mX = x - containerLocation[0]; @@ -136,6 +143,7 @@ public class QSCustomizer extends LinearLayout { void showImmediately() { if (!isShown) { + reloadAdapterTileHeight(mRecyclerView.getAdapter()); mRecyclerView.getLayoutManager().scrollToPosition(0); setVisibility(VISIBLE); mClipper.cancelAnimator(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 6a05684a74e8..596475eedb43 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -43,9 +43,11 @@ import androidx.recyclerview.widget.RecyclerView.State; import androidx.recyclerview.widget.RecyclerView.ViewHolder; import com.android.internal.logging.UiEventLogger; +import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.qs.QSEditEvent; import com.android.systemui.qs.QSHost; +import com.android.systemui.qs.TileLayout; import com.android.systemui.qs.customize.TileAdapter.Holder; import com.android.systemui.qs.customize.TileQueryHelper.TileInfo; import com.android.systemui.qs.customize.TileQueryHelper.TileStateListener; @@ -114,6 +116,9 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta private RecyclerView mRecyclerView; private int mNumColumns; + private TextView mTempTextView; + private int mMinTileViewHeight; + @Inject public TileAdapter( @QSThemedContext Context context, @@ -129,6 +134,8 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mNumColumns = context.getResources().getInteger(NUM_COLUMNS_ID); mAccessibilityDelegate = new TileAdapterDelegate(); mSizeLookup.setSpanIndexCacheEnabled(true); + mTempTextView = new TextView(context); + mMinTileViewHeight = context.getResources().getDimensionPixelSize(R.dimen.qs_tile_height); } @Override @@ -318,6 +325,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta @Override public void onBindViewHolder(final Holder holder, int position) { + if (holder.mTileView != null) { + holder.mTileView.setMinimumHeight(mMinTileViewHeight); + } + if (holder.getItemViewType() == TYPE_HEADER) { setSelectableForHeaders(holder.itemView); return; @@ -860,4 +871,19 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta - buttonMinWidth - res.getDimensionPixelSize(R.dimen.qs_tile_margin_top_bottom); } + + /** + * Re-estimate the tile view height based under current font scaling. Like + * {@link TileLayout#estimateCellHeight()}, the tile view height would be estimated with 2 + * labels as general case. + */ + public void reloadTileHeight() { + final int minHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height); + FontSizeUtils.updateFontSize(mTempTextView, R.dimen.qs_tile_text_size); + int unspecifiedSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + mTempTextView.measure(unspecifiedSpec, unspecifiedSpec); + int padding = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_padding); + int estimatedTileViewHeight = mTempTextView.getMeasuredHeight() * 2 + padding * 2; + mMinTileViewHeight = Math.max(minHeight, estimatedTileViewHeight); + } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index d2e94d6a20a5..776a90d75a75 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -4813,7 +4813,9 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump if (!mHeadsUpTouchHelper.isTrackingHeadsUp() && mQsController.handleTouch( event, isFullyCollapsed(), isShadeOrQsHeightAnimationRunning())) { - mShadeLog.logMotionEvent(event, "onTouch: handleQsTouch handled event"); + if (event.getActionMasked() != MotionEvent.ACTION_MOVE) { + mShadeLog.logMotionEvent(event, "onTouch: handleQsTouch handled event"); + } return true; } if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) { @@ -4827,7 +4829,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump } handled |= handleTouch(event); - mShadeLog.logOnTouchEventLastReturn(event, !mDozing, handled); return !mDozing || handled; } @@ -5010,7 +5011,6 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump } break; } - mShadeLog.logHandleTouchLastReturn(event, !mGestureWaitForTouchSlop, mTracking); return !mGestureWaitForTouchSlop || mTracking; } diff --git a/packages/SystemUI/src/com/android/systemui/shade/QsBatteryModeController.kt b/packages/SystemUI/src/com/android/systemui/shade/QsBatteryModeController.kt index ff57a73a8d6d..3eec7fa0e84a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/QsBatteryModeController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/QsBatteryModeController.kt @@ -39,12 +39,19 @@ constructor( * [cutout]. We don't show battery estimation in qqs header on the devices with center cutout. * The result might be null when the battery icon is invisible during the qs-qqs transition * animation. - * - * Note: short-circuiting this value until a comprehensive fix for b/282044659 is finished. */ @BatteryMeterView.BatteryPercentMode fun getBatteryMode(cutout: DisplayCutout?, qsExpandedFraction: Float): Int? = - BatteryMeterView.MODE_ON + when { + qsExpandedFraction > fadeInStartFraction -> BatteryMeterView.MODE_ESTIMATE + qsExpandedFraction < fadeOutCompleteFraction -> + if (hasCenterCutout(cutout)) { + BatteryMeterView.MODE_ON + } else { + BatteryMeterView.MODE_ESTIMATE + } + else -> null + } fun updateResources() { fadeInStartFraction = diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java index 6480164cdaf5..7d66a0b431fa 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java @@ -1186,7 +1186,6 @@ public class QuickSettingsController implements Dumpable { mClippingAnimationEndBounds.left, fraction); int animTop = (int) MathUtils.lerp(startTop, mClippingAnimationEndBounds.top, fraction); - logClippingTopBound("interpolated top bound", top); int animRight = (int) MathUtils.lerp(startRight, mClippingAnimationEndBounds.right, fraction); int animBottom = (int) MathUtils.lerp(startBottom, @@ -1216,7 +1215,8 @@ public class QuickSettingsController implements Dumpable { if (mIsFullWidth) { clipStatusView = qsVisible; float screenCornerRadius = - mRecordingController.isRecording() || mCastController.hasConnectedCastDevice() + !mSplitShadeEnabled || mRecordingController.isRecording() + || mCastController.hasConnectedCastDevice() ? 0 : mScreenCornerRadius; radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius, Math.min(top / (float) mScrimCornerRadius, 1f)); @@ -1337,8 +1337,6 @@ public class QuickSettingsController implements Dumpable { // the screen without clipping. return -mAmbientState.getStackTopMargin(); } else { - logNotificationsClippingTopBound(qsTop, - mNotificationStackScrollLayoutController.getTop()); return qsTop - mNotificationStackScrollLayoutController.getTop(); } } @@ -1380,25 +1378,21 @@ public class QuickSettingsController implements Dumpable { keyguardNotificationStaticPadding, maxQsPadding) : maxQsPadding; topPadding = (int) MathUtils.lerp((float) getMinExpansionHeight(), (float) max, expandedFraction); - logNotificationsTopPadding("keyguard and expandImmediate", topPadding); return topPadding; } else if (isSizeChangeAnimationRunning()) { topPadding = Math.max((int) mSizeChangeAnimator.getAnimatedValue(), keyguardNotificationStaticPadding); - logNotificationsTopPadding("size change animation running", topPadding); return topPadding; } else if (keyguardShowing) { // We can only do the smoother transition on Keyguard when we also are not collapsing // from a scrolled quick settings. topPadding = MathUtils.lerp((float) keyguardNotificationStaticPadding, (float) (getMaxExpansionHeight()), computeExpansionFraction()); - logNotificationsTopPadding("keyguard", topPadding); return topPadding; } else { topPadding = Math.max(mQsFrameTranslateController.getNotificationsTopPadding( mExpansionHeight, mNotificationStackScrollLayoutController), mQuickQsHeaderHeight); - logNotificationsTopPadding("default case", topPadding); return topPadding; } } @@ -1446,38 +1440,6 @@ public class QuickSettingsController implements Dumpable { - mAmbientState.getScrollY()); } - /** TODO(b/273591201): remove after bug resolved */ - private void logNotificationsTopPadding(String message, float rawPadding) { - int padding = ((int) rawPadding / 10) * 10; - if (mBarState != KEYGUARD && padding != mLastNotificationsTopPadding && !mExpanded) { - mLastNotificationsTopPadding = padding; - mShadeLog.logNotificationsTopPadding(message, padding); - } - } - - /** TODO(b/273591201): remove after bug resolved */ - private void logClippingTopBound(String message, int top) { - top = (top / 10) * 10; - if (mBarState != KEYGUARD && mShadeExpandedFraction == 1 - && top != mLastClippingTopBound && !mExpanded) { - mLastClippingTopBound = top; - mShadeLog.logClippingTopBound(message, top); - } - } - - /** TODO(b/273591201): remove after bug resolved */ - private void logNotificationsClippingTopBound(int top, int nsslTop) { - top = (top / 10) * 10; - nsslTop = (nsslTop / 10) * 10; - if (mBarState == SHADE && mShadeExpandedFraction == 1 - && (top != mLastNotificationsClippingTopBound - || nsslTop != mLastNotificationsClippingTopBoundNssl) && !mExpanded) { - mLastNotificationsClippingTopBound = top; - mLastNotificationsClippingTopBoundNssl = nsslTop; - mShadeLog.logNotificationsClippingTopBound(top, nsslTop); - } - } - private int calculateTopClippingBound(int qsPanelBottomY) { int top; if (mSplitShadeEnabled) { @@ -1487,7 +1449,6 @@ public class QuickSettingsController implements Dumpable { // If we're transitioning, let's use the actual value. The else case // can be wrong during transitions when waiting for the keyguard to unlock top = mTransitionToFullShadePosition; - logClippingTopBound("set while transitioning to full shade", top); } else { final float notificationTop = getEdgePosition(); if (mBarState == KEYGUARD) { @@ -1496,10 +1457,8 @@ public class QuickSettingsController implements Dumpable { // this should go away once we unify the stackY position and don't have // to do this min anymore below. top = qsPanelBottomY; - logClippingTopBound("bypassing keyguard", top); } else { top = (int) Math.min(qsPanelBottomY, notificationTop); - logClippingTopBound("keyguard default case", top); } } else { top = (int) notificationTop; @@ -1507,14 +1466,12 @@ public class QuickSettingsController implements Dumpable { } // TODO (b/265193930): remove dependency on NPVC top += mPanelViewControllerLazy.get().getOverStretchAmount(); - logClippingTopBound("including overstretch", top); // Correction for instant expansion caused by HUN pull down/ float minFraction = mPanelViewControllerLazy.get().getMinFraction(); if (minFraction > 0f && minFraction < 1f) { float realFraction = (mShadeExpandedFraction - minFraction) / (1f - minFraction); top *= MathUtils.saturate(realFraction / minFraction); - logClippingTopBound("after adjusted fraction", top); } } return top; @@ -1654,15 +1611,11 @@ public class QuickSettingsController implements Dumpable { // as sometimes the qsExpansionFraction can be a tiny value instead of 0 when in QQS. if (!mSplitShadeEnabled && !mLastShadeFlingWasExpanding && computeExpansionFraction() <= 0.01 && mShadeExpandedFraction < 1.0) { - mShadeLog.logMotionEvent(event, - "handleQsTouch: shade touched while shade collapsing, QS tracking disabled"); mTracking = false; } if (!isExpandImmediate() && mTracking) { onTouch(event); if (!mConflictingExpansionGesture && !mSplitShadeEnabled) { - mShadeLog.logMotionEvent(event, - "handleQsTouch: not immediate expand or conflicting gesture"); return true; } } @@ -1756,7 +1709,6 @@ public class QuickSettingsController implements Dumpable { break; case MotionEvent.ACTION_MOVE: - mShadeLog.logMotionEvent(event, "onQsTouch: move action, setting QS expansion"); setExpansionHeight(h + mInitialHeightOnTouch); // TODO (b/265193930): remove dependency on NPVC if (h >= mPanelViewControllerLazy.get().getFalsingThreshold()) { @@ -1844,17 +1796,14 @@ public class QuickSettingsController implements Dumpable { final float h = y - mInitialTouchY; trackMovement(event); if (mTracking) { - // Already tracking because onOverscrolled was called. We need to update here // so we don't stop for a frame until the next touch event gets handled in // onTouchEvent. setExpansionHeight(h + mInitialHeightOnTouch); trackMovement(event); return true; - } else { - mShadeLog.logMotionEvent(event, - "onQsIntercept: move ignored because qs tracking disabled"); } + // TODO (b/265193930): remove dependency on NPVC float touchSlop = event.getClassification() == MotionEvent.CLASSIFICATION_AMBIGUOUS_GESTURE @@ -1878,7 +1827,7 @@ public class QuickSettingsController implements Dumpable { } else { mShadeLog.logQsTrackingNotStarted(mInitialTouchY, y, h, touchSlop, getExpanded(), mPanelViewControllerLazy.get().isKeyguardShowing(), - isExpansionEnabled()); + isExpansionEnabled(), event.getDownTime()); } break; diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt index 2b772e372f77..2da8d5f4d921 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt @@ -54,7 +54,8 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) { touchSlop: Float, qsExpanded: Boolean, keyguardShowing: Boolean, - qsExpansionEnabled: Boolean + qsExpansionEnabled: Boolean, + downTime: Long ) { buffer.log( TAG, @@ -67,10 +68,11 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) { bool1 = qsExpanded bool2 = keyguardShowing bool3 = qsExpansionEnabled + str1 = downTime.toString() }, { - "QsTrackingNotStarted: initTouchY=$int1,y=$int2,h=$long1,slop=$double1,qsExpanded" + - "=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3" + "QsTrackingNotStarted: downTime=$str1,initTouchY=$int1,y=$int2,h=$long1," + + "slop=$double1,qsExpanded=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3" } ) } @@ -306,91 +308,6 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) { ) } - fun logNotificationsTopPadding(message: String, padding: Int) { - buffer.log( - TAG, - LogLevel.VERBOSE, - { - str1 = message - int1 = padding - }, - { "QSC NotificationsTopPadding $str1: $int1"} - ) - } - - fun logClippingTopBound(message: String, top: Int) { - buffer.log( - TAG, - LogLevel.VERBOSE, - { - str1 = message - int1 = top - }, - { "QSC ClippingTopBound $str1: $int1" } - ) - } - - fun logNotificationsClippingTopBound(top: Int, nsslTop: Int) { - buffer.log( - TAG, - LogLevel.VERBOSE, - { - int1 = top - int2 = nsslTop - }, - { "QSC NotificationsClippingTopBound set to $int1 - $int2" } - ) - } - - fun logOnTouchEventLastReturn( - event: MotionEvent, - dozing: Boolean, - handled: Boolean, - ) { - buffer.log( - TAG, - LogLevel.VERBOSE, - { - bool1 = dozing - bool2 = handled - long1 = event.eventTime - long2 = event.downTime - int1 = event.action - int2 = event.classification - double1 = event.y.toDouble() - }, - { - "NPVC onTouchEvent last return: !mDozing: $bool1 || handled: $bool2 " + - "\neventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2" - } - ) - } - - fun logHandleTouchLastReturn( - event: MotionEvent, - gestureWaitForTouchSlop: Boolean, - tracking: Boolean, - ) { - buffer.log( - TAG, - LogLevel.VERBOSE, - { - bool1 = gestureWaitForTouchSlop - bool2 = tracking - long1 = event.eventTime - long2 = event.downTime - int1 = event.action - int2 = event.classification - double1 = event.y.toDouble() - }, - { - "NPVC handleTouch last return: !mGestureWaitForTouchSlop: $bool1 " + - "|| mTracking: $bool2 " + - "\neventTime=$long1,downTime=$long2,y=$double1,action=$int1,class=$int2" - } - ) - } - fun logUpdateNotificationPanelTouchState( disabled: Boolean, isGoingToSleep: Boolean, diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java index fc1e87ad3e45..ad49b267c6ac 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java @@ -198,6 +198,11 @@ public class ShadeCarrierGroupController { return mSlotIndexResolver.getSlotIndex(subscriptionId); } + @VisibleForTesting + protected int getShadeCarrierVisibility(int index) { + return mCarrierGroups[index].getVisibility(); + } + /** * Sets a {@link OnSingleCarrierChangedListener}. * @@ -307,11 +312,13 @@ public class ShadeCarrierGroupController { + info.subscriptionIds[i]); continue; } - mInfos[slot] = mInfos[slot].changeVisibility(true); - slotSeen[slot] = true; - mCarrierGroups[slot].setCarrierText( - info.listOfCarriers[i].toString().trim()); - mCarrierGroups[slot].setVisibility(View.VISIBLE); + String carrierText = info.listOfCarriers[i].toString().trim(); + if (!TextUtils.isEmpty(carrierText)) { + mInfos[slot] = mInfos[slot].changeVisibility(true); + slotSeen[slot] = true; + mCarrierGroups[slot].setCarrierText(carrierText); + mCarrierGroups[slot].setVisibility(View.VISIBLE); + } } for (int i = 0; i < SIM_SLOTS; i++) { if (!slotSeen[i]) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java index 731ec80817ca..d47fe20911f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java @@ -63,10 +63,27 @@ public class HighPriorityProvider { * - has a media session associated with it * - has messaging style * - * A GroupEntry is considered high priority if its representativeEntry (summary) or children are - * high priority + * A GroupEntry is considered high priority if its representativeEntry (summary) or any of its + * children are high priority. */ public boolean isHighPriority(@Nullable ListEntry entry) { + return isHighPriority(entry, /* allowImplicit = */ true); + } + + /** + * @return true if the ListEntry is explicitly high priority, else false + * + * A NotificationEntry is considered explicitly high priority if has importance greater than or + * equal to IMPORTANCE_DEFAULT. + * + * A GroupEntry is considered explicitly high priority if its representativeEntry (summary) or + * any of its children are explicitly high priority. + */ + public boolean isExplicitlyHighPriority(@Nullable ListEntry entry) { + return isHighPriority(entry, /* allowImplicit= */ false); + } + + private boolean isHighPriority(@Nullable ListEntry entry, boolean allowImplicit) { if (entry == null) { return false; } @@ -77,8 +94,8 @@ public class HighPriorityProvider { } return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT - || hasHighPriorityCharacteristics(notifEntry) - || hasHighPriorityChild(entry); + || (allowImplicit && hasHighPriorityCharacteristics(notifEntry)) + || hasHighPriorityChild(entry, allowImplicit); } /** @@ -112,7 +129,7 @@ public class HighPriorityProvider { >= NotificationManager.IMPORTANCE_DEFAULT); } - private boolean hasHighPriorityChild(ListEntry entry) { + private boolean hasHighPriorityChild(ListEntry entry, boolean allowImplicit) { if (entry instanceof NotificationEntry && !mGroupMembershipManager.isGroupSummary((NotificationEntry) entry)) { return false; @@ -121,7 +138,7 @@ public class HighPriorityProvider { List<NotificationEntry> children = mGroupMembershipManager.getChildren(entry); if (children != null) { for (NotificationEntry child : children) { - if (child != entry && isHighPriority(child)) { + if (child != entry && isHighPriority(child, allowImplicit)) { return true; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt index 7513aa7fa2a2..90014c2518d1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt @@ -180,8 +180,8 @@ private class KeyguardNotificationVisibilityProviderImpl @Inject constructor( } private fun shouldHideIfEntrySilent(entry: ListEntry): Boolean = when { - // Show if high priority (not hidden) - highPriorityProvider.isHighPriority(entry) -> false + // Show if explicitly high priority (not hidden) + highPriorityProvider.isExplicitlyHighPriority(entry) -> false // Ambient notifications are hidden always from lock screen entry.representativeEntry?.isAmbient == true -> true // [Now notification is silent] diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 1cd0f081a744..648ece527bef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -475,6 +475,13 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { */ private boolean mShouldDelayWakeUpAnimation = false; + /** + * Whether we should delay the AOD->Lockscreen animation. + * If false, the animation will start in onStartedWakingUp(). + * If true, the animation will start in onFinishedWakingUp(). + */ + private boolean mShouldDelayLockscreenTransitionFromAod = false; + private final Object mQueueLock = new Object(); private final PulseExpansionHandler mPulseExpansionHandler; @@ -3242,7 +3249,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { updateVisibleToUser(); updateIsKeyguard(); - if (!mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) { + mShouldDelayLockscreenTransitionFromAod = mDozeParameters.getAlwaysOn() + && mFeatureFlags.isEnabled( + Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD); + if (!mShouldDelayLockscreenTransitionFromAod) { startLockscreenTransitionFromAod(); } }); @@ -3251,8 +3261,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { /** * Private helper for starting the LOCKSCREEN_TRANSITION_FROM_AOD animation - only necessary - * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp() depending - * on a flag value. + * so we can start it from either onFinishedWakingUp() or onFinishedWakingUp(). */ private void startLockscreenTransitionFromAod() { // stopDozing() starts the LOCKSCREEN_TRANSITION_FROM_AOD animation. @@ -3273,7 +3282,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { @Override public void onFinishedWakingUp() { - if (mFeatureFlags.isEnabled(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD)) { + if (mShouldDelayLockscreenTransitionFromAod) { mNotificationShadeWindowController.batchApplyWindowLayoutParams( this::startLockscreenTransitionFromAod); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java index 7bc4fc3c5e47..ae70384aa71a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java @@ -115,7 +115,6 @@ public class LightBarTransitionsController implements Dumpable { }; private final Context mContext; - private Boolean mOverrideIconTintForNavMode; @AssistedInject public LightBarTransitionsController( @@ -276,19 +275,11 @@ public class LightBarTransitionsController implements Dumpable { } /** - * Specify an override value to return for {@link #overrideIconTintForNavMode(boolean)}. - */ - public void overrideIconTintForNavMode(boolean overrideValue) { - mOverrideIconTintForNavMode = overrideValue; - } - /** * Return whether to use the tint calculated in this class for nav icons. */ public boolean supportsIconTintForNavMode(int navigationMode) { // In gesture mode, we already do region sampling to update tint based on content beneath. - return mOverrideIconTintForNavMode != null - ? mOverrideIconTintForNavMode - : !QuickStepContract.isGesturalMode(navigationMode); + return !QuickStepContract.isGesturalMode(navigationMode); } /** diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java index ae3a320cde54..fa32835c2695 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.KeyEvent; @@ -183,4 +184,15 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { mKeyguardAbsKeyInputViewController.onResume(KeyguardSecurityView.VIEW_REVEALED); verify(mLockPatternUtils).getLockoutAttemptDeadline(anyInt()); } + + @Test + public void testLockedOut_verifyPasswordAndUnlock_doesNotEnableViewInput() { + mKeyguardAbsKeyInputViewController.handleAttemptLockout( + SystemClock.elapsedRealtime() + 1000); + mKeyguardAbsKeyInputViewController.verifyPasswordAndUnlock(); + verify(mAbsKeyInputView).setPasswordEntryInputEnabled(false); + verify(mAbsKeyInputView).setPasswordEntryEnabled(false); + verify(mAbsKeyInputView, never()).setPasswordEntryInputEnabled(true); + verify(mAbsKeyInputView, never()).setPasswordEntryEnabled(true); + } } 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 8a422c895052..c280538f2d30 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -22,6 +22,8 @@ import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; +import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE; +import static com.android.systemui.keyguard.KeyguardViewMediator.SYS_BOOT_REASON_PROP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -72,6 +74,7 @@ import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FakeFeatureFlags; import com.android.systemui.flags.Flags; +import com.android.systemui.flags.SystemPropertiesHelper; import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel; import com.android.systemui.log.SessionTracker; import com.android.systemui.navigationbar.NavigationModeController; @@ -153,6 +156,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock ShadeWindowLogger mShadeWindowLogger; private @Captor ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor; + private @Captor ArgumentCaptor<KeyguardStateController.Callback> + mKeyguardStateControllerCallback; private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake(); private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -161,6 +166,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock CentralSurfaces mCentralSurfaces; private @Mock UiEventLogger mUiEventLogger; private @Mock SessionTracker mSessionTracker; + private @Mock SystemPropertiesHelper mSystemPropertiesHelper; private @Mock CoroutineDispatcher mDispatcher; private @Mock DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel; @@ -357,6 +363,23 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { } @Test + public void testBouncerPrompt_deviceRestartedDueToMainlineUpdate() { + // GIVEN biometrics enrolled + when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true); + + // WHEN reboot caused by ota update + KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker = + mock(KeyguardUpdateMonitor.StrongAuthTracker.class); + when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker); + when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(false); + when(mSystemPropertiesHelper.get(SYS_BOOT_REASON_PROP)).thenReturn(REBOOT_MAINLINE_UPDATE); + + // THEN the bouncer prompt reason should return PROMPT_REASON_RESTART_FOR_OTA + assertEquals(KeyguardSecurityView.PROMPT_REASON_RESTART_FOR_MAINLINE_UPDATE, + mViewMediator.mViewMediatorCallback.getBouncerPromptReason()); + } + + @Test public void testBouncerPrompt_afterUserLockDown() { // GIVEN biometrics enrolled when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true); @@ -641,6 +664,33 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { ); } + @Test + @TestableLooper.RunWithLooper(setAsMainLooper = true) + public void pendingPinLockOnKeyguardGoingAway_doKeyguardLockedOnKeyguardVisibilityChanged() { + // GIVEN SIM_STATE_PIN_REQUIRED + mViewMediator.onSystemReady(); + final KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback = + mViewMediator.mUpdateCallback; + keyguardUpdateMonitorCallback.onSimStateChanged(0, 0, + TelephonyManager.SIM_STATE_PIN_REQUIRED); + TestableLooper.get(this).processAllMessages(); + + // ...and then the primary bouncer shows while the keyguard is going away + captureKeyguardStateControllerCallback(); + when(mKeyguardStateController.isPrimaryBouncerShowing()).thenReturn(true); + when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true); + mKeyguardStateControllerCallback.getValue().onPrimaryBouncerShowingChanged(); + TestableLooper.get(this).processAllMessages(); + + // WHEN keyguard visibility becomes FALSE + mViewMediator.setShowingLocked(false); + keyguardUpdateMonitorCallback.onKeyguardVisibilityChanged(false); + TestableLooper.get(this).processAllMessages(); + + // THEN keyguard shows due to the pending SIM PIN lock + assertTrue(mViewMediator.isShowingAndNotOccluded()); + } + private void createAndStartViewMediator() { mViewMediator = new KeyguardViewMediator( mContext, @@ -677,7 +727,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { () -> mScrimController, mFeatureFlags, mDispatcher, - () -> mDreamingToLockscreenTransitionViewModel); + () -> mDreamingToLockscreenTransitionViewModel, + mSystemPropertiesHelper); mViewMediator.start(); mViewMediator.registerCentralSurfaces(mCentralSurfaces, null, null, null, null, null); @@ -686,4 +737,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private void captureKeyguardUpdateMonitorCallback() { verify(mUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallbackCaptor.capture()); } + + private void captureKeyguardStateControllerCallback() { + verify(mKeyguardStateController).addCallback(mKeyguardStateControllerCallback.capture()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt index 9e798490eaff..0ef77e8b9216 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/factory/BouncerMessageFactoryTest.kt @@ -34,6 +34,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock @@ -42,6 +43,7 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) +@Ignore("b/236891644") class BouncerMessageFactoryTest : SysuiTestCase() { private lateinit var underTest: BouncerMessageFactory diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt index 1277fc0e1bdd..a729de5eced5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/data/repository/BouncerMessageRepositoryTest.kt @@ -61,6 +61,7 @@ import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor @@ -73,6 +74,7 @@ import org.mockito.MockitoAnnotations @SmallTest @TestableLooper.RunWithLooper(setAsMainLooper = true) @RunWith(AndroidJUnit4::class) +@Ignore("b/236891644") class BouncerMessageRepositoryTest : SysuiTestCase() { @Mock private lateinit var updateMonitor: KeyguardUpdateMonitor diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt index b0af3104a3ae..3a87680bb24c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/bouncer/domain/interactor/BouncerMessageInteractorTest.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Before +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq @@ -53,6 +54,7 @@ import org.mockito.MockitoAnnotations @SmallTest @TestableLooper.RunWithLooper(setAsMainLooper = true) @RunWith(AndroidJUnit4::class) +@Ignore("b/236891644") class BouncerMessageInteractorTest : SysuiTestCase() { @Mock private lateinit var securityModel: KeyguardSecurityModel diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt index b028f1fd3664..d421acac2daa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QsBatteryModeControllerTest.kt @@ -63,40 +63,36 @@ class QsBatteryModeControllerTest : SysuiTestCase() { @Test fun returnsMODE_ESTIMATEforQsWithCenterCutout() { - // TODO (b/282044659): revert this test to previous behavior assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction())) - .isEqualTo(BatteryMeterView.MODE_ON) + .isEqualTo(BatteryMeterView.MODE_ESTIMATE) } @Test fun returnsMODE_ONforQqsWithCornerCutout() { whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true) - // TODO (b/282044659): revert this test to previous behavior assertThat( controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.prevFrameToFraction()) ) - .isEqualTo(BatteryMeterView.MODE_ON) + .isEqualTo(BatteryMeterView.MODE_ESTIMATE) } @Test fun returnsMODE_ESTIMATEforQsWithCornerCutout() { whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(true) - // TODO (b/282044659): revert this test to previous behavior assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.nextFrameToFraction())) - .isEqualTo(BatteryMeterView.MODE_ON) + .isEqualTo(BatteryMeterView.MODE_ESTIMATE) } @Test fun returnsNullInBetween() { - // TODO (b/282044659): revert this test to previous behavior assertThat( controller.getBatteryMode(CENTER_TOP_CUTOUT, QQS_START_FRAME.nextFrameToFraction()) ) - .isEqualTo(BatteryMeterView.MODE_ON) + .isNull() assertThat(controller.getBatteryMode(CENTER_TOP_CUTOUT, QS_END_FRAME.prevFrameToFraction())) - .isEqualTo(BatteryMeterView.MODE_ON) + .isNull() } private fun Int.prevFrameToFraction(): Float = (this - 1) / MOTION_LAYOUT_MAX_FRAME.toFloat() diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java index 57ae621f01ef..31bfa3fdf8cb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java @@ -66,6 +66,11 @@ import org.mockito.MockitoAnnotations; @SmallTest public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { + private static final String SINGLE_CARRIER_TEXT = "singleCarrierText"; + private static final String MULTI_CARRIER_TEXT = "multiCarrierText"; + private static final String FIRST_CARRIER_NAME = "carrier1"; + private static final String SECOND_CARRIER_NAME = "carrier2"; + private ShadeCarrierGroupController mShadeCarrierGroupController; private SignalCallback mSignalCallback; private CarrierTextManager.CarrierTextCallback mCallback; @@ -148,8 +153,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 1, subscriptionIds length 1, anySims false CarrierTextManager.CarrierTextCallbackInfo c1 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME}, false, new int[]{0}); mCallback.updateCarrierInfo(c1); @@ -157,8 +162,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 1, subscriptionIds length 1, anySims true CarrierTextManager.CarrierTextCallbackInfo c2 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME}, true, new int[]{0}); mCallback.updateCarrierInfo(c2); @@ -166,8 +171,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 2, subscriptionIds length 2, anySims false CarrierTextManager.CarrierTextCallbackInfo c3 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, false, new int[]{0, 1}); mCallback.updateCarrierInfo(c3); @@ -175,8 +180,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 2, subscriptionIds length 2, anySims true CarrierTextManager.CarrierTextCallbackInfo c4 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, true, new int[]{0, 1}); mCallback.updateCarrierInfo(c4); @@ -189,8 +194,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 2, subscriptionIds length 1, anySims false CarrierTextManager.CarrierTextCallbackInfo c1 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, false, new int[]{0}); mCallback.updateCarrierInfo(c1); @@ -198,8 +203,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 2, subscriptionIds length 1, anySims true CarrierTextManager.CarrierTextCallbackInfo c2 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, true, new int[]{0}); mCallback.updateCarrierInfo(c2); @@ -207,8 +212,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 1, subscriptionIds length 2, anySims false CarrierTextManager.CarrierTextCallbackInfo c3 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME}, false, new int[]{0, 1}); mCallback.updateCarrierInfo(c3); @@ -216,8 +221,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // listOfCarriers length 1, subscriptionIds length 2, anySims true CarrierTextManager.CarrierTextCallbackInfo c4 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME}, true, new int[]{0, 1}); mCallback.updateCarrierInfo(c4); @@ -230,8 +235,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { CarrierTextManager.CarrierTextCallbackInfo c4 = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, true, new int[]{0, 1}); mCallback.updateCarrierInfo(c4); @@ -264,6 +269,20 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { } @Test + public void testVisibleView_airplaneMode_WFCOn() { + CarrierTextManager.CarrierTextCallbackInfo + info = new CarrierTextManager.CarrierTextCallbackInfo( + "", + new CharSequence[]{FIRST_CARRIER_NAME, ""}, + true, + new int[]{0, 1}, + false /* airplaneMode */); + mCallback.updateCarrierInfo(info); + mTestableLooper.processAllMessages(); + assertEquals(View.VISIBLE, mShadeCarrierGroupController.getShadeCarrierVisibility(0)); + } + + @Test public void testListenerNotCalledOnRegistreation() { mShadeCarrierGroupController .setOnSingleCarrierChangedListener(mOnSingleCarrierChangedListener); @@ -276,8 +295,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // Only one element in the info CarrierTextManager.CarrierTextCallbackInfo info = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{SINGLE_CARRIER_TEXT}, true, new int[]{0}, false /* airplaneMode */); @@ -295,8 +314,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { // More than one element in the info CarrierTextManager.CarrierTextCallbackInfo info = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, true, new int[]{0, 1}, false /* airplaneMode */); @@ -313,16 +332,16 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { public void testSingleMultiCarrierSwitch() { CarrierTextManager.CarrierTextCallbackInfo singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME}, true, new int[]{0}, false /* airplaneMode */); CarrierTextManager.CarrierTextCallbackInfo multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, true, new int[]{0, 1}, false /* airplaneMode */); @@ -347,8 +366,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { public void testNoCallbackIfSingleCarrierDoesntChange() { CarrierTextManager.CarrierTextCallbackInfo singleCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{""}, + SINGLE_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME}, true, new int[]{0}, false /* airplaneMode */); @@ -369,8 +388,8 @@ public class ShadeCarrierGroupControllerTest extends LeakCheckedTest { public void testNoCallbackIfMultiCarrierDoesntChange() { CarrierTextManager.CarrierTextCallbackInfo multiCarrierInfo = new CarrierTextManager.CarrierTextCallbackInfo( - "", - new CharSequence[]{"", ""}, + MULTI_CARRIER_TEXT, + new CharSequence[]{FIRST_CARRIER_NAME, SECOND_CARRIER_NAME}, true, new int[]{0, 1}, false /* airplaneMode */); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java index ac66ad9e9c8d..2d044fec1eb6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java @@ -92,8 +92,9 @@ public class HighPriorityProviderTest extends SysuiTestCase { .getPeopleNotificationType(entry)) .thenReturn(TYPE_PERSON); - // THEN it has high priority + // THEN it has high priority BUT it has low explicit priority. assertTrue(mHighPriorityProvider.isHighPriority(entry)); + assertFalse(mHighPriorityProvider.isExplicitlyHighPriority(entry)); } @Test @@ -115,7 +116,7 @@ public class HighPriorityProviderTest extends SysuiTestCase { @Test public void lowImportanceConversation() { - // GIVEN notification is high importance and is a people notification + // GIVEN notification is low importance and is a people notification final Notification notification = new Notification.Builder(mContext, "test") .build(); final NotificationEntry entry = new NotificationEntryBuilder() @@ -162,8 +163,9 @@ public class HighPriorityProviderTest extends SysuiTestCase { .getPeopleNotificationType(entry)) .thenReturn(TYPE_NON_PERSON); - // THEN it has high priority + // THEN it has high priority but low explicit priority assertTrue(mHighPriorityProvider.isHighPriority(entry)); + assertFalse(mHighPriorityProvider.isExplicitlyHighPriority(entry)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java index 6bd3f7a27413..8f39ee6a6e9f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java @@ -257,7 +257,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_LOW) .setParent(parent) .build(); - when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false); assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); } @@ -270,7 +270,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { .setUser(new UserHandle(NOTIF_USER_ID)) .setImportance(IMPORTANCE_LOW) .build(); - when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false); assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); } @@ -292,7 +292,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { .setImportance(IMPORTANCE_LOW) .setParent(parent) .build(); - when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false); assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); } @@ -309,7 +309,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { mEntry = new NotificationEntryBuilder() .setImportance(IMPORTANCE_LOW) .build(); - when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false); // THEN filter out the entry assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); @@ -328,7 +328,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { mEntry = new NotificationEntryBuilder() .setImportance(IMPORTANCE_LOW) .build(); - when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(false); // THEN do not filter out the entry assertFalse(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); @@ -345,7 +345,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { .setUser(new UserHandle(NOTIF_USER_ID)) .setImportance(IMPORTANCE_LOW) .build(); - when(mHighPriorityProvider.isHighPriority(any())).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(any())).thenReturn(false); // WhHEN the show silent notifs on lockscreen setting is unset assertNull(mFakeSettings.getString(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS)); @@ -460,13 +460,33 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { .setKey(mEntry.getKey()) .setImportance(IMPORTANCE_MIN) .build()); - when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(false); // THEN filter out the entry assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); } @Test + public void highPriorityCharacteristicsIgnored() { + // GIVEN an 'unfiltered-keyguard-showing' state with silent notifications hidden + setupUnfilteredState(mEntry); + mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, true); + mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, false); + + // WHEN the notification doesn't exceed the threshold to show on the lockscreen, but does + // have the "high priority characteristics" that would promote it to high priority + mEntry.setRanking(new RankingBuilder() + .setKey(mEntry.getKey()) + .setImportance(IMPORTANCE_MIN) + .build()); + when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true); + when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(false); + + // THEN filter out the entry anyway, because the user explicitly asked us to hide it + assertTrue(mKeyguardNotificationVisibilityProvider.shouldHideNotification(mEntry)); + } + + @Test public void notificationVisibilityPublic() { // GIVEN a VISIBILITY_PUBLIC notification NotificationEntryBuilder entryBuilder = new NotificationEntryBuilder() @@ -538,14 +558,14 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { // WHEN its parent does exceed threshold tot show on the lockscreen mFakeSettings.putBool(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, false); - when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true); + when(mHighPriorityProvider.isExplicitlyHighPriority(parent)).thenReturn(true); // THEN filter out the entry regardless of parent assertTrue( mKeyguardNotificationVisibilityProvider.shouldHideNotification(entryWithParent)); // WHEN its parent doesn't exceed threshold to show on lockscreen - when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false); + when(mHighPriorityProvider.isExplicitlyHighPriority(parent)).thenReturn(false); modifyEntry(parent.getSummary(), builder -> builder .setImportance(IMPORTANCE_MIN) .done()); @@ -591,7 +611,7 @@ public class KeyguardNotificationVisibilityProviderTest extends SysuiTestCase { // notification doesn't have a summary // notification is high priority, so it shouldn't be filtered - when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true); + when(mHighPriorityProvider.isExplicitlyHighPriority(mEntry)).thenReturn(true); } @SysUISingleton diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 85b1ec108e98..40e7e8d61b5e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -61,7 +61,6 @@ import android.view.WindowInsets; import android.view.WindowInsetsAnimation; import android.widget.TextView; -import androidx.test.annotation.UiThreadTest; import androidx.test.filters.SmallTest; import com.android.keyguard.BouncerPanelExpansionCalculator; @@ -84,12 +83,11 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.FooterView; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.phone.ScreenOffAnimationController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -103,7 +101,6 @@ import java.util.ArrayList; /** * Tests for {@link NotificationStackScrollLayout}. */ -@Ignore("b/255552856") @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -113,7 +110,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { private NotificationStackScrollLayout mStackScrollerInternal; // See explanation below private AmbientState mAmbientState; private TestableResources mTestableResources; - @Rule public MockitoRule mockito = MockitoJUnit.rule(); @Mock private CentralSurfaces mCentralSurfaces; @Mock private SysuiStatusBarStateController mBarState; @@ -128,7 +124,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationSection mNotificationSection; @Mock private NotificationSwipeHelper mNotificationSwipeHelper; @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController; - @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Mock private ScreenOffAnimationController mScreenOffAnimationController; @Mock private NotificationShelf mNotificationShelf; @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @@ -136,7 +132,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private FeatureFlags mFeatureFlags; @Before - @UiThreadTest public void setUp() throws Exception { allowTestableLooperAsMainThread(); mTestableResources = mContext.getOrCreateTestableResources(); @@ -162,7 +157,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mDependency.injectTestDependency(AmbientState.class, mAmbientState); mDependency.injectTestDependency(NotificationShelf.class, mNotificationShelf); mDependency.injectTestDependency( - UnlockedScreenOffAnimationController.class, mUnlockedScreenOffAnimationController); + ScreenOffAnimationController.class, mScreenOffAnimationController); NotificationShelfController notificationShelfController = mock(NotificationShelfController.class); @@ -364,7 +359,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @UiThreadTest public void testSetExpandedHeight_listenerReceivedCallbacks() { final float expectedHeight = 0f; @@ -375,20 +369,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - public void testAppearFractionCalculation() { - // appear start position - when(mNotificationShelf.getIntrinsicHeight()).thenReturn(100); - // because it's the same as shelf height, appear start position equals shelf height - mStackScroller.mStatusBarHeight = 100; - // appear end position - when(mEmptyShadeView.getHeight()).thenReturn(200); - - assertEquals(0f, mStackScroller.calculateAppearFraction(100)); - assertEquals(1f, mStackScroller.calculateAppearFraction(200)); - assertEquals(0.5f, mStackScroller.calculateAppearFraction(150)); - } - - @Test public void testAppearFractionCalculationIsNotNegativeWhenShelfBecomesSmaller() { // this situation might occur if status bar height is defined in pixels while shelf height // in dp and screen density changes - appear start position @@ -405,7 +385,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @UiThreadTest public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() { mTestableResources .addOverride(R.bool.config_use_split_notification_shade, /* value= */ true); @@ -590,6 +569,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testReInflatesFooterViews() { + when(mEmptyShadeView.getTextResource()).thenReturn(R.string.empty_shade_text); clearInvocations(mStackScroller); mStackScroller.reinflateViews(); verify(mStackScroller).setFooterView(any()); @@ -597,21 +577,18 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { } @Test - @UiThreadTest public void testSetIsBeingDraggedResetsExposedMenu() { mStackScroller.setIsBeingDragged(true); verify(mNotificationSwipeHelper).resetExposedMenuView(true, true); } @Test - @UiThreadTest public void testPanelTrackingStartResetsExposedMenu() { mStackScroller.onPanelTrackingStarted(); verify(mNotificationSwipeHelper).resetExposedMenuView(true, true); } @Test - @UiThreadTest public void testDarkModeResetsExposedMenu() { mStackScroller.setHideAmount(0.1f, 0.1f); verify(mNotificationSwipeHelper).resetExposedMenuView(true, true); @@ -916,7 +893,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mStackScroller.setHasFilteredOutSeenNotifications(true); mStackScroller.updateEmptyShadeView(true, false); - verify(mEmptyShadeView).setFooterText(not(0)); + verify(mEmptyShadeView).setFooterText(not(eq(0))); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 8062272a0042..77026308ad38 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -350,7 +350,9 @@ public class CentralSurfacesImplTest extends SysuiTestCase { // For the Shade to animate during the Back gesture, we must enable the animation flag. mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true); mFeatureFlags.set(Flags.LIGHT_REVEAL_MIGRATION, true); + // Turn AOD on and toggle feature flag for jank fixes mFeatureFlags.set(Flags.ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD, true); + when(mDozeParameters.getAlwaysOn()).thenReturn(true); IThermalService thermalService = mock(IThermalService.class); mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService, diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java index ac770439a524..82af38200166 100644 --- a/services/autofill/java/com/android/server/autofill/Helper.java +++ b/services/autofill/java/com/android/server/autofill/Helper.java @@ -46,6 +46,7 @@ import com.android.internal.util.ArrayUtils; import com.android.server.utils.Slogf; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; @@ -319,6 +320,13 @@ public final class Helper { return context.createDisplayContext(display); } + static <T> @Nullable T weakDeref(WeakReference<T> weakRef, String tag, String prefix) { + T deref = weakRef.get(); + if (deref == null) { + Slog.wtf(tag, prefix + "fail to deref " + weakRef); + } + return deref; + } private interface ViewNodeFilter { boolean matches(ViewNode node); diff --git a/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java b/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java index ea31074ff5d2..bcca0069eb34 100644 --- a/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java +++ b/services/autofill/java/com/android/server/autofill/RemoteFieldClassificationService.java @@ -44,6 +44,8 @@ import android.util.Slog; import com.android.internal.infra.AbstractRemoteService; import com.android.internal.infra.ServiceConnector; +import java.lang.ref.WeakReference; + /** * Class responsible for connection with the Remote {@link FieldClassificationService}. * This class is instantiated when {@link AutofillManagerServiceImpl} is established. @@ -133,7 +135,8 @@ final class RemoteFieldClassificationService } public void onFieldClassificationRequest(@NonNull FieldClassificationRequest request, - FieldClassificationServiceCallbacks fieldClassificationServiceCallbacks) { + WeakReference<FieldClassificationServiceCallbacks> + fieldClassificationServiceCallbacksWeakRef) { final long startTime = SystemClock.elapsedRealtime(); if (sVerbose) { Slog.v(TAG, "onFieldClassificationRequest request:" + request); @@ -170,6 +173,15 @@ final class RemoteFieldClassificationService Slog.d(TAG, "onSuccess " + msg); } } + FieldClassificationServiceCallbacks + fieldClassificationServiceCallbacks = + Helper.weakDeref( + fieldClassificationServiceCallbacksWeakRef, + TAG, "onSuccess " + ); + if (fieldClassificationServiceCallbacks == null) { + return; + } fieldClassificationServiceCallbacks .onClassificationRequestSuccess(response); } @@ -180,6 +192,15 @@ final class RemoteFieldClassificationService if (sDebug) { Slog.d(TAG, "onFailure"); } + FieldClassificationServiceCallbacks + fieldClassificationServiceCallbacks = + Helper.weakDeref( + fieldClassificationServiceCallbacksWeakRef, + TAG, "onFailure " + ); + if (fieldClassificationServiceCallbacks == null) { + return; + } fieldClassificationServiceCallbacks .onClassificationRequestFailure(0, null); } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 0c3f8667f4f8..fb26f427dad7 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -850,8 +850,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState RemoteFieldClassificationService remoteFieldClassificationService = mService.getRemoteFieldClassificationServiceLocked(); if (remoteFieldClassificationService != null) { + WeakReference<RemoteFieldClassificationService.FieldClassificationServiceCallbacks> + fieldClassificationServiceCallbacksWeakRef = + new WeakReference<>(Session.this); remoteFieldClassificationService.onFieldClassificationRequest( - mClassificationState.mPendingFieldClassificationRequest, Session.this); + mClassificationState.mPendingFieldClassificationRequest, + fieldClassificationServiceCallbacksWeakRef); } mClassificationState.onFieldClassificationRequestSent(); } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index fc84e1386d1f..c1239d53058c 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -406,6 +406,8 @@ public final class ActiveServices { // allowlisted packageName. ArraySet<String> mAllowListWhileInUsePermissionInFgs = new ArraySet<>(); + String mCachedDeviceProvisioningPackage; + // TODO: remove this after feature development is done private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -480,7 +482,8 @@ public final class ActiveServices { // (REASON_ALARM_MANAGER_ALARM_CLOCK), allow it to continue and do not stop it, // even the app is background-restricted. if (r.isForeground - && r.mAllowStartForegroundAtEntering != REASON_ALARM_MANAGER_ALARM_CLOCK) { + && r.mAllowStartForegroundAtEntering != REASON_ALARM_MANAGER_ALARM_CLOCK + && !isDeviceProvisioningPackage(r.packageName)) { toStop.add(r); } } @@ -880,7 +883,8 @@ public final class ActiveServices { boolean forcedStandby = false; if (bgLaunch && appRestrictedAnyInBackground(appUid, appPackageName) - && !isTempAllowedByAlarmClock(appUid)) { + && !isTempAllowedByAlarmClock(appUid) + && !isDeviceProvisioningPackage(appPackageName)) { if (DEBUG_FOREGROUND_SERVICE) { Slog.d(TAG, "Forcing bg-only service start only for " + r.shortInstanceName + " : bgLaunch=" + bgLaunch + " callerFg=" + callerFg); @@ -1926,6 +1930,9 @@ public final class ActiveServices { */ private boolean isForegroundServiceAllowedInBackgroundRestricted(ProcessRecord app) { final ProcessStateRecord state = app.mState; + if (isDeviceProvisioningPackage(app.info.packageName)) { + return true; + } if (!state.isBackgroundRestricted() || state.getSetProcState() <= ActivityManager.PROCESS_STATE_BOUND_TOP) { return true; @@ -8404,4 +8411,13 @@ public final class ActiveServices { } return results; } + + private boolean isDeviceProvisioningPackage(String packageName) { + if (mCachedDeviceProvisioningPackage == null) { + mCachedDeviceProvisioningPackage = mAm.mContext.getResources().getString( + com.android.internal.R.string.config_deviceProvisioningPackage); + } + return mCachedDeviceProvisioningPackage != null + && mCachedDeviceProvisioningPackage.equals(packageName); + } } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index 1fa2bea6e5ea..eccff2a74eac 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -123,7 +123,14 @@ public final class CachedAppOptimizer { "freeze_debounce_timeout"; @VisibleForTesting static final String KEY_FREEZER_EXEMPT_INST_PKG = "freeze_exempt_inst_pkg"; - + @VisibleForTesting static final String KEY_FREEZER_BINDER_ENABLED = + "freeze_binder_enabled"; + @VisibleForTesting static final String KEY_FREEZER_BINDER_DIVISOR = + "freeze_binder_divisor"; + @VisibleForTesting static final String KEY_FREEZER_BINDER_OFFSET = + "freeze_binder_offset"; + @VisibleForTesting static final String KEY_FREEZER_BINDER_THRESHOLD = + "freeze_binder_threshold"; static final int UNFREEZE_REASON_NONE = FrameworkStatsLog.APP_FREEZE_CHANGED__UNFREEZE_REASON_V2__UFR_NONE; @@ -237,8 +244,8 @@ public final class CachedAppOptimizer { @VisibleForTesting static final boolean ENABLE_FILE_COMPACT = false; // Defaults for phenotype flags. - @VisibleForTesting static final Boolean DEFAULT_USE_COMPACTION = true; - @VisibleForTesting static final Boolean DEFAULT_USE_FREEZER = true; + @VisibleForTesting static final boolean DEFAULT_USE_COMPACTION = true; + @VisibleForTesting static final boolean DEFAULT_USE_FREEZER = true; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_1 = 5_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_2 = 10_000; @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_3 = 500; @@ -257,7 +264,11 @@ public final class CachedAppOptimizer { @VisibleForTesting static final String DEFAULT_COMPACT_PROC_STATE_THROTTLE = String.valueOf(ActivityManager.PROCESS_STATE_RECEIVER); @VisibleForTesting static final long DEFAULT_FREEZER_DEBOUNCE_TIMEOUT = 10_000L; - @VisibleForTesting static final Boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true; + @VisibleForTesting static final boolean DEFAULT_FREEZER_EXEMPT_INST_PKG = true; + @VisibleForTesting static final boolean DEFAULT_FREEZER_BINDER_ENABLED = true; + @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_DIVISOR = 4; + @VisibleForTesting static final int DEFAULT_FREEZER_BINDER_OFFSET = 500; + @VisibleForTesting static final long DEFAULT_FREEZER_BINDER_THRESHOLD = 1_000; @VisibleForTesting static final Uri CACHED_APP_FREEZER_ENABLED_URI = Settings.Global.getUriFor( Settings.Global.CACHED_APPS_FREEZER_ENABLED); @@ -393,6 +404,11 @@ public final class CachedAppOptimizer { updateFreezerDebounceTimeout(); } else if (KEY_FREEZER_EXEMPT_INST_PKG.equals(name)) { updateFreezerExemptInstPkg(); + } else if (KEY_FREEZER_BINDER_ENABLED.equals(name) + || KEY_FREEZER_BINDER_DIVISOR.equals(name) + || KEY_FREEZER_BINDER_THRESHOLD.equals(name) + || KEY_FREEZER_BINDER_OFFSET.equals(name)) { + updateFreezerBinderState(); } } } @@ -455,6 +471,16 @@ public final class CachedAppOptimizer { @GuardedBy("mPhenotypeFlagLock") @VisibleForTesting final Set<Integer> mProcStateThrottle; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting volatile boolean mFreezerBinderEnabled = DEFAULT_FREEZER_BINDER_ENABLED; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting volatile long mFreezerBinderDivisor = DEFAULT_FREEZER_BINDER_DIVISOR; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting volatile int mFreezerBinderOffset = DEFAULT_FREEZER_BINDER_OFFSET; + @GuardedBy("mPhenotypeFlagLock") + @VisibleForTesting volatile long mFreezerBinderThreshold = DEFAULT_FREEZER_BINDER_THRESHOLD; + + // Handler on which compaction runs. @VisibleForTesting Handler mCompactionHandler; @@ -759,6 +785,10 @@ public final class CachedAppOptimizer { pw.println(" " + KEY_FREEZER_STATSD_SAMPLE_RATE + "=" + mFreezerStatsdSampleRate); pw.println(" " + KEY_FREEZER_DEBOUNCE_TIMEOUT + "=" + mFreezerDebounceTimeout); pw.println(" " + KEY_FREEZER_EXEMPT_INST_PKG + "=" + mFreezerExemptInstPkg); + pw.println(" " + KEY_FREEZER_BINDER_ENABLED + "=" + mFreezerBinderEnabled); + pw.println(" " + KEY_FREEZER_BINDER_THRESHOLD + "=" + mFreezerBinderThreshold); + pw.println(" " + KEY_FREEZER_BINDER_DIVISOR + "=" + mFreezerBinderDivisor); + pw.println(" " + KEY_FREEZER_BINDER_OFFSET + "=" + mFreezerBinderOffset); synchronized (mProcLock) { int size = mFrozenProcesses.size(); pw.println(" Apps frozen: " + size); @@ -1264,6 +1294,26 @@ public final class CachedAppOptimizer { Slog.d(TAG_AM, "Freezer exemption set to " + mFreezerExemptInstPkg); } + @GuardedBy("mPhenotypeFlagLock") + private void updateFreezerBinderState() { + mFreezerBinderEnabled = DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, + KEY_FREEZER_BINDER_ENABLED, DEFAULT_FREEZER_BINDER_ENABLED); + mFreezerBinderDivisor = DeviceConfig.getLong( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, + KEY_FREEZER_BINDER_DIVISOR, DEFAULT_FREEZER_BINDER_DIVISOR); + mFreezerBinderOffset = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, + KEY_FREEZER_BINDER_OFFSET, DEFAULT_FREEZER_BINDER_OFFSET); + mFreezerBinderThreshold = DeviceConfig.getLong( + DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT, + KEY_FREEZER_BINDER_THRESHOLD, DEFAULT_FREEZER_BINDER_THRESHOLD); + Slog.d(TAG_AM, "Freezer binder state set to enabled=" + mFreezerBinderEnabled + + ", divisor=" + mFreezerBinderDivisor + + ", offset=" + mFreezerBinderOffset + + ", threshold=" + mFreezerBinderThreshold); + } + private boolean parseProcStateThrottle(String procStateThrottleString) { String[] procStates = TextUtils.split(procStateThrottleString, ","); mProcStateThrottle.clear(); @@ -1352,6 +1402,7 @@ public final class CachedAppOptimizer { } } } + app.mOptRecord.setLastUsedTimeout(delayMillis); mFreezeHandler.sendMessageDelayed( mFreezeHandler.obtainMessage(SET_FROZEN_PROCESS_MSG, DO_FREEZE, 0, app), delayMillis); @@ -2121,12 +2172,54 @@ public final class CachedAppOptimizer { } @GuardedBy({"mAm", "mProcLock"}) - private void rescheduleFreeze(final ProcessRecord proc, final String reason, - @UnfreezeReason int reasonCode) { + private void handleBinderFreezerFailure(final ProcessRecord proc, final String reason) { + if (!mFreezerBinderEnabled) { + // Just reschedule indefinitely. + unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS); + freezeAppAsyncLSP(proc); + return; + } + /* + * This handles the case where a process couldn't be frozen due to pending binder + * transactions. In order to prevent apps from avoiding the freezer by spamming binder + * transactions, there is an exponential decrease in freezer retry times plus a random + * offset per attempt to avoid phase issues. Once the last-attempted timeout is below a + * threshold, we assume that the app is spamming binder calls and can never be frozen, + * and we will then crash the app. + */ + if (proc.mOptRecord.getLastUsedTimeout() <= mFreezerBinderThreshold) { + // We've given the app plenty of chances, assume broken. Time to die. + Slog.d(TAG_AM, "Kill app due to repeated failure to freeze binder: " + + proc.getPid() + " " + proc.processName); + mAm.mHandler.post(() -> { + synchronized (mAm) { + // Crash regardless of procstate in case the app has found another way + // to abuse oom_adj + if (proc.getThread() == null) { + return; + } + proc.killLocked("excessive binder traffic during cached", + ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE, + ApplicationExitInfo.SUBREASON_EXCESSIVE_CPU, + true); + } + }); + return; + } + + long timeout = proc.mOptRecord.getLastUsedTimeout() / mFreezerBinderDivisor; + // range is [-mFreezerBinderOffset, +mFreezerBinderOffset] + int offset = mRandom.nextInt(mFreezerBinderOffset * 2) - mFreezerBinderOffset; + timeout = Math.max(timeout + offset, mFreezerBinderThreshold); + Slog.d(TAG_AM, "Reschedule freeze for process " + proc.getPid() - + " " + proc.processName + " (" + reason + ")"); - unfreezeAppLSP(proc, reasonCode); - freezeAppAsyncLSP(proc); + + " " + proc.processName + " (" + reason + "), timeout=" + timeout); + Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, ATRACE_FREEZER_TRACK, + "Reschedule freeze " + proc.processName + ":" + proc.getPid() + + " timeout=" + timeout + ", reason=" + reason); + + unfreezeAppLSP(proc, UNFREEZE_REASON_BINDER_TXNS); + freezeAppAsyncLSP(proc, timeout); } /** @@ -2173,7 +2266,7 @@ public final class CachedAppOptimizer { // transactions that might be pending. try { if (freezeBinder(pid, true, FREEZE_BINDER_TIMEOUT_MS) != 0) { - rescheduleFreeze(proc, "outstanding txns", UNFREEZE_REASON_BINDER_TXNS); + handleBinderFreezerFailure(proc, "outstanding txns"); return; } } catch (RuntimeException e) { @@ -2234,7 +2327,7 @@ public final class CachedAppOptimizer { if ((freezeInfo & TXNS_PENDING_WHILE_FROZEN) != 0) { synchronized (mProcLock) { - rescheduleFreeze(proc, "new pending txns", UNFREEZE_REASON_BINDER_TXNS); + handleBinderFreezerFailure(proc, "new pending txns"); } return; } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 764bbe8bd191..f21ad2204d74 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1009,7 +1009,6 @@ public class OomAdjuster { mCacheOomRanker.reRankLruCachedAppsLSP(mProcessList.getLruProcessesLSP(), mProcessList.getLruProcessServiceStartLOSP()); } - assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP()); if (computeClients) { // There won't be cycles if we didn't compute clients above. // Cycle strategy: @@ -1034,7 +1033,7 @@ public class OomAdjuster { ProcessRecord app = activeProcesses.get(i); final ProcessStateRecord state = app.mState; if (!app.isKilledByAm() && app.getThread() != null && state.containsCycle()) { - if (computeOomAdjLSP(app, state.getCurRawAdj(), topApp, true, now, + if (computeOomAdjLSP(app, UNKNOWN_ADJ, topApp, true, now, true, true)) { retryCycles = true; } @@ -1044,6 +1043,8 @@ public class OomAdjuster { } mProcessesInCycle.clear(); + assignCachedAdjIfNecessary(mProcessList.getLruProcessesLOSP()); + mNumNonCachedProcs = 0; mNumCachedHiddenProcs = 0; diff --git a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java index ffe5a6e6b958..f5c5ea8ae55a 100644 --- a/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java +++ b/services/core/java/com/android/server/am/ProcessCachedOptimizerRecord.java @@ -127,6 +127,12 @@ final class ProcessCachedOptimizerRecord { @GuardedBy("mProcLock") private @UptimeMillisLong long mEarliestFreezableTimeMillis; + /** + * This is the most recently used timeout for freezing the app in millis + */ + @GuardedBy("mProcLock") + private long mLastUsedTimeout; + @GuardedBy("mProcLock") long getLastCompactTime() { return mLastCompactTime; @@ -282,6 +288,16 @@ final class ProcessCachedOptimizerRecord { } @GuardedBy("mProcLock") + long getLastUsedTimeout() { + return mLastUsedTimeout; + } + + @GuardedBy("mProcLock") + void setLastUsedTimeout(long lastUsedTimeout) { + mLastUsedTimeout = lastUsedTimeout; + } + + @GuardedBy("mProcLock") boolean isFreezeExempt() { return mFreezeExempt; } diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index ec85d577a8e7..0c7f11f98809 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -1199,11 +1199,16 @@ public class AudioDeviceInventory { AudioDeviceInfo device = Stream.of(connectedDevices) .filter(d -> d.getInternalType() == ada.getInternalType()) .filter(d -> (!AudioSystem.isBluetoothDevice(d.getInternalType()) - || (d.getAddress() == ada.getAddress()))) + || (d.getAddress().equals(ada.getAddress())))) .findFirst() .orElse(null); if (device == null) { + if (AudioService.DEBUG_DEVICES) { + Slog.i(TAG, "purgeRoles() removing device: " + ada.toString() + + ", for strategy: " + keyRole.first + + " and role: " + keyRole.second); + } asi.deviceRoleAction(keyRole.first, keyRole.second, Arrays.asList(ada)); itDev.remove(); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c177c4efb5ef..53ed38edffe4 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3666,25 +3666,29 @@ public class AudioService extends IAudioService.Stub * and aliases before mute change changed and after. */ private void muteAliasStreams(int streamAlias, boolean state) { - synchronized (VolumeStreamState.class) { - List<Integer> streamsToMute = new ArrayList<>(); - for (int stream = 0; stream < mStreamStates.length; stream++) { - VolumeStreamState vss = mStreamStates[stream]; - if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) { - if (!(mCameraSoundForced - && (vss.getStreamType() - == AudioSystem.STREAM_SYSTEM_ENFORCED))) { - boolean changed = vss.mute(state, /* apply= */ false, "muteAliasStreams"); - if (changed) { - streamsToMute.add(stream); + // Locking mSettingsLock to avoid inversion when calling doMute -> updateVolumeGroupIndex + synchronized (mSettingsLock) { + synchronized (VolumeStreamState.class) { + List<Integer> streamsToMute = new ArrayList<>(); + for (int stream = 0; stream < mStreamStates.length; stream++) { + VolumeStreamState vss = mStreamStates[stream]; + if (streamAlias == mStreamVolumeAlias[stream] && vss.isMutable()) { + if (!(mCameraSoundForced + && (vss.getStreamType() + == AudioSystem.STREAM_SYSTEM_ENFORCED))) { + boolean changed = vss.mute(state, /* apply= */ false, + "muteAliasStreams"); + if (changed) { + streamsToMute.add(stream); + } } } } + streamsToMute.forEach(streamToMute -> { + mStreamStates[streamToMute].doMute(); + broadcastMuteSetting(streamToMute, state); + }); } - streamsToMute.forEach(streamToMute -> { - mStreamStates[streamToMute].doMute(); - broadcastMuteSetting(streamToMute, state); - }); } } @@ -3699,18 +3703,22 @@ public class AudioService extends IAudioService.Stub // Called after a delay when volume down is pressed while muted private void onUnmuteStream(int stream, int flags) { boolean wasMuted; - synchronized (VolumeStreamState.class) { - final VolumeStreamState streamState = mStreamStates[stream]; - // if unmuting causes a change, it was muted - wasMuted = streamState.mute(false, "onUnmuteStream"); + // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute -> + // vss.updateVolumeGroupIndex + synchronized (mSettingsLock) { + synchronized (VolumeStreamState.class) { + final VolumeStreamState streamState = mStreamStates[stream]; + // if unmuting causes a change, it was muted + wasMuted = streamState.mute(false, "onUnmuteStream"); - final int device = getDeviceForStream(stream); - final int index = streamState.getIndex(device); - sendVolumeUpdate(stream, index, index, flags, device); - } - if (stream == AudioSystem.STREAM_MUSIC && wasMuted) { - synchronized (mHdmiClientLock) { - maybeSendSystemAudioStatusCommand(true); + final int device = getDeviceForStream(stream); + final int index = streamState.getIndex(device); + sendVolumeUpdate(stream, index, index, flags, device); + } + if (stream == AudioSystem.STREAM_MUSIC && wasMuted) { + synchronized (mHdmiClientLock) { + maybeSendSystemAudioStatusCommand(true); + } } } } @@ -7611,7 +7619,11 @@ public class AudioService extends IAudioService.Stub Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]", newDevice, AudioSystem.getOutputDeviceName(newDevice))); } - mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute"); + // Locking mSettingsLock to avoid inversion when calling vss.mute -> vss.doMute -> + // vss.updateVolumeGroupIndex + synchronized (mSettingsLock) { + mStreamStates[AudioSystem.STREAM_MUSIC].mute(false, "onAccessoryPlugMediaUnmute"); + } } } @@ -7646,9 +7658,14 @@ public class AudioService extends IAudioService.Stub continue; } } - for (int i = 0; i < sVolumeGroupStates.size(); i++) { - final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i); - vgs.applyAllVolumes(/* userSwitch= */ false); + + // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after + // VSS.class. Locking order needs to be preserved + synchronized (mSettingsLock) { + for (int i = 0; i < sVolumeGroupStates.size(); i++) { + final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i); + vgs.applyAllVolumes(/* userSwitch= */ false); + } } } @@ -7685,9 +7702,14 @@ public class AudioService extends IAudioService.Stub if (DEBUG_VOL) { Log.v(TAG, "restoreVolumeGroups"); } - for (int i = 0; i < sVolumeGroupStates.size(); i++) { - final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i); - vgs.applyAllVolumes(false/*userSwitch*/); + + // need mSettingsLock for vgs.applyAllVolumes -> vss.setIndex which grabs this lock after + // VSS.class. Locking order needs to be preserved + synchronized (mSettingsLock) { + for (int i = 0; i < sVolumeGroupStates.size(); i++) { + final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i); + vgs.applyAllVolumes(false/*userSwitch*/); + } } } @@ -7824,49 +7846,51 @@ public class AudioService extends IAudioService.Stub } public void adjustVolume(int direction, int flags) { - synchronized (AudioService.VolumeStreamState.class) { - int device = getDeviceForVolume(); - int previousIndex = getIndex(device); - if (isMuteAdjust(direction) && !isMutable()) { - // Non mutable volume group - if (DEBUG_VOL) { - Log.d(TAG, "invalid mute on unmutable volume group " + name()); - } - return; - } - switch (direction) { - case AudioManager.ADJUST_TOGGLE_MUTE: { - // Note: If muted by volume 0, unmute will restore volume 0. - mute(!mIsMuted); - break; + synchronized (mSettingsLock) { + synchronized (AudioService.VolumeStreamState.class) { + int device = getDeviceForVolume(); + int previousIndex = getIndex(device); + if (isMuteAdjust(direction) && !isMutable()) { + // Non mutable volume group + if (DEBUG_VOL) { + Log.d(TAG, "invalid mute on unmutable volume group " + name()); + } + return; } - case AudioManager.ADJUST_UNMUTE: - // Note: If muted by volume 0, unmute will restore volume 0. - mute(false); - break; - case AudioManager.ADJUST_MUTE: - // May be already muted by setvolume 0, prevent from setting same value - if (previousIndex != 0) { - // bypass persist - mute(true); + switch (direction) { + case AudioManager.ADJUST_TOGGLE_MUTE: { + // Note: If muted by volume 0, unmute will restore volume 0. + mute(!mIsMuted); + break; } - mIsMuted = true; - break; - case AudioManager.ADJUST_RAISE: - // As for stream, RAISE during mute will increment the index - setVolumeIndex(Math.min(previousIndex + 1, mIndexMax), device, flags); - break; - case AudioManager.ADJUST_LOWER: - // For stream, ADJUST_LOWER on a muted VSS is a no-op - // If we decide to unmute on ADJUST_LOWER, cannot fallback on - // adjustStreamVolume for group associated to legacy stream type - if (isMuted() && previousIndex != 0) { + case AudioManager.ADJUST_UNMUTE: + // Note: If muted by volume 0, unmute will restore volume 0. mute(false); - } else { - int newIndex = Math.max(previousIndex - 1, mIndexMin); - setVolumeIndex(newIndex, device, flags); - } - break; + break; + case AudioManager.ADJUST_MUTE: + // May be already muted by setvolume 0, prevent from setting same value + if (previousIndex != 0) { + // bypass persist + mute(true); + } + mIsMuted = true; + break; + case AudioManager.ADJUST_RAISE: + // As for stream, RAISE during mute will increment the index + setVolumeIndex(Math.min(previousIndex + 1, mIndexMax), device, flags); + break; + case AudioManager.ADJUST_LOWER: + // For stream, ADJUST_LOWER on a muted VSS is a no-op + // If we decide to unmute on ADJUST_LOWER, cannot fallback on + // adjustStreamVolume for group associated to legacy stream type + if (isMuted() && previousIndex != 0) { + mute(false); + } else { + int newIndex = Math.max(previousIndex - 1, mIndexMin); + setVolumeIndex(newIndex, device, flags); + } + break; + } } } } @@ -7878,11 +7902,13 @@ public class AudioService extends IAudioService.Stub } public void setVolumeIndex(int index, int flags) { - synchronized (AudioService.VolumeStreamState.class) { - if (mUseFixedVolume) { - return; + synchronized (mSettingsLock) { + synchronized (AudioService.VolumeStreamState.class) { + if (mUseFixedVolume) { + return; + } + setVolumeIndex(index, getDeviceForVolume(), flags); } - setVolumeIndex(index, getDeviceForVolume(), flags); } } @@ -8689,24 +8715,30 @@ public class AudioService extends IAudioService.Stub // If associated to volume group, update group cache private void updateVolumeGroupIndex(int device, boolean forceMuteState) { - synchronized (VolumeStreamState.class) { - if (mVolumeGroupState != null) { - int groupIndex = (getIndex(device) + 5) / 10; - if (DEBUG_VOL) { - Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType - + ", muted=" + mIsMuted + ", device=" + device + ", index=" - + getIndex(device) + ", group " + mVolumeGroupState.name() - + " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + groupIndex - + ", forceMuteState=" + forceMuteState); - } - mVolumeGroupState.updateVolumeIndex(groupIndex, device); - // Only propage mute of stream when applicable - if (isMutable()) { - // For call stream, align mute only when muted, not when index is set to 0 - mVolumeGroupState.mute( - forceMuteState ? mIsMuted : - (groupIndex == 0 && !isCallStream(mStreamType)) - || mIsMuted); + // need mSettingsLock when called from setIndex for vgs.mute -> vgs.applyAllVolumes -> + // vss.setIndex which grabs this lock after VSS.class. Locking order needs to be + // preserved + synchronized (mSettingsLock) { + synchronized (VolumeStreamState.class) { + if (mVolumeGroupState != null) { + int groupIndex = (getIndex(device) + 5) / 10; + if (DEBUG_VOL) { + Log.d(TAG, "updateVolumeGroupIndex for stream " + mStreamType + + ", muted=" + mIsMuted + ", device=" + device + ", index=" + + getIndex(device) + ", group " + mVolumeGroupState.name() + + " Muted=" + mVolumeGroupState.isMuted() + ", Index=" + + groupIndex + ", forceMuteState=" + forceMuteState); + } + mVolumeGroupState.updateVolumeIndex(groupIndex, device); + // Only propage mute of stream when applicable + if (isMutable()) { + // For call stream, align mute only when muted, not when index is set to + // 0 + mVolumeGroupState.mute( + forceMuteState ? mIsMuted : + (groupIndex == 0 && !isCallStream(mStreamType)) + || mIsMuted); + } } } } diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index c8a17e5eea5a..3560797ce2cf 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -218,8 +218,8 @@ public class BtHelper { if (AudioService.DEBUG_VOL) { AudioService.sVolumeLogger.enqueue(new EventLogger.StringEvent( "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp").printLog(TAG)); - return; } + return; } if (!mAvrcpAbsVolSupported) { AudioService.sVolumeLogger.enqueue(new EventLogger.StringEvent( diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 3e81f465a6c2..3132c5d713e3 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -3272,12 +3272,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { Slog.wtf(TAG, "KEYCODE_STYLUS_BUTTON_* should be handled in" + " interceptKeyBeforeQueueing"); return key_consumed; - case KeyEvent.KEYCODE_MACRO_1: - case KeyEvent.KEYCODE_MACRO_2: - case KeyEvent.KEYCODE_MACRO_3: - case KeyEvent.KEYCODE_MACRO_4: - Slog.wtf(TAG, "KEYCODE_MACRO_x should be handled in interceptKeyBeforeQueueing"); - return key_consumed; } if (isValidGlobalKey(keyCode) @@ -4427,7 +4421,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_MACRO_2: case KeyEvent.KEYCODE_MACRO_3: case KeyEvent.KEYCODE_MACRO_4: - // TODO(b/266098478): Add logic to handle KEYCODE_MACROx feature result &= ~ACTION_PASS_TO_USER; break; } diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 770f04a2db5e..60e2af5f283c 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -2512,6 +2512,35 @@ public class MockingOomAdjusterTests { assertEquals(FOREGROUND_APP_ADJ, app.mState.getSetAdj()); } + @SuppressWarnings("GuardedBy") + @Test + public void testUpdateOomAdj_DoAll_Side_Cycle() { + final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, + MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false)); + final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, + MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false)); + final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID, + MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false)); + long now = SystemClock.uptimeMillis(); + ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class)); + s.startRequested = true; + s.lastActivity = now; + s = bindService(app2, app3, null, 0, mock(IBinder.class)); + s.lastActivity = now; + s = bindService(app3, app2, null, 0, mock(IBinder.class)); + s.lastActivity = now; + + sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE); + sService.mOomAdjuster.mNumServiceProcs = 3; + updateOomAdj(app, app2, app3); + + assertEquals(SERVICE_ADJ, app.mState.getSetAdj()); + assertTrue(sFirstCachedAdj <= app2.mState.getSetAdj()); + assertTrue(sFirstCachedAdj <= app3.mState.getSetAdj()); + assertTrue(CACHED_APP_MAX_ADJ >= app2.mState.getSetAdj()); + assertTrue(CACHED_APP_MAX_ADJ >= app3.mState.getSetAdj()); + } + private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName, String packageName, boolean hasShownUi) { long now = SystemClock.uptimeMillis(); diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt index 122a6cbbb98f..537238b1d626 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.ime -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.Rotation @@ -104,7 +103,6 @@ open class CloseImeOnGoHomeTest(flicker: FlickerTest) : BaseTest(flicker) { @Presubmit @Test @PlatinumTest(focusArea = "ime") - @IwTest(focusArea = "ime") override fun cujCompleted() { super.cujCompleted() imeLayerBecomesInvisible() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt index 5aa43820e5cb..8d8075927076 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.ime -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher @@ -105,7 +104,6 @@ open class CloseImeToAppOnPressBackTest(flicker: FlickerTest) : BaseTest(flicker @Presubmit @Test @PlatinumTest(focusArea = "ime") - @IwTest(focusArea = "ime") override fun cujCompleted() { super.cujCompleted() imeLayerBecomesInvisible() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt index 6731089f8903..15262959332e 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt @@ -17,7 +17,6 @@ package com.android.server.wm.flicker.ime import android.platform.test.annotations.FlakyTest -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.Rotation @@ -73,7 +72,6 @@ open class CloseImeToHomeOnFinishActivityTest(flicker: FlickerTest) : BaseTest(f @Presubmit @Test @PlatinumTest(focusArea = "ime") - @IwTest(focusArea = "ime") override fun cujCompleted() { runAndIgnoreAssumptionViolation { entireScreenCovered() } runAndIgnoreAssumptionViolation { statusBarLayerIsVisibleAtStartAndEnd() } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt index c70e3cb773d4..827110dd4572 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.ime -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.Rotation @@ -54,7 +53,6 @@ open class ShowImeWhenFocusingOnInputFieldTest(flicker: FlickerTest) : BaseTest( @Presubmit @Test @PlatinumTest(focusArea = "ime") - @IwTest(focusArea = "ime") override fun cujCompleted() { super.cujCompleted() imeWindowBecomesVisible() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index 7fbcfec40121..ef75c6105b53 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.rotation -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.traces.component.ComponentNameMatcher @@ -131,7 +130,6 @@ open class ChangeAppRotationTest(flicker: FlickerTest) : RotationTransition(flic @Test @PlatinumTest(focusArea = "framework") - @IwTest(focusArea = "framework") override fun cujCompleted() { super.cujCompleted() focusChanges() diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt index 44ae14a8e4bb..f654bdd48e89 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt @@ -16,7 +16,6 @@ package com.android.server.wm.flicker.rotation -import android.platform.test.annotations.IwTest import android.platform.test.annotations.PlatinumTest import android.platform.test.annotations.Presubmit import android.tools.common.ScenarioBuilder @@ -215,7 +214,6 @@ open class SeamlessAppRotationTest(flicker: FlickerTest) : RotationTransition(fl @Test @PlatinumTest(focusArea = "framework") - @IwTest(focusArea = "framework") override fun cujCompleted() { appWindowFullScreen() appWindowSeamlessRotation() diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp index 0d2f2ef46cab..90e61c52da68 100644 --- a/tests/UiBench/Android.bp +++ b/tests/UiBench/Android.bp @@ -24,5 +24,6 @@ android_test { "androidx.recyclerview_recyclerview", "androidx.leanback_leanback", ], + certificate: "platform", test_suites: ["device-tests"], } diff --git a/tests/UiBench/AndroidManifest.xml b/tests/UiBench/AndroidManifest.xml index 4fc6ec71f29c..47211c5fbad1 100644 --- a/tests/UiBench/AndroidManifest.xml +++ b/tests/UiBench/AndroidManifest.xml @@ -18,6 +18,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.android.test.uibench"> + <uses-permission android:name="android.permission.INJECT_EVENTS" /> <application android:allowBackup="false" android:theme="@style/Theme.AppCompat.Light.DarkActionBar" |