Handle uiMode change in CompatUI
When uiMode changes we need to recreate CompatUI components to
allow the update of the resources in case of switch between
Light/Dark more or when the device is docked/undocked.
This allows to cover the use case of a change in theme of
a docked device showing a restart dialog.
Fixes: 279170801
Test: atest WMShellUnitTests:CompatUIWindowManagerTest
atest WMShellUnitTests:ReachabilityEduWindowManagerTest
atest WMShellUnitTests:RestartDialogWindowManagerTest
Change-Id: I179df47bdc23f238dee9ffe6b2e579a67921eb1f
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
@@ -94,6 +99,17 @@ public abstract class CompatUIWindowManagerAbstract extends WindowlessWindowMana
|
||||
mDisplayLayout.getStableBounds(mStableBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(mWindowManager.createLayout(/* canShow= */ true));
|
||||
|
||||
assertFalse(windowManager.createLayout(/* canShow= */ true));
|
||||
assertNull(mWindowManager.mLayout);
|
||||
}
|
||||
|
||||
assertNull(windowManager.mLayout);
|
||||
@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));
|
||||
}
|
||||
|
||||
private ReachabilityEduWindowManager createReachabilityEduWindowManager(TaskInfo taskInfo) {
|
||||
return new ReachabilityEduWindowManager(mContext, taskInfo, mSyncTransactionQueue,
|
||||
mTaskListener, mDisplayLayout, mCompatUIConfiguration, mExecutor);
|
||||
}
|
||||
|
||||
private static TaskInfo createTaskInfo(int userId, boolean isLetterboxDoubleTapEnabled) {
|
||||
return createTaskInfo(userId, /* isLetterboxDoubleTapEnabled */ isLetterboxDoubleTapEnabled,
|
||||
/* topActivityLetterboxVerticalPosition */ -1,
|
||||
/* topActivityLetterboxHorizontalPosition */ -1,
|
||||
/* topActivityLetterboxWidth */ -1,
|
||||
/* topActivityLetterboxHeight */ -1);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user