Loading core/java/android/app/AppCompatTaskInfo.java +21 −2 Original line number Diff line number Diff line Loading @@ -114,6 +114,8 @@ public class AppCompatTaskInfo implements Parcelable { public static final int FLAG_OPT_OUT_EDGE_TO_EDGE = FLAG_BASE << 11; /** Top activity flag for whether activity is letterboxed for a safe region. */ public static final int FLAG_SAFE_REGION_LETTERBOXED = FLAG_BASE << 12; /** The related task is a leaf task. */ public static final int FLAG_IS_LEAF_TASK = FLAG_BASE << 13; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { Loading @@ -130,7 +132,8 @@ public class AppCompatTaskInfo implements Parcelable { FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE, FLAG_OPT_OUT_EDGE_TO_EDGE, FLAG_SAFE_REGION_LETTERBOXED FLAG_SAFE_REGION_LETTERBOXED, FLAG_IS_LEAF_TASK }) public @interface TopActivityFlag {} Loading @@ -145,7 +148,8 @@ public class AppCompatTaskInfo implements Parcelable { private static final int FLAGS_ORGANIZER_INTERESTED = FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP | FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON | FLAG_FULLSCREEN_OVERRIDE_SYSTEM | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE | FLAG_OPT_OUT_EDGE_TO_EDGE | FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE; | FLAG_OPT_OUT_EDGE_TO_EDGE | FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE | FLAG_IS_LEAF_TASK; @TopActivityFlag private static final int FLAGS_COMPAT_UI_INTERESTED = FLAGS_ORGANIZER_INTERESTED Loading Loading @@ -221,6 +225,20 @@ public class AppCompatTaskInfo implements Parcelable { return isTopActivityFlagEnabled(FLAG_ELIGIBLE_FOR_LETTERBOX_EDU); } /** * Set if the current Task is a leaf task. */ public void setIsLeafTask(boolean isLeafTask) { setTopActivityFlag(FLAG_IS_LEAF_TASK, isLeafTask); } /** * @return {@code true} if the task is a leaf task. */ public boolean isLeafTask() { return isTopActivityFlagEnabled(FLAG_IS_LEAF_TASK); } /** * Sets the top activity flag to be eligible for letterbox education. */ Loading Loading @@ -467,6 +485,7 @@ public class AppCompatTaskInfo implements Parcelable { @Override public String toString() { return "AppCompatTaskInfo { topActivityInSizeCompat=" + isTopActivityInSizeCompat() + " isLeafTask= " + isLeafTask() + " eligibleForLetterboxEducation= " + eligibleForLetterboxEducation() + " isLetterboxEducationEnabled= " + isLetterboxEducationEnabled() + " isLetterboxDoubleTapEnabled= " + isLetterboxDoubleTapEnabled() Loading libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/lifecycle/LetterboxLifecycleEvent.kt +22 −0 Original line number Diff line number Diff line Loading @@ -61,3 +61,25 @@ fun Change.asLetterboxLifecycleEventType() = when { isOpeningType(mode) -> OPEN else -> NONE } /** * Logic to skip a [Change] if not related to Letterboxing. We always skip changes about closing. * We skip the changes for tasks which are not leaves. The isLeaf information for changes with * activity target is always false but those changes cannot be skipped. * * No leaf task -> isChangeForALeafTask()==false isActivityChange()==false Skip * leaf task -> isChangeForALeafTask()==true isActivityChange()==false No Skip * Activity change -> isChangeForALeafTask()==false isActivityChange()==true No Skip */ fun Change.shouldSkipForLetterbox(): Boolean = isClosingType(mode) || !(isChangeForALeafTask() || isActivityChange()) /** * Returns [true] if the [Change] is about an [Activity] and so it contains a * [ActivityTransitionInfo]. */ fun Change.isActivityChange(): Boolean = activityTransitionInfo != null /** Returns [true] if the Task hosts Activities */ fun Change.isChangeForALeafTask(): Boolean = taskInfo?.appCompatTaskInfo?.isLeafTask() ?: false libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/lifecycle/SkipLetterboxLifecycleEventFactory.kt +4 −5 Original line number Diff line number Diff line Loading @@ -16,9 +16,8 @@ package com.android.wm.shell.compatui.letterbox.lifecycle import android.window.TransitionInfo import android.window.TransitionInfo.Change import com.android.wm.shell.dagger.WMSingleton import com.android.wm.shell.shared.TransitionUtil.isClosingType import javax.inject.Inject /** Loading @@ -28,11 +27,11 @@ import javax.inject.Inject @WMSingleton class SkipLetterboxLifecycleEventFactory @Inject constructor() : LetterboxLifecycleEventFactory { // We also ignore closing Changes. override fun canHandle(change: TransitionInfo.Change): Boolean = isClosingType(change.mode) // We also ignore closing Changes or changes related to Tasks without any activity. override fun canHandle(change: Change): Boolean = change.shouldSkipForLetterbox() // Although this LetterboxLifecycleEventFactory is able to handle the specific Change // it returns an empty LetterboxLifecycleEvent to basically ignore the Change. override fun createLifecycleEvent(change: TransitionInfo.Change): LetterboxLifecycleEvent? = override fun createLifecycleEvent(change: Change): LetterboxLifecycleEvent? = null } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/lifecycle/SkipLetterboxLifecycleEventFactoryTest.kt +43 −2 Original line number Diff line number Diff line Loading @@ -54,13 +54,54 @@ class SkipLetterboxLifecycleEventFactoryTest : ShellTestCase() { } @Test fun `Factory is skipped when Change is not closing one`() { fun `Factory is active when Change is for a Task which is NOT a leaf`() { runTestScenario { r -> testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) { inputChange { mode = TRANSIT_OPEN runningTaskInfo { ti -> ti.appCompatTaskInfo.setIsLeafTask(false) } } validateCanHandle { canHandle -> assert(canHandle) } validateCreateLifecycleEvent { event -> assert(event == null) } } } } @Test fun `Factory is skipped when Change is not closing for a Task which is NOT a leaf`() { runTestScenario { r -> testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) { inputChange { mode = TRANSIT_OPEN runningTaskInfo { ti -> ti.appCompatTaskInfo.setIsLeafTask(true) } } validateCanHandle { canHandle -> assert(!canHandle) } validateCreateLifecycleEvent { event -> assert(event != null) assert(event?.type == LetterboxLifecycleEventType.NONE) } } } } @Test fun `Factory is skipped when Change is not closing for an Activity Transition`() { runTestScenario { r -> testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) { inputChange { mode = TRANSIT_OPEN activityTransitionInfo { taskId = 10 this.taskId = 10 } } validateCanHandle { canHandle -> Loading services/core/java/com/android/server/wm/AppCompatUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -139,7 +139,7 @@ final class AppCompatUtils { @Nullable ActivityRecord top) { final AppCompatTaskInfo appCompatTaskInfo = info.appCompatTaskInfo; clearAppCompatTaskInfo(appCompatTaskInfo); appCompatTaskInfo.setIsLeafTask(task.isLeafTask()); if (top == null) { return; } Loading Loading
core/java/android/app/AppCompatTaskInfo.java +21 −2 Original line number Diff line number Diff line Loading @@ -114,6 +114,8 @@ public class AppCompatTaskInfo implements Parcelable { public static final int FLAG_OPT_OUT_EDGE_TO_EDGE = FLAG_BASE << 11; /** Top activity flag for whether activity is letterboxed for a safe region. */ public static final int FLAG_SAFE_REGION_LETTERBOXED = FLAG_BASE << 12; /** The related task is a leaf task. */ public static final int FLAG_IS_LEAF_TASK = FLAG_BASE << 13; @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = { Loading @@ -130,7 +132,8 @@ public class AppCompatTaskInfo implements Parcelable { FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE, FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE, FLAG_OPT_OUT_EDGE_TO_EDGE, FLAG_SAFE_REGION_LETTERBOXED FLAG_SAFE_REGION_LETTERBOXED, FLAG_IS_LEAF_TASK }) public @interface TopActivityFlag {} Loading @@ -145,7 +148,8 @@ public class AppCompatTaskInfo implements Parcelable { private static final int FLAGS_ORGANIZER_INTERESTED = FLAG_IS_FROM_LETTERBOX_DOUBLE_TAP | FLAG_ELIGIBLE_FOR_USER_ASPECT_RATIO_BUTTON | FLAG_FULLSCREEN_OVERRIDE_SYSTEM | FLAG_FULLSCREEN_OVERRIDE_USER | FLAG_HAS_MIN_ASPECT_RATIO_OVERRIDE | FLAG_OPT_OUT_EDGE_TO_EDGE | FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE; | FLAG_OPT_OUT_EDGE_TO_EDGE | FLAG_ENABLE_RESTART_MENU_FOR_DISPLAY_MOVE | FLAG_IS_LEAF_TASK; @TopActivityFlag private static final int FLAGS_COMPAT_UI_INTERESTED = FLAGS_ORGANIZER_INTERESTED Loading Loading @@ -221,6 +225,20 @@ public class AppCompatTaskInfo implements Parcelable { return isTopActivityFlagEnabled(FLAG_ELIGIBLE_FOR_LETTERBOX_EDU); } /** * Set if the current Task is a leaf task. */ public void setIsLeafTask(boolean isLeafTask) { setTopActivityFlag(FLAG_IS_LEAF_TASK, isLeafTask); } /** * @return {@code true} if the task is a leaf task. */ public boolean isLeafTask() { return isTopActivityFlagEnabled(FLAG_IS_LEAF_TASK); } /** * Sets the top activity flag to be eligible for letterbox education. */ Loading Loading @@ -467,6 +485,7 @@ public class AppCompatTaskInfo implements Parcelable { @Override public String toString() { return "AppCompatTaskInfo { topActivityInSizeCompat=" + isTopActivityInSizeCompat() + " isLeafTask= " + isLeafTask() + " eligibleForLetterboxEducation= " + eligibleForLetterboxEducation() + " isLetterboxEducationEnabled= " + isLetterboxEducationEnabled() + " isLetterboxDoubleTapEnabled= " + isLetterboxDoubleTapEnabled() Loading
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/lifecycle/LetterboxLifecycleEvent.kt +22 −0 Original line number Diff line number Diff line Loading @@ -61,3 +61,25 @@ fun Change.asLetterboxLifecycleEventType() = when { isOpeningType(mode) -> OPEN else -> NONE } /** * Logic to skip a [Change] if not related to Letterboxing. We always skip changes about closing. * We skip the changes for tasks which are not leaves. The isLeaf information for changes with * activity target is always false but those changes cannot be skipped. * * No leaf task -> isChangeForALeafTask()==false isActivityChange()==false Skip * leaf task -> isChangeForALeafTask()==true isActivityChange()==false No Skip * Activity change -> isChangeForALeafTask()==false isActivityChange()==true No Skip */ fun Change.shouldSkipForLetterbox(): Boolean = isClosingType(mode) || !(isChangeForALeafTask() || isActivityChange()) /** * Returns [true] if the [Change] is about an [Activity] and so it contains a * [ActivityTransitionInfo]. */ fun Change.isActivityChange(): Boolean = activityTransitionInfo != null /** Returns [true] if the Task hosts Activities */ fun Change.isChangeForALeafTask(): Boolean = taskInfo?.appCompatTaskInfo?.isLeafTask() ?: false
libs/WindowManager/Shell/src/com/android/wm/shell/compatui/letterbox/lifecycle/SkipLetterboxLifecycleEventFactory.kt +4 −5 Original line number Diff line number Diff line Loading @@ -16,9 +16,8 @@ package com.android.wm.shell.compatui.letterbox.lifecycle import android.window.TransitionInfo import android.window.TransitionInfo.Change import com.android.wm.shell.dagger.WMSingleton import com.android.wm.shell.shared.TransitionUtil.isClosingType import javax.inject.Inject /** Loading @@ -28,11 +27,11 @@ import javax.inject.Inject @WMSingleton class SkipLetterboxLifecycleEventFactory @Inject constructor() : LetterboxLifecycleEventFactory { // We also ignore closing Changes. override fun canHandle(change: TransitionInfo.Change): Boolean = isClosingType(change.mode) // We also ignore closing Changes or changes related to Tasks without any activity. override fun canHandle(change: Change): Boolean = change.shouldSkipForLetterbox() // Although this LetterboxLifecycleEventFactory is able to handle the specific Change // it returns an empty LetterboxLifecycleEvent to basically ignore the Change. override fun createLifecycleEvent(change: TransitionInfo.Change): LetterboxLifecycleEvent? = override fun createLifecycleEvent(change: Change): LetterboxLifecycleEvent? = null }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/letterbox/lifecycle/SkipLetterboxLifecycleEventFactoryTest.kt +43 −2 Original line number Diff line number Diff line Loading @@ -54,13 +54,54 @@ class SkipLetterboxLifecycleEventFactoryTest : ShellTestCase() { } @Test fun `Factory is skipped when Change is not closing one`() { fun `Factory is active when Change is for a Task which is NOT a leaf`() { runTestScenario { r -> testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) { inputChange { mode = TRANSIT_OPEN runningTaskInfo { ti -> ti.appCompatTaskInfo.setIsLeafTask(false) } } validateCanHandle { canHandle -> assert(canHandle) } validateCreateLifecycleEvent { event -> assert(event == null) } } } } @Test fun `Factory is skipped when Change is not closing for a Task which is NOT a leaf`() { runTestScenario { r -> testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) { inputChange { mode = TRANSIT_OPEN runningTaskInfo { ti -> ti.appCompatTaskInfo.setIsLeafTask(true) } } validateCanHandle { canHandle -> assert(!canHandle) } validateCreateLifecycleEvent { event -> assert(event != null) assert(event?.type == LetterboxLifecycleEventType.NONE) } } } } @Test fun `Factory is skipped when Change is not closing for an Activity Transition`() { runTestScenario { r -> testLetterboxLifecycleEventFactory(r.getLetterboxLifecycleEventFactory()) { inputChange { mode = TRANSIT_OPEN activityTransitionInfo { taskId = 10 this.taskId = 10 } } validateCanHandle { canHandle -> Loading
services/core/java/com/android/server/wm/AppCompatUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -139,7 +139,7 @@ final class AppCompatUtils { @Nullable ActivityRecord top) { final AppCompatTaskInfo appCompatTaskInfo = info.appCompatTaskInfo; clearAppCompatTaskInfo(appCompatTaskInfo); appCompatTaskInfo.setIsLeafTask(task.isLeafTask()); if (top == null) { return; } Loading