diff options
4 files changed, 144 insertions, 1 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 93eed370004b..db699d7bfb06 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -625,6 +625,12 @@ public interface WindowManager extends ViewManager { int TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH = (1 << 14); // 0x4000 /** + * Transition flag: Indicates that aod is showing hidden by entering doze + * @hide + */ + int TRANSIT_FLAG_AOD_APPEARING = (1 << 15); // 0x8000 + + /** * @hide */ @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = { @@ -643,6 +649,7 @@ public interface WindowManager extends ViewManager { TRANSIT_FLAG_KEYGUARD_OCCLUDING, TRANSIT_FLAG_KEYGUARD_UNOCCLUDING, TRANSIT_FLAG_PHYSICAL_DISPLAY_SWITCH, + TRANSIT_FLAG_AOD_APPEARING, }) @Retention(RetentionPolicy.SOURCE) @interface TransitionFlags {} @@ -659,7 +666,8 @@ public interface WindowManager extends ViewManager { (TRANSIT_FLAG_KEYGUARD_GOING_AWAY | TRANSIT_FLAG_KEYGUARD_APPEARING | TRANSIT_FLAG_KEYGUARD_OCCLUDING - | TRANSIT_FLAG_KEYGUARD_UNOCCLUDING); + | TRANSIT_FLAG_KEYGUARD_UNOCCLUDING + | TRANSIT_FLAG_AOD_APPEARING); /** * Remove content mode: Indicates remove content mode is currently not defined. diff --git a/services/tests/wmtests/src/com/android/server/TransitionSubject.java b/services/tests/wmtests/src/com/android/server/TransitionSubject.java new file mode 100644 index 000000000000..07026b98f226 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/TransitionSubject.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + +import android.annotation.Nullable; + +import com.google.common.truth.FailureMetadata; +import com.google.common.truth.IterableSubject; +import com.google.common.truth.Subject; +import com.google.common.truth.Truth; + +import java.util.ArrayList; +import java.util.List; + +public class TransitionSubject extends Subject { + + @Nullable + private final Transition actual; + + /** + * Internal constructor. + * + * @see TransitionSubject#assertThat(Transition) + */ + private TransitionSubject(FailureMetadata metadata, @Nullable Transition actual) { + super(metadata, actual); + this.actual = actual; + } + + /** + * In a fluent assertion chain, the argument to the "custom" overload of {@link + * StandardSubjectBuilder#about(CustomSubjectBuilder.Factory) about}, the method that specifies + * what kind of {@link Subject} to create. + */ + public static Factory<TransitionSubject, Transition> transitions() { + return TransitionSubject::new; + } + + /** + * Typical entry point for making assertions about Transitions. + * + * @see @Truth#assertThat(Object) + */ + public static TransitionSubject assertThat(Transition transition) { + return Truth.assertAbout(transitions()).that(transition); + } + + /** + * Converts to a {@link IterableSubject} containing {@link Transition#getFlags()} separated into + * a list of individual flags for assertions such as {@code flags().contains(TRANSIT_FLAG_XYZ)}. + * + * <p>If the subject is null, this will fail instead of returning a null subject. + */ + public IterableSubject flags() { + isNotNull(); + + final List<Integer> sortedFlags = new ArrayList<>(); + for (int i = 0; i < 32; i++) { + if ((actual.getFlags() & (1 << i)) != 0) { + sortedFlags.add((1 << i)); + } + } + return com.google.common.truth.Truth.assertThat(sortedFlags); + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 181853066f7b..f7007ddda9ec 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -63,6 +63,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static android.view.WindowManager.TRANSIT_FLAG_AOD_APPEARING; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING; import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; @@ -80,6 +83,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_TOKEN_TRANSFO import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; +import static com.android.server.wm.TransitionSubject.assertThat; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE; import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT; @@ -146,6 +150,7 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.server.LocalServices; import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.utils.WmDisplayCutout; +import com.android.window.flags.Flags; import org.junit.Test; import org.junit.runner.RunWith; @@ -2619,6 +2624,7 @@ public class DisplayContentTests extends WindowTestsBase { final KeyguardController keyguard = mAtm.mKeyguardController; final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build(); final int displayId = mDisplayContent.getDisplayId(); + final TestTransitionPlayer transitions = registerTestTransitionPlayer(); final BooleanSupplier keyguardShowing = () -> keyguard.isKeyguardShowing(displayId); final BooleanSupplier keyguardGoingAway = () -> keyguard.isKeyguardGoingAway(displayId); @@ -2628,21 +2634,40 @@ public class DisplayContentTests extends WindowTestsBase { keyguard.setKeyguardShown(displayId, true /* keyguard */, true /* aod */); assertFalse(keyguardGoingAway.getAsBoolean()); assertFalse(appVisible.getAsBoolean()); + transitions.flush(); // Start unlocking from AOD. keyguard.keyguardGoingAway(displayId, 0x0 /* flags */); assertTrue(keyguardGoingAway.getAsBoolean()); assertTrue(appVisible.getAsBoolean()); + if (Flags.ensureKeyguardDoesTransitionStarting()) { + assertThat(transitions.mLastTransit).isNull(); + } else { + assertThat(transitions.mLastTransit).flags() + .containsExactly(TRANSIT_FLAG_KEYGUARD_GOING_AWAY); + } + transitions.flush(); + // Clear AOD. This does *not* clear the going-away status. keyguard.setKeyguardShown(displayId, true /* keyguard */, false /* aod */); assertTrue(keyguardGoingAway.getAsBoolean()); assertTrue(appVisible.getAsBoolean()); + if (Flags.aodTransition()) { + assertThat(transitions.mLastTransit).flags() + .containsExactly(TRANSIT_FLAG_AOD_APPEARING); + } else { + assertThat(transitions.mLastTransit).isNull(); + } + transitions.flush(); + // Finish unlock keyguard.setKeyguardShown(displayId, false /* keyguard */, false /* aod */); assertFalse(keyguardGoingAway.getAsBoolean()); assertTrue(appVisible.getAsBoolean()); + + assertThat(transitions.mLastTransit).isNull(); } @Test @@ -2652,6 +2677,7 @@ public class DisplayContentTests extends WindowTestsBase { final KeyguardController keyguard = mAtm.mKeyguardController; final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build(); final int displayId = mDisplayContent.getDisplayId(); + final TestTransitionPlayer transitions = registerTestTransitionPlayer(); final BooleanSupplier keyguardShowing = () -> keyguard.isKeyguardShowing(displayId); final BooleanSupplier keyguardGoingAway = () -> keyguard.isKeyguardGoingAway(displayId); @@ -2661,22 +2687,44 @@ public class DisplayContentTests extends WindowTestsBase { keyguard.setKeyguardShown(displayId, true /* keyguard */, true /* aod */); assertFalse(keyguardGoingAway.getAsBoolean()); assertFalse(appVisible.getAsBoolean()); + transitions.flush(); // Start unlocking from AOD. keyguard.keyguardGoingAway(displayId, 0x0 /* flags */); assertTrue(keyguardGoingAway.getAsBoolean()); assertTrue(appVisible.getAsBoolean()); + if (!Flags.ensureKeyguardDoesTransitionStarting()) { + assertThat(transitions.mLastTransit).flags() + .containsExactly(TRANSIT_FLAG_KEYGUARD_GOING_AWAY); + } + transitions.flush(); + // Clear AOD. This does *not* clear the going-away status. keyguard.setKeyguardShown(displayId, true /* keyguard */, false /* aod */); assertTrue(keyguardGoingAway.getAsBoolean()); assertTrue(appVisible.getAsBoolean()); + if (Flags.aodTransition()) { + assertThat(transitions.mLastTransit).flags() + .containsExactly(TRANSIT_FLAG_AOD_APPEARING); + } else { + assertThat(transitions.mLastTransit).isNull(); + } + transitions.flush(); + // Same API call a second time cancels the unlock, because AOD isn't changing. keyguard.setKeyguardShown(displayId, true /* keyguard */, false /* aod */); assertTrue(keyguardShowing.getAsBoolean()); assertFalse(keyguardGoingAway.getAsBoolean()); assertFalse(appVisible.getAsBoolean()); + + if (Flags.ensureKeyguardDoesTransitionStarting()) { + assertThat(transitions.mLastTransit).isNull(); + } else { + assertThat(transitions.mLastTransit).flags() + .containsExactly(TRANSIT_FLAG_KEYGUARD_APPEARING); + } } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index c6416850c464..b7f23c5afe4f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -2140,6 +2140,14 @@ public class WindowTestsBase extends SystemServiceTestsBase { mLastRequest = null; } + void flush() { + if (mLastTransit != null) { + start(); + finish(); + clear(); + } + } + @Override public void onTransitionReady(IBinder transitToken, TransitionInfo transitionInfo, SurfaceControl.Transaction transaction, SurfaceControl.Transaction finishT) |