diff options
Diffstat (limited to 'libs')
17 files changed, 330 insertions, 124 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index e8014af463bd..adc0c9c4322a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -479,7 +479,7 @@ public class BubbleExpandedView extends LinearLayout { void applyThemeAttrs() { final TypedArray ta = mContext.obtainStyledAttributes(new int[]{ android.R.attr.dialogCornerRadius, - android.R.attr.colorBackgroundFloating}); + com.android.internal.R.attr.materialColorSurfaceBright}); boolean supportsRoundedCorners = ScreenDecorationsUtils.supportsRoundedCornersOnWindows( mContext.getResources()); mCornerRadius = supportsRoundedCorners ? ta.getDimensionPixelSize(0, 0) : 0; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index e7dede757578..2832c553c20c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -412,7 +412,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange /** Releases and re-inflates {@link DividerView} on the root surface. */ public void update(SurfaceControl.Transaction t) { - if (!mInitialized) return; + if (!mInitialized) { + init(); + return; + } mSplitWindowManager.release(t); mImePositionProcessor.reset(); mSplitWindowManager.init(this, mInsetsState); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java index 838e37a905db..2bbd870f024d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java @@ -47,6 +47,8 @@ import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; +import dagger.Lazy; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashSet; @@ -55,8 +57,6 @@ import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; -import dagger.Lazy; - /** * Controller to show/update compat UI components on Tasks based on whether the foreground * activities are in compatibility mode. @@ -284,13 +284,18 @@ public class CompatUIController implements OnDisplaysChangedListener, ShellTaskOrganizer.TaskListener taskListener) { CompatUIWindowManager layout = mActiveCompatLayouts.get(taskInfo.taskId); if (layout != null) { - // UI already exists, update the UI layout. - if (!layout.updateCompatInfo(taskInfo, taskListener, - showOnDisplay(layout.getDisplayId()))) { - // The layout is no longer eligible to be shown, remove from active layouts. + if (layout.needsToBeRecreated(taskInfo, taskListener)) { mActiveCompatLayouts.remove(taskInfo.taskId); + layout.release(); + } else { + // UI already exists, update the UI layout. + if (!layout.updateCompatInfo(taskInfo, taskListener, + showOnDisplay(layout.getDisplayId()))) { + // The layout is no longer eligible to be shown, remove from active layouts. + mActiveCompatLayouts.remove(taskInfo.taskId); + } + return; } - return; } // Create a new UI layout. @@ -433,13 +438,18 @@ public class CompatUIController implements OnDisplaysChangedListener, private void createOrUpdateReachabilityEduLayout(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { if (mActiveReachabilityEduLayout != null) { - // UI already exists, update the UI layout. - if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener, - showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) { - // The layout is no longer eligible to be shown, remove from active layouts. + if (mActiveReachabilityEduLayout.needsToBeRecreated(taskInfo, taskListener)) { + mActiveReachabilityEduLayout.release(); mActiveReachabilityEduLayout = null; + } else { + // UI already exists, update the UI layout. + if (!mActiveReachabilityEduLayout.updateCompatInfo(taskInfo, taskListener, + showOnDisplay(mActiveReachabilityEduLayout.getDisplayId()))) { + // The layout is no longer eligible to be shown, remove from active layouts. + mActiveReachabilityEduLayout = null; + } + return; } - return; } // Create a new UI layout. final Context context = getOrCreateDisplayContext(taskInfo.displayId); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java index 659229228a57..d4778fa7a58a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManager.java @@ -22,7 +22,6 @@ import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_APPLIED; import static android.app.TaskInfo.CAMERA_COMPAT_CONTROL_TREATMENT_SUGGESTED; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; -import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskInfo; import android.app.TaskInfo.CameraCompatControlState; @@ -53,9 +52,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { private final Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartButtonClicked; - @NonNull - private TaskInfo mTaskInfo; - // Remember the last reported states in case visibility changes due to keyguard or IME updates. @VisibleForTesting boolean mHasSizeCompat; @@ -77,7 +73,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { CompatUIHintsState compatUIHintsState, CompatUIConfiguration compatUIConfiguration, Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> onRestartButtonClicked) { super(context, taskInfo, syncQueue, taskListener, displayLayout); - mTaskInfo = taskInfo; mCallback = callback; mHasSizeCompat = taskInfo.topActivityInSizeCompat; mCameraCompatControlState = taskInfo.cameraCompatControlState; @@ -129,7 +124,6 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { @Override public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { - mTaskInfo = taskInfo; final boolean prevHasSizeCompat = mHasSizeCompat; final int prevCameraCompatControlState = mCameraCompatControlState; mHasSizeCompat = taskInfo.topActivityInSizeCompat; @@ -149,7 +143,7 @@ class CompatUIWindowManager extends CompatUIWindowManagerAbstract { /** Called when the restart button is clicked. */ void onRestartButtonClicked() { - mOnRestartButtonClicked.accept(Pair.create(mTaskInfo, getTaskListener())); + mOnRestartButtonClicked.accept(Pair.create(getLastTaskInfo(), getTaskListener())); } /** Called when the camera treatment button is clicked. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java index 9c4e79cd631b..180498c50c78 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java @@ -26,6 +26,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskInfo; import android.content.Context; @@ -65,6 +66,9 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana private DisplayLayout mDisplayLayout; private final Rect mStableBounds; + @NonNull + private TaskInfo mTaskInfo; + /** * Utility class for adding and releasing a View hierarchy for this {@link * WindowlessWindowManager} to {@code mLeash}. @@ -83,6 +87,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout) { super(taskInfo.configuration, null /* rootSurface */, null /* hostInputToken */); + mTaskInfo = taskInfo; mContext = context; mSyncQueue = syncQueue; mTaskConfig = taskInfo.configuration; @@ -95,6 +100,17 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana } /** + * @return {@code true} if the instance of the specific {@link CompatUIWindowManagerAbstract} + * for the current task id needs to be recreated loading the related resources. This happens + * if the user switches between Light/Dark mode, if the device is docked/undocked or if the + * user switches between multi-window mode to fullscreen where the + * {@link ShellTaskOrganizer.TaskListener} implementation is different. + */ + boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { + return hasUiModeChanged(mTaskInfo, taskInfo) || hasTaskListenerChanged(taskListener); + } + + /** * Returns the z-order of this window which will be passed to the {@link SurfaceControl} once * {@link #attachToParentSurface} is called. * @@ -195,6 +211,7 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana @VisibleForTesting(visibility = PROTECTED) public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { + mTaskInfo = taskInfo; final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; mTaskConfig = taskInfo.configuration; @@ -315,6 +332,11 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana updateSurfacePosition(); } + @Nullable + protected TaskInfo getLastTaskInfo() { + return mTaskInfo; + } + /** * Called following a change in the task bounds, display layout stable bounds, or the layout * direction. @@ -402,4 +424,12 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana protected final String getTag() { return getClass().getSimpleName(); } + + protected boolean hasTaskListenerChanged(ShellTaskOrganizer.TaskListener newTaskListener) { + return !mTaskListener.equals(newTaskListener); + } + + protected static boolean hasUiModeChanged(TaskInfo currentTaskInfo, TaskInfo newTaskInfo) { + return currentTaskInfo.configuration.uiMode != newTaskInfo.configuration.uiMode; + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java index 959c50d5c640..9a67258ded2e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/LetterboxEduWindowManager.java @@ -19,7 +19,6 @@ package com.android.wm.shell.compatui; import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; -import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskInfo; import android.content.Context; @@ -69,9 +68,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { @VisibleForTesting LetterboxEduDialogLayout mLayout; - @NonNull - private TaskInfo mTaskInfo; - /** * The vertical margin between the dialog container and the task stable bounds (excluding * insets). @@ -99,7 +95,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { DialogAnimationController<LetterboxEduDialogLayout> animationController, DockStateReader dockStateReader, CompatUIConfiguration compatUIConfiguration) { super(context, taskInfo, syncQueue, taskListener, displayLayout); - mTaskInfo = taskInfo; mTransitions = transitions; mOnDismissCallback = onDismissCallback; mAnimationController = animationController; @@ -197,7 +192,7 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { mLayout.setDismissOnClickListener(null); mAnimationController.startExitAnimation(mLayout, () -> { release(); - mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener())); + mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener())); }); } @@ -210,7 +205,6 @@ class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract { @Override public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { - mTaskInfo = taskInfo; mEligibleForLetterboxEducation = taskInfo.topActivityEligibleForLetterboxEducation; return super.updateCompatInfo(taskInfo, taskListener, canShow); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java index a18ab9154e01..95bb1fe1c986 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/ReachabilityEduWindowManager.java @@ -20,7 +20,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; -import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskInfo; import android.content.Context; @@ -52,9 +51,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { private final ShellExecutor mMainExecutor; - @NonNull - private TaskInfo mTaskInfo; - private boolean mIsActivityLetterboxed; private int mLetterboxVerticalPosition; @@ -86,7 +82,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { ShellTaskOrganizer.TaskListener taskListener, DisplayLayout displayLayout, CompatUIConfiguration compatUIConfiguration, ShellExecutor mainExecutor) { super(context, taskInfo, syncQueue, taskListener, displayLayout); - mTaskInfo = taskInfo; mIsActivityLetterboxed = taskInfo.isLetterboxDoubleTapEnabled; mLetterboxVerticalPosition = taskInfo.topActivityLetterboxVerticalPosition; mLetterboxHorizontalPosition = taskInfo.topActivityLetterboxHorizontalPosition; @@ -136,7 +131,6 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { @Override public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, boolean canShow) { - mTaskInfo = taskInfo; final boolean prevIsActivityLetterboxed = mIsActivityLetterboxed; final int prevLetterboxVerticalPosition = mLetterboxVerticalPosition; final int prevLetterboxHorizontalPosition = mLetterboxHorizontalPosition; @@ -222,14 +216,14 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { if (mLayout == null) { return; } - + final TaskInfo lastTaskInfo = getLastTaskInfo(); final boolean eligibleForDisplayHorizontalEducation = mForceUpdate - || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(mTaskInfo) + || !mCompatUIConfiguration.hasSeenHorizontalReachabilityEducation(lastTaskInfo) || (mHasUserDoubleTapped && (mLetterboxHorizontalPosition == REACHABILITY_LEFT_OR_UP_POSITION || mLetterboxHorizontalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION)); final boolean eligibleForDisplayVerticalEducation = mForceUpdate - || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(mTaskInfo) + || !mCompatUIConfiguration.hasSeenVerticalReachabilityEducation(lastTaskInfo) || (mHasUserDoubleTapped && (mLetterboxVerticalPosition == REACHABILITY_LEFT_OR_UP_POSITION || mLetterboxVerticalPosition == REACHABILITY_RIGHT_OR_BOTTOM_POSITION)); @@ -241,7 +235,7 @@ class ReachabilityEduWindowManager extends CompatUIWindowManagerAbstract { mLayout.handleVisibility(eligibleForDisplayHorizontalEducation, eligibleForDisplayVerticalEducation, mLetterboxVerticalPosition, mLetterboxHorizontalPosition, availableWidth, - availableHeight, mCompatUIConfiguration, mTaskInfo); + availableHeight, mCompatUIConfiguration, lastTaskInfo); if (!mHasLetterboxSizeChanged) { updateHideTime(); mMainExecutor.executeDelayed(this::hideReachability, DISAPPEAR_DELAY_MS); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java index 51e5141a28af..a770da28fbd1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java @@ -19,7 +19,6 @@ package com.android.wm.shell.compatui; import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING; import static android.window.TaskConstants.TASK_CHILD_LAYER_COMPAT_UI; -import android.annotation.NonNull; import android.annotation.Nullable; import android.app.TaskInfo; import android.content.Context; @@ -67,9 +66,6 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { */ private final int mDialogVerticalMargin; - @NonNull - private TaskInfo mTaskInfo; - @Nullable @VisibleForTesting RestartDialogLayout mLayout; @@ -95,7 +91,6 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { DialogAnimationController<RestartDialogLayout> animationController, CompatUIConfiguration compatUIConfiguration) { super(context, taskInfo, syncQueue, taskListener, displayLayout); - mTaskInfo = taskInfo; mTransitions = transitions; mOnDismissCallback = onDismissCallback; mOnRestartCallback = onRestartCallback; @@ -125,7 +120,7 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { protected boolean eligibleToShowLayout() { // We don't show this dialog if the user has explicitly selected so clicking on a checkbox. return mRequestRestartDialog && !isTaskbarEduShowing() && (mLayout != null - || mCompatUIConfiguration.shouldShowRestartDialogAgain(mTaskInfo)); + || mCompatUIConfiguration.shouldShowRestartDialogAgain(getLastTaskInfo())); } @Override @@ -143,18 +138,6 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { mRequestRestartDialog = enabled; } - @Override - public boolean updateCompatInfo(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener, - boolean canShow) { - mTaskInfo = taskInfo; - return super.updateCompatInfo(taskInfo, taskListener, canShow); - } - - boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) { - return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode - || !getTaskListener().equals(taskListener); - } - private void updateDialogMargins() { if (mLayout == null) { return; @@ -191,6 +174,7 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { // Dialog has already been released. return; } + final TaskInfo lastTaskInfo = getLastTaskInfo(); mLayout.setDismissOnClickListener(this::onDismiss); mLayout.setRestartOnClickListener(dontShowAgain -> { if (mLayout != null) { @@ -200,9 +184,9 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { }); } if (dontShowAgain) { - mCompatUIConfiguration.setDontShowRestartDialogAgain(mTaskInfo); + mCompatUIConfiguration.setDontShowRestartDialogAgain(lastTaskInfo); } - mOnRestartCallback.accept(Pair.create(mTaskInfo, getTaskListener())); + mOnRestartCallback.accept(Pair.create(lastTaskInfo, getTaskListener())); }); // Focus on the dialog title for accessibility. mLayout.getDialogTitle().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); @@ -216,7 +200,7 @@ class RestartDialogWindowManager extends CompatUIWindowManagerAbstract { mLayout.setDismissOnClickListener(null); mAnimationController.startExitAnimation(mLayout, () -> { release(); - mOnDismissCallback.accept(Pair.create(mTaskInfo, getTaskListener())); + mOnDismissCallback.accept(Pair.create(getLastTaskInfo(), getTaskListener())); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index b3109388da2c..9de9855720bc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -39,7 +39,6 @@ import android.window.TransitionRequestInfo import android.window.WindowContainerToken import android.window.WindowContainerTransaction import androidx.annotation.BinderThread -import com.android.internal.protolog.common.ProtoLog import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.common.DisplayController @@ -56,6 +55,7 @@ import com.android.wm.shell.sysui.ShellController import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.sysui.ShellSharedConstants import com.android.wm.shell.transition.Transitions +import com.android.wm.shell.util.KtProtoLog import java.util.concurrent.Executor import java.util.function.Consumer @@ -91,7 +91,7 @@ class DesktopTasksController( } private fun onInit() { - ProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController") + KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "Initialize DesktopTasksController") shellController.addExternalInterface( ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE, { createExternalInterface() }, @@ -102,7 +102,7 @@ class DesktopTasksController( /** Show all tasks, that are part of the desktop, on top of launcher */ fun showDesktopApps(displayId: Int) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps") + KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "showDesktopApps") val wct = WindowContainerTransaction() // TODO(b/278084491): pass in display id bringDesktopAppsToFront(displayId, wct) @@ -130,7 +130,7 @@ class DesktopTasksController( /** Move a task to desktop */ fun moveToDesktop(task: RunningTaskInfo) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDesktop: %d", task.taskId) + KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDesktop: %d", task.taskId) val wct = WindowContainerTransaction() // Bring other apps to front first @@ -190,7 +190,7 @@ class DesktopTasksController( /** Move a task to fullscreen */ fun moveToFullscreen(task: RunningTaskInfo) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToFullscreen: %d", task.taskId) + KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToFullscreen: %d", task.taskId) val wct = WindowContainerTransaction() addMoveToFullscreenChanges(wct, task.token) @@ -255,10 +255,10 @@ class DesktopTasksController( fun moveToNextDisplay(taskId: Int) { val task = shellTaskOrganizer.getRunningTaskInfo(taskId) if (task == null) { - ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId) + KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId) return } - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d", + KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d", taskId, task.displayId) val displayIds = rootTaskDisplayAreaOrganizer.displayIds.sorted() @@ -269,7 +269,7 @@ class DesktopTasksController( newDisplayId = displayIds.firstOrNull { displayId -> displayId < task.displayId } } if (newDisplayId == null) { - ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found") + KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found") return } moveToDisplay(task, newDisplayId) @@ -281,17 +281,17 @@ class DesktopTasksController( * No-op if task is already on that display per [RunningTaskInfo.displayId]. */ private fun moveToDisplay(task: RunningTaskInfo, displayId: Int) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d", + KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d", task.taskId, displayId) if (task.displayId == displayId) { - ProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display") + KtProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display") return } val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId) if (displayAreaInfo == null) { - ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found") + KtProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found") return } @@ -316,7 +316,7 @@ class DesktopTasksController( } private fun bringDesktopAppsToFront(displayId: Int, wct: WindowContainerTransaction) { - ProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront") + KtProtoLog.v(WM_SHELL_DESKTOP_MODE, "bringDesktopAppsToFront") val activeTasks = desktopModeTaskRepository.getActiveTasks(displayId) // First move home to front and then other tasks on top of it @@ -397,7 +397,7 @@ class DesktopTasksController( if (task.windowingMode == WINDOWING_MODE_FULLSCREEN) { // If there are any visible desktop tasks, switch the task to freeform if (activeTasks.any { desktopModeTaskRepository.isVisibleTask(it) }) { - ProtoLog.d( + KtProtoLog.d( WM_SHELL_DESKTOP_MODE, "DesktopTasksController#handleRequest: switch fullscreen task to freeform," + " taskId=%d", @@ -414,7 +414,7 @@ class DesktopTasksController( // If no visible desktop tasks, switch this task to freeform as the transition came // outside of this controller if (activeTasks.none { desktopModeTaskRepository.isVisibleTask(it) }) { - ProtoLog.d( + KtProtoLog.d( WM_SHELL_DESKTOP_MODE, "DesktopTasksController#handleRequest: switch freeform task to fullscreen," + " taskId=%d", diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java index 24d0b996a3cb..f51eb5299dd9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java @@ -180,6 +180,35 @@ public class PipBoundsAlgorithm { return null; } + + /** + * Returns the source hint rect if it is valid (if provided and is contained by the current + * task bounds, while not smaller than the destination bounds). + */ + @Nullable + public static Rect getValidSourceHintRect(PictureInPictureParams params, Rect sourceBounds, + Rect destinationBounds) { + Rect sourceRectHint = getValidSourceHintRect(params, sourceBounds); + if (!isSourceRectHintValidForEnterPip(sourceRectHint, destinationBounds)) { + sourceRectHint = null; + } + return sourceRectHint; + } + + /** + * This is a situation in which the source rect hint on at least one axis is smaller + * than the destination bounds, which represents a problem because we would have to scale + * up that axis to fit the bounds. So instead, just fallback to the non-source hint + * animation in this case. + * + * @return {@code false} if the given source is too small to use for the entering animation. + */ + static boolean isSourceRectHintValidForEnterPip(Rect sourceRectHint, Rect destinationBounds) { + return sourceRectHint != null + && sourceRectHint.width() > destinationBounds.width() + && sourceRectHint.height() > destinationBounds.height(); + } + public float getDefaultAspectRatio() { return mDefaultAspectRatio; } 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 6cedcf534f3b..363d6759f8d0 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 @@ -1657,8 +1657,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, "%s: Abort animation, invalid leash", TAG); return null; } - if (isInPipDirection(direction) - && !isSourceRectHintValidForEnterPip(sourceHintRect, destinationBounds)) { + if (isInPipDirection(direction) && !PipBoundsAlgorithm + .isSourceRectHintValidForEnterPip(sourceHintRect, destinationBounds)) { // The given source rect hint is too small for enter PiP animation, reset it to null. sourceHintRect = null; } @@ -1757,20 +1757,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } /** - * This is a situation in which the source rect hint on at least one axis is smaller - * than the destination bounds, which represents a problem because we would have to scale - * up that axis to fit the bounds. So instead, just fallback to the non-source hint - * animation in this case. - * - * @return {@code false} if the given source is too small to use for the entering animation. - */ - private boolean isSourceRectHintValidForEnterPip(Rect sourceRectHint, Rect destinationBounds) { - return sourceRectHint != null - && sourceRectHint.width() > destinationBounds.width() - && sourceRectHint.height() > destinationBounds.height(); - } - - /** * Sync with {@link SplitScreenController} on destination bounds if PiP is going to * split screen. * 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 98db707d1105..6b8108a50589 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 @@ -764,7 +764,7 @@ public class PipTransition extends PipTransitionController { final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds(); int rotationDelta = deltaRotation(startRotation, endRotation); Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect( - taskInfo.pictureInPictureParams, currentBounds); + taskInfo.pictureInPictureParams, currentBounds, destinationBounds); if (rotationDelta != Surface.ROTATION_0 && mInFixedRotation) { // Need to get the bounds of new rotation in old rotation for fixed rotation, computeEnterPipRotatedBounds(rotationDelta, startRotation, endRotation, taskInfo, 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 5c2f1438c08e..b8373f3548ca 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 @@ -1538,7 +1538,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } void finishEnterSplitScreen(SurfaceControl.Transaction t) { - mSplitLayout.init(); + mSplitLayout.update(t); setDividerVisibility(true, t); // Ensure divider surface are re-parented back into the hierarchy at the end of the // transition. See Transition#buildFinishTransaction for more detail. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt new file mode 100644 index 000000000000..9b48a542720c --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt @@ -0,0 +1,74 @@ +/* + * 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. + */ + +package com.android.wm.shell.util + +import android.util.Log +import com.android.internal.protolog.common.IProtoLogGroup +import com.android.wm.shell.protolog.ShellProtoLogImpl + +/** + * Log messages using an API similar to [com.android.internal.protolog.common.ProtoLog]. Useful for + * logging from Kotlin classes as ProtoLog does not have support for Kotlin. + * + * All messages are logged to logcat if logging is enabled for that [IProtoLogGroup]. + */ +// TODO(b/168581922): remove once ProtoLog adds support for Kotlin +class KtProtoLog { + companion object { + /** @see [com.android.internal.protolog.common.ProtoLog.d] */ + fun d(group: IProtoLogGroup, messageString: String, vararg args: Any) { + if (ShellProtoLogImpl.isEnabled(group)) { + Log.d(group.tag, String.format(messageString, *args)) + } + } + + /** @see [com.android.internal.protolog.common.ProtoLog.v] */ + fun v(group: IProtoLogGroup, messageString: String, vararg args: Any) { + if (ShellProtoLogImpl.isEnabled(group)) { + Log.v(group.tag, String.format(messageString, *args)) + } + } + + /** @see [com.android.internal.protolog.common.ProtoLog.i] */ + fun i(group: IProtoLogGroup, messageString: String, vararg args: Any) { + if (ShellProtoLogImpl.isEnabled(group)) { + Log.i(group.tag, String.format(messageString, *args)) + } + } + + /** @see [com.android.internal.protolog.common.ProtoLog.w] */ + fun w(group: IProtoLogGroup, messageString: String, vararg args: Any) { + if (ShellProtoLogImpl.isEnabled(group)) { + Log.w(group.tag, String.format(messageString, *args)) + } + } + + /** @see [com.android.internal.protolog.common.ProtoLog.e] */ + fun e(group: IProtoLogGroup, messageString: String, vararg args: Any) { + if (ShellProtoLogImpl.isEnabled(group)) { + Log.e(group.tag, String.format(messageString, *args)) + } + } + + /** @see [com.android.internal.protolog.common.ProtoLog.wtf] */ + fun wtf(group: IProtoLogGroup, messageString: String, vararg args: Any) { + if (ShellProtoLogImpl.isEnabled(group)) { + Log.wtf(group.tag, String.format(messageString, *args)) + } + } + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java index 4de529885565..55781f1b4d6f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIWindowManagerTest.java @@ -37,6 +37,7 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.app.TaskInfo; +import android.content.res.Configuration; import android.graphics.Rect; import android.testing.AndroidTestingRunner; import android.util.Pair; @@ -455,12 +456,21 @@ public class CompatUIWindowManagerTest extends ShellTestCase { verify(mLayout).setCameraCompatHintVisibility(/* show= */ true); } + @Test + public void testWhenDockedStateHasChanged_needsToBeRecreated() { + ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo(); + newTaskInfo.configuration.uiMode |= Configuration.UI_MODE_TYPE_DESK; + + Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener)); + } + private static TaskInfo createTaskInfo(boolean hasSizeCompat, @TaskInfo.CameraCompatControlState int cameraCompatControlState) { ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); taskInfo.taskId = TASK_ID; taskInfo.topActivityInSizeCompat = hasSizeCompat; taskInfo.cameraCompatControlState = cameraCompatControlState; + taskInfo.configuration.uiMode &= ~Configuration.UI_MODE_TYPE_DESK; return taskInfo; } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java index 5bcc72e73cb9..973a99c269ea 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/ReachabilityEduWindowManagerTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertNull; import android.app.ActivityManager; import android.app.TaskInfo; +import android.content.res.Configuration; import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; @@ -31,6 +32,8 @@ import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.SyncTransactionQueue; +import junit.framework.Assert; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,63 +49,61 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @SmallTest public class ReachabilityEduWindowManagerTest extends ShellTestCase { - - private static final int USER_ID = 1; - private static final int TASK_ID = 1; - @Mock private SyncTransactionQueue mSyncTransactionQueue; @Mock private ShellTaskOrganizer.TaskListener mTaskListener; @Mock - private CompatUIController.CompatUICallback mCallback; - @Mock private CompatUIConfiguration mCompatUIConfiguration; @Mock private DisplayLayout mDisplayLayout; - private TestShellExecutor mExecutor; + private TaskInfo mTaskInfo; + private ReachabilityEduWindowManager mWindowManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); mExecutor = new TestShellExecutor(); + mTaskInfo = new ActivityManager.RunningTaskInfo(); + mTaskInfo.configuration.uiMode = + (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) + | Configuration.UI_MODE_NIGHT_NO; + mTaskInfo.configuration.uiMode = + (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK) + | Configuration.UI_MODE_TYPE_NORMAL; + mWindowManager = createReachabilityEduWindowManager(mTaskInfo); } @Test public void testCreateLayout_notEligible_doesNotCreateLayout() { - final ReachabilityEduWindowManager windowManager = createReachabilityEduWindowManager( - createTaskInfo(/* userId= */ USER_ID, /*isLetterboxDoubleTapEnabled */ false)); - - assertFalse(windowManager.createLayout(/* canShow= */ true)); + assertFalse(mWindowManager.createLayout(/* canShow= */ true)); - assertNull(windowManager.mLayout); + assertNull(mWindowManager.mLayout); } - private ReachabilityEduWindowManager createReachabilityEduWindowManager(TaskInfo taskInfo) { - return new ReachabilityEduWindowManager(mContext, taskInfo, mSyncTransactionQueue, - mTaskListener, mDisplayLayout, mCompatUIConfiguration, mExecutor); + @Test + public void testWhenDockedStateHasChanged_needsToBeRecreated() { + ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo(); + newTaskInfo.configuration.uiMode = + (newTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK) + | Configuration.UI_MODE_TYPE_DESK; + + Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener)); } - private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled) { - return createTaskInfo(userId, /* isLetterboxDoubleTapEnabled */ isLetterboxDoubleTapEnabled, - /* topActivityLetterboxVerticalPosition */ -1, - /* topActivityLetterboxHorizontalPosition */ -1, - /* topActivityLetterboxWidth */ -1, - /* topActivityLetterboxHeight */ -1); + @Test + public void testWhenDarkLightThemeHasChanged_needsToBeRecreated() { + ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo(); + mTaskInfo.configuration.uiMode = + (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) + | Configuration.UI_MODE_NIGHT_YES; + + Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener)); } - private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled, - int topActivityLetterboxVerticalPosition, int topActivityLetterboxHorizontalPosition, - int topActivityLetterboxWidth, int topActivityLetterboxHeight) { - ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo(); - taskInfo.userId = userId; - taskInfo.taskId = TASK_ID; - taskInfo.isLetterboxDoubleTapEnabled = isLetterboxDoubleTapEnabled; - taskInfo.topActivityLetterboxVerticalPosition = topActivityLetterboxVerticalPosition; - taskInfo.topActivityLetterboxHorizontalPosition = topActivityLetterboxHorizontalPosition; - taskInfo.topActivityLetterboxWidth = topActivityLetterboxWidth; - taskInfo.topActivityLetterboxHeight = topActivityLetterboxHeight; - return taskInfo; + private ReachabilityEduWindowManager createReachabilityEduWindowManager(TaskInfo taskInfo) { + return new ReachabilityEduWindowManager(mContext, taskInfo, mSyncTransactionQueue, + mTaskListener, mDisplayLayout, mCompatUIConfiguration, mExecutor); } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java new file mode 100644 index 000000000000..9f109a1d0f50 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/RestartDialogWindowManagerTest.java @@ -0,0 +1,97 @@ +/* + * 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. + */ + +package com.android.wm.shell.compatui; + +import android.app.ActivityManager; +import android.app.TaskInfo; +import android.content.res.Configuration; +import android.testing.AndroidTestingRunner; +import android.util.Pair; + +import androidx.test.filters.SmallTest; + +import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.common.DisplayLayout; +import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.transition.Transitions; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.function.Consumer; + +/** + * Tests for {@link RestartDialogWindowManager}. + * + * Build/Install/Run: + * atest WMShellUnitTests:RestartDialogWindowManagerTest + */ +@RunWith(AndroidTestingRunner.class) +@SmallTest +public class RestartDialogWindowManagerTest extends ShellTestCase { + + @Mock + private SyncTransactionQueue mSyncTransactionQueue; + @Mock private ShellTaskOrganizer.TaskListener mTaskListener; + @Mock private CompatUIConfiguration mCompatUIConfiguration; + @Mock private Transitions mTransitions; + @Mock private Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnRestartCallback; + @Mock private Consumer<Pair<TaskInfo, ShellTaskOrganizer.TaskListener>> mOnDismissCallback; + private RestartDialogWindowManager mWindowManager; + private TaskInfo mTaskInfo; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mTaskInfo = new ActivityManager.RunningTaskInfo(); + mTaskInfo.configuration.uiMode = + (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) + | Configuration.UI_MODE_NIGHT_NO; + mTaskInfo.configuration.uiMode = + (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK) + | Configuration.UI_MODE_TYPE_NORMAL; + mWindowManager = new RestartDialogWindowManager(mContext, mTaskInfo, mSyncTransactionQueue, + mTaskListener, new DisplayLayout(), mTransitions, mOnRestartCallback, + mOnDismissCallback, mCompatUIConfiguration); + } + + @Test + public void testWhenDockedStateHasChanged_needsToBeRecreated() { + ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo(); + newTaskInfo.configuration.uiMode = + (newTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_TYPE_MASK) + | Configuration.UI_MODE_TYPE_DESK; + + Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener)); + } + + @Test + public void testWhenDarkLightThemeHasChanged_needsToBeRecreated() { + ActivityManager.RunningTaskInfo newTaskInfo = new ActivityManager.RunningTaskInfo(); + mTaskInfo.configuration.uiMode = + (mTaskInfo.configuration.uiMode & ~Configuration.UI_MODE_NIGHT_MASK) + | Configuration.UI_MODE_NIGHT_YES; + + Assert.assertTrue(mWindowManager.needsToBeRecreated(newTaskInfo, mTaskListener)); + } +} |