Only show the toast of dismissing docked stack if it actually happens

When launching a non-resizable activity on secondary display, an overlay
activity will show "App may not work on a secondary display" on it.
Because the overlay activity is resizable, it is nothing to handle on
secondary display. But it falls to the condition of split-screen, and
even there is no docked stack, the toast of dismissing docked stack is
still shown.

Bug: 128674132
Test: atest ActivityStackSupervisorTests# \
      testHandleNonResizableTaskOnSecondaryDisplay

Change-Id: I1b8fe892ec4cace4f87112f132e0eefdae19024d
This commit is contained in:
Riddle Hsu
2019-03-15 20:26:27 +08:00
parent 9bb28c288c
commit bed3db4d0b
2 changed files with 62 additions and 31 deletions

View File

@@ -2453,46 +2453,43 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
mService.getTaskChangeNotificationController()
.notifyActivityLaunchOnSecondaryDisplayFailed(task.getTaskInfo(),
preferredDisplayId);
return;
} else if (!forceNonResizable && handleForcedResizableTask(task,
FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY)) {
return;
} else if (!forceNonResizable) {
handleForcedResizableTaskIfNeeded(task, FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY);
}
// The information about not support secondary display should already be notified, we
// don't want to show another message on default display about split-screen. And it may
// be the case that a resizable activity is launched on a non-resizable task.
return;
}
if (!task.supportsSplitScreenWindowingMode() || forceNonResizable) {
// Display a warning toast that we tried to put an app that doesn't support split-screen
// in split-screen.
mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
// Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
// we need to move it to top of fullscreen stack, otherwise it will be covered.
final ActivityStack dockedStack =
task.getStack().getDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null) {
// Display a warning toast that we tried to put an app that doesn't support
// split-screen in split-screen.
mService.getTaskChangeNotificationController()
.notifyActivityDismissingDockedStack();
moveTasksToFullscreenStackLocked(dockedStack, actualStack == dockedStack);
}
return;
}
handleForcedResizableTask(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
handleForcedResizableTaskIfNeeded(task, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN);
}
/**
* @return {@code true} if the top activity of the task is forced to be resizable and the user
* was notified about activity being forced resized.
*/
private boolean handleForcedResizableTask(TaskRecord task, int reason) {
/** Notifies that the top activity of the task is forced to be resizeable. */
private void handleForcedResizableTaskIfNeeded(TaskRecord task, int reason) {
final ActivityRecord topActivity = task.getTopActivity();
if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
&& !topActivity.noDisplay) {
final String packageName = topActivity.appInfo.packageName;
mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
task.taskId, reason, packageName);
return true;
if (topActivity == null || topActivity.noDisplay
|| !topActivity.isNonResizableOrForcedResizable()) {
return;
}
return false;
mService.getTaskChangeNotificationController().notifyActivityForcedResizable(
task.taskId, reason, topActivity.appInfo.packageName);
}
void activityRelaunchedLocked(IBinder token) {

View File

@@ -18,32 +18,26 @@ package com.android.server.wm;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import android.app.WaitResult;
import android.content.pm.ActivityInfo;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.MediumTest;
@@ -112,4 +106,44 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
assertEquals(deliverToTopWait.who, firstActivity.mActivityComponent);
}
}
/**
* Ensures that {@link TaskChangeNotificationController} notifies only when an activity is
* forced to resize on secondary display.
*/
@Test
public void testHandleNonResizableTaskOnSecondaryDisplay() {
// Create an unresizable task on secondary display.
final ActivityDisplay newDisplay = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
final ActivityStack stack = new StackBuilder(mRootActivityContainer)
.setDisplay(newDisplay).build();
final ActivityRecord unresizableActivity = stack.getTopActivity();
final TaskRecord task = unresizableActivity.getTaskRecord();
unresizableActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
task.setResizeMode(unresizableActivity.info.resizeMode);
final TaskChangeNotificationController taskChangeNotifier =
mService.getTaskChangeNotificationController();
spyOn(taskChangeNotifier);
mSupervisor.handleNonResizableTaskIfNeeded(task, newDisplay.getWindowingMode(),
newDisplay.mDisplayId, stack);
// The top activity is unresizable, so it should notify the activity is forced resizing.
verify(taskChangeNotifier).notifyActivityForcedResizable(eq(task.taskId),
eq(FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY),
eq(unresizableActivity.packageName));
reset(taskChangeNotifier);
// Put a resizable activity on top of the unresizable task.
final ActivityRecord resizableActivity = new ActivityBuilder(mService)
.setTask(task).build();
resizableActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
mSupervisor.handleNonResizableTaskIfNeeded(task, newDisplay.getWindowingMode(),
newDisplay.mDisplayId, stack);
// For the resizable activity, it is no need to force resizing or dismiss the docked stack.
verify(taskChangeNotifier, never()).notifyActivityForcedResizable(anyInt() /* taskId */,
anyInt() /* reason */, anyString() /* packageName */);
verify(taskChangeNotifier, never()).notifyActivityDismissingDockedStack();
}
}