Merge "Make stacks without running activities being invisible"

This commit is contained in:
Louis Chang
2018-10-31 11:56:21 +00:00
committed by Android (Google) Code Review
9 changed files with 165 additions and 114 deletions

View File

@@ -373,7 +373,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
return getOrCreateStack(windowingMode, activityType, onTop);
}
private int getNextStackId() {
@VisibleForTesting
int getNextStackId() {
return sNextFreeStackId++;
}

View File

@@ -48,41 +48,7 @@ import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_APP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_APP;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
@@ -102,8 +68,42 @@ import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_APP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_APP;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static java.lang.Integer.MAX_VALUE;
import android.app.Activity;
@@ -1807,13 +1807,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
final ActivityRecord top = topRunningActivityLocked();
if (top == null && isInStackLocked(starting) == null && !isTopStackOnDisplay()) {
// Shouldn't be visible if you don't have any running activities, not starting one, and
// not the top stack on display.
return false;
}
final ActivityDisplay display = getDisplay();
boolean gotSplitScreenStack = false;
boolean gotOpaqueSplitScreenPrimary = false;
@@ -1822,9 +1815,16 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean isAssistantType = isActivityTypeAssistant();
for (int i = display.getChildCount() - 1; i >= 0; --i) {
final ActivityStack other = display.getChildAt(i);
final boolean hasRunningActivities = other.topRunningActivityLocked() != null;
if (other == this) {
// Should be visible if there is no other stack occluding it.
return true;
// Should be visible if there is no other stack occluding it, unless it doesn't
// have any running activities, not starting one and not home stack.
return hasRunningActivities || isInStackLocked(starting) != null
|| isActivityTypeHome();
}
if (!hasRunningActivities) {
continue;
}
final int otherWindowingMode = other.getWindowingMode();

View File

@@ -60,8 +60,7 @@ public class ActivityDisplayTests extends ActivityTestsBase {
public void testLastFocusedStackIsUpdatedWhenMovingStack() {
// Create a stack at bottom.
final ActivityDisplay display = mSupervisor.getDefaultDisplay();
final ActivityStack stack = display.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, !ON_TOP);
final ActivityStack stack = new StackBuilder(mSupervisor).setOnTop(!ON_TOP).build();
final ActivityStack prevFocusedStack = display.getFocusedStack();
stack.moveToFront("moveStackToFront");
@@ -140,16 +139,14 @@ public class ActivityDisplayTests extends ActivityTestsBase {
*/
@Test
public void testTopRunningActivity() {
// Create stack to hold focus.
final ActivityDisplay display = mSupervisor.getDefaultDisplay();
final ActivityStack emptyStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
final KeyguardController keyguard = mSupervisor.getKeyguardController();
final ActivityStack stack = mSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(stack).build();
final ActivityStack stack = new StackBuilder(mSupervisor).build();
final ActivityRecord activity = stack.getTopActivity();
// Create empty stack on top.
final ActivityStack emptyStack =
new StackBuilder(mSupervisor).setCreateActivity(false).build();
// Make sure the top running activity is not affected when keyguard is not locked.
assertTopRunningActivity(activity, display);
@@ -159,8 +156,8 @@ public class ActivityDisplayTests extends ActivityTestsBase {
assertEquals(activity, display.topRunningActivity());
assertNull(display.topRunningActivity(true /* considerKeyguardState */));
// Change focus to stack with activity.
stack.moveToFront("focusChangeToTestStack");
// Move stack with activity to top.
stack.moveToFront("testStackToFront");
assertEquals(stack, display.getFocusedStack());
assertEquals(activity, display.topRunningActivity());
assertNull(display.topRunningActivity(true /* considerKeyguardState */));
@@ -175,11 +172,10 @@ public class ActivityDisplayTests extends ActivityTestsBase {
// Ensure the show when locked activity is returned.
assertTopRunningActivity(showWhenLockedActivity, display);
// Change focus back to empty stack.
emptyStack.moveToFront("focusChangeToEmptyStack");
assertEquals(emptyStack, display.getFocusedStack());
// If there is no running activity in focused stack, the running activity in next focusable
// stack should be returned.
// Move empty stack to front. The running activity in focusable stack which below the
// empty stack should be returned.
emptyStack.moveToFront("emptyStackToFront");
assertEquals(stack, display.getFocusedStack());
assertTopRunningActivity(showWhenLockedActivity, display);
}

View File

@@ -79,10 +79,9 @@ public class ActivityRecordTests extends ActivityTestsBase {
super.setUp();
setupActivityTaskManagerService();
mStack = mSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
mActivity = new ActivityBuilder(mService).setTask(mTask).build();
mStack = new StackBuilder(mSupervisor).build();
mTask = mStack.getChildAt(0);
mActivity = mTask.getTopActivity();
}
@Test

View File

@@ -359,15 +359,12 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
public void testFindTaskToMoveToFrontWhenRecentsOnTop() throws Exception {
// Create stack/task on default display.
final ActivityDisplay display = mSupervisor.getDefaultDisplay();
final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */);
final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
final TestActivityStack targetStack = new StackBuilder(mSupervisor).setOnTop(false).build();
final TaskRecord targetTask = targetStack.getChildAt(0);
// Create Recents on top of the display.
final ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS, true /* onTop */);
final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
new ActivityBuilder(mService).setTask(task).build();
final ActivityStack stack =
new StackBuilder(mSupervisor).setActivityType(ACTIVITY_TYPE_RECENTS).build();
final String reason = "findTaskToMoveToFront";
mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,

View File

@@ -26,8 +26,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
@@ -361,14 +361,12 @@ public class ActivityStackTests extends ActivityTestsBase {
translucentStack.topRunningActivityLocked();
topRunningTranslucentActivity.finishing = true;
// Home shouldn't be visible since its activity is marked as finishing and it isn't the top
// of the stack list.
assertFalse(homeStack.shouldBeVisible(null /* starting */));
// Home stack should be visible even there are no running activities.
assertTrue(homeStack.shouldBeVisible(null /* starting */));
// Home should be visible if we are starting an activity within it.
assertTrue(homeStack.shouldBeVisible(topRunningHomeActivity /* starting */));
// The translucent stack should be visible since it is the top of the stack list even though
// it has its activity marked as finishing.
assertTrue(translucentStack.shouldBeVisible(null /* starting */));
// The translucent stack shouldn't be visible since its activity marked as finishing.
assertFalse(translucentStack.shouldBeVisible(null /* starting */));
}
@Test
@@ -672,9 +670,10 @@ public class ActivityStackTests extends ActivityTestsBase {
// There is still an activity1 in stack1 so the activity2 should be added to finishing list
// that will be destroyed until idle.
stack2.getTopActivity().visible = true;
final ActivityRecord activity2 = finishCurrentActivity(stack2);
assertEquals(FINISHING, activity2.getState());
assertTrue(mSupervisor.mFinishingActivities.contains(activity2));
assertEquals(STOPPING, activity2.getState());
assertTrue(mSupervisor.mStoppingActivities.contains(activity2));
// The display becomes empty. Since there is no next activity to be idle, the activity
// should be destroyed immediately with updating configuration to restore original state.

View File

@@ -39,14 +39,6 @@ import static org.mockito.Mockito.spy;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.content.pm.PackageManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.DisplayWindowController;
import org.junit.Rule;
import org.mockito.invocation.InvocationOnMock;
import android.app.IApplicationThread;
import android.content.ComponentName;
import android.content.Context;
@@ -54,6 +46,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
@@ -73,7 +66,10 @@ import com.android.internal.app.IVoiceInteractor;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.ServiceThread;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.AppWindowContainerController;
import com.android.server.wm.DisplayWindowController;
import com.android.server.wm.PinnedStackWindowController;
import com.android.server.wm.RootWindowContainerController;
import com.android.server.wm.StackWindowController;
@@ -83,7 +79,9 @@ import com.android.server.wm.WindowTestUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import java.io.File;
import java.util.List;
@@ -608,23 +606,9 @@ public class ActivityTestsBase {
@Override
<T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
int stackId, boolean onTop) {
if (windowingMode == WINDOWING_MODE_PINNED) {
return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop) {
@Override
Rect getDefaultPictureInPictureBounds(float aspectRatio) {
return new Rect(50, 50, 100, 100);
}
@Override
PinnedStackWindowController createStackWindowController(int displayId,
boolean onTop, Rect outBounds) {
return mock(PinnedStackWindowController.class);
}
};
} else {
return (T) new TestActivityStack(
this, stackId, mSupervisor, windowingMode, activityType, onTop);
}
return new StackBuilder(mSupervisor).setDisplay(this)
.setWindowingMode(windowingMode).setActivityType(activityType)
.setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build();
}
@Override
@@ -677,8 +661,19 @@ public class ActivityTestsBase {
private int mSupportsSplitScreen = SUPPORTS_SPLIT_SCREEN_UNSET;
TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
int windowingMode, int activityType, boolean onTop) {
int windowingMode, int activityType, boolean onTop, boolean createActivity) {
super(display, stackId, supervisor, windowingMode, activityType, onTop);
if (createActivity) {
new ActivityBuilder(mService).setCreateTask(true).setStack(this).build();
if (onTop) {
// We move the task to front again in order to regain focus after activity
// added to the stack. Or {@link ActivityDisplay#mPreferredTopFocusableStack}
// could be other stacks (e.g. home stack).
moveToFront("createActivityStack");
} else {
moveToBack("createActivityStack", null);
}
}
}
@Override
@@ -750,4 +745,71 @@ public class ActivityTestsBase {
ActivityOptions options) {
}
}
protected static class StackBuilder {
private final ActivityStackSupervisor mSupervisor;
private ActivityDisplay mDisplay;
private int mStackId = -1;
private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
private int mActivityType = ACTIVITY_TYPE_STANDARD;
private boolean mOnTop = true;
private boolean mCreateActivity = true;
StackBuilder(ActivityStackSupervisor supervisor) {
mSupervisor = supervisor;
mDisplay = mSupervisor.getDefaultDisplay();
}
StackBuilder setWindowingMode(int windowingMode) {
mWindowingMode = windowingMode;
return this;
}
StackBuilder setActivityType(int activityType) {
mActivityType = activityType;
return this;
}
StackBuilder setStackId(int stackId) {
mStackId = stackId;
return this;
}
StackBuilder setDisplay(ActivityDisplay display) {
mDisplay = display;
return this;
}
StackBuilder setOnTop(boolean onTop) {
mOnTop = onTop;
return this;
}
StackBuilder setCreateActivity(boolean createActivity) {
mCreateActivity = createActivity;
return this;
}
<T extends ActivityStack> T build() {
final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
if (mWindowingMode == WINDOWING_MODE_PINNED) {
return (T) new PinnedActivityStack(mDisplay, stackId, mSupervisor, mOnTop) {
@Override
Rect getDefaultPictureInPictureBounds(float aspectRatio) {
return new Rect(50, 50, 100, 100);
}
@Override
PinnedStackWindowController createStackWindowController(int displayId,
boolean onTop, Rect outBounds) {
return mock(PinnedStackWindowController.class);
}
};
} else {
return (T) new TestActivityStack(mDisplay, stackId, mSupervisor, mWindowingMode,
mActivityType, mOnTop, mCreateActivity);
}
}
}
}

View File

@@ -883,7 +883,7 @@ public class RecentTasksTest extends ActivityTestsBase {
MyTestActivityStack(ActivityDisplay display, ActivityStackSupervisor supervisor) {
super(display, LAST_STACK_ID++, supervisor, WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true);
ACTIVITY_TYPE_STANDARD, true /* onTop */, false /* createActivity */);
mDisplay = display;
}

View File

@@ -16,9 +16,7 @@
package com.android.server.am;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -30,7 +28,6 @@ import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
@@ -72,8 +69,8 @@ public class RunningTasksTest extends ActivityTestsBase {
final int numStacks = 2;
for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
final ActivityStack stack = new TestActivityStack(display, stackIndex, mSupervisor,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true);
final ActivityStack stack =
new StackBuilder(mSupervisor).setCreateActivity(false).build();
display.addChild(stack, POSITION_BOTTOM);
}