Loading core/java/android/view/Display.java +29 −0 Original line number Diff line number Diff line Loading @@ -338,6 +338,21 @@ public final class Display { /** @hide */ public static final int COLOR_MODE_DISPLAY_P3 = 9; /** * Indicates that when display is removed, all its activities will be moved to the primary * display and the topmost activity should become focused. * * @hide */ public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0; /** * Indicates that when display is removed, all its stacks and tasks will be removed, all * activities will be destroyed according to the usual lifecycle. * * @hide */ public static final int REMOVE_MODE_DESTROY_CONTENT = 1; /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} Loading Loading @@ -769,6 +784,20 @@ public final class Display { } } /** * @hide * Get current remove mode of the display - what actions should be performed with the display's * content when it is removed. Default behavior for public displays in this case is to move all * activities to the primary display and make it focused. For private display - destroy all * activities. * * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY * @see #REMOVE_MODE_DESTROY_CONTENT */ public int getRemoveMode() { return mDisplayInfo.removeMode; } /** * Returns the display's HDR capabilities. * Loading core/java/android/view/DisplayInfo.java +16 −1 Original line number Diff line number Diff line Loading @@ -238,6 +238,15 @@ public final class DisplayInfo implements Parcelable { */ public String ownerPackageName; /** * @hide * Get current remove mode of the display - what actions should be performed with the display's * content when it is removed. * * @see Display#getRemoveMode() */ public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { @Override public DisplayInfo createFromParcel(Parcel source) { Loading Loading @@ -298,7 +307,8 @@ public final class DisplayInfo implements Parcelable { && presentationDeadlineNanos == other.presentationDeadlineNanos && state == other.state && ownerUid == other.ownerUid && Objects.equal(ownerPackageName, other.ownerPackageName); && Objects.equal(ownerPackageName, other.ownerPackageName) && removeMode == other.removeMode; } @Override Loading Loading @@ -341,6 +351,7 @@ public final class DisplayInfo implements Parcelable { state = other.state; ownerUid = other.ownerUid; ownerPackageName = other.ownerPackageName; removeMode = other.removeMode; } public void readFromParcel(Parcel source) { Loading Loading @@ -385,6 +396,7 @@ public final class DisplayInfo implements Parcelable { ownerUid = source.readInt(); ownerPackageName = source.readString(); uniqueId = source.readString(); removeMode = source.readInt(); } @Override Loading Loading @@ -428,6 +440,7 @@ public final class DisplayInfo implements Parcelable { dest.writeInt(ownerUid); dest.writeString(ownerPackageName); dest.writeString(uniqueId); dest.writeInt(removeMode); } @Override Loading Loading @@ -637,6 +650,8 @@ public final class DisplayInfo implements Parcelable { sb.append(" (uid ").append(ownerUid).append(")"); } sb.append(flagsToString(flags)); sb.append(", removeMode "); sb.append(removeMode); sb.append("}"); return sb.toString(); } Loading services/core/java/com/android/server/am/ActivityManagerService.java +1 −1 Original line number Diff line number Diff line Loading @@ -9916,7 +9916,7 @@ public class ActivityManagerService extends IActivityManager.Stub try { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId + " to displayId=" + displayId); mStackSupervisor.moveStackToDisplayLocked(stackId, displayId); mStackSupervisor.moveStackToDisplayLocked(stackId, displayId, ON_TOP); } finally { Binder.restoreCallingIdentity(ident); } Loading services/core/java/com/android/server/am/ActivityStack.java +15 −2 Original line number Diff line number Diff line Loading @@ -477,6 +477,8 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL mTmpRect2.setEmpty(); mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2); postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); adjustFocusToNextFocusableStackLocked("reparent", true /* allowFocusSelf */); mStackSupervisor.resumeFocusedStackTopActivityLocked(); } /** Loading Loading @@ -3179,8 +3181,18 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL mStackSupervisor.topRunningActivityLocked(), myReason); } /** Find next proper focusable stack and make it focused. */ private boolean adjustFocusToNextFocusableStackLocked(String reason) { final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(this); return adjustFocusToNextFocusableStackLocked(reason, false /* allowFocusSelf */); } /** * Find next proper focusable stack and make it focused. * @param allowFocusSelf Is the focus allowed to remain on the same stack. */ private boolean adjustFocusToNextFocusableStackLocked(String reason, boolean allowFocusSelf) { final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked( allowFocusSelf ? null : this); final String myReason = reason + " adjustFocusToNextFocusableStack"; if (stack == null) { return false; Loading @@ -3190,7 +3202,8 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL if (stack.isHomeOrRecentsStack() && (top == null || !top.visible)) { // If we will be focusing on the home stack next and its current top activity isn't // visible, then use the task return to value to determine the home task to display next. // visible, then use the task return to value to determine the home task to display // next. return mStackSupervisor.moveHomeStackTaskToTop(reason); } Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +18 −9 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS; Loading Loading @@ -2616,8 +2617,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * Move stack with all its existing content to specified display. * @param stackId Id of stack to move. * @param displayId Id of display to move stack to. * @param onTop Indicates whether container should be place on top or on bottom. */ void moveStackToDisplayLocked(int stackId, int displayId) { void moveStackToDisplayLocked(int stackId, int displayId, boolean onTop) { final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId=" Loading @@ -2631,7 +2633,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D + " to its current displayId=" + displayId); } activityContainer.moveToDisplayLocked(activityDisplay); activityContainer.moveToDisplayLocked(activityDisplay, onTop); } else { throw new IllegalStateException("moveStackToDisplayLocked: Stack with stackId=" + stackId + " is not attached to any display."); Loading Loading @@ -3777,12 +3779,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay != null) { final boolean destroyContentOnRemoval = activityDisplay.shouldDestroyContentOnRemove(); ArrayList<ActivityStack> stacks = activityDisplay.mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); // TODO: Implement proper stack removal and ability to choose the behavior - // remove stack completely or move it to other display. moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY); moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, !destroyContentOnRemoval /* onTop */); if (destroyContentOnRemoval) { stack.finishAllActivitiesLocked(true /* immediately */); } } mActivityDisplays.remove(displayId); } Loading Loading @@ -4451,8 +4457,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** * Move the stack to specified display. * @param activityDisplay Target display to move the stack to. * @param onTop Indicates whether container should be place on top or on bottom. */ void moveToDisplayLocked(ActivityDisplay activityDisplay) { void moveToDisplayLocked(ActivityDisplay activityDisplay, boolean onTop) { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveToDisplayLocked: " + this + " from display=" + mActivityDisplay + " to display=" + activityDisplay + " Callers=" + Debug.getCallers(2)); Loading @@ -4460,7 +4467,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D removeFromDisplayLocked(); mActivityDisplay = activityDisplay; mStack.reparent(activityDisplay, ON_TOP); mStack.reparent(activityDisplay, onTop); } @Override Loading Loading @@ -4642,8 +4649,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Actual Display this object tracks. */ int mDisplayId; Display mDisplay; private final DisplayMetrics mRealMetrics = new DisplayMetrics(); private final Point mRealSize = new Point(); /** All of the stacks on this display. Order matters, topmost stack is in front of all other * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ Loading Loading @@ -4737,6 +4742,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } return mDisplayAccessUIDs; } boolean shouldDestroyContentOnRemove() { return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; } } class VirtualActivityDisplay extends ActivityDisplay { Loading Loading
core/java/android/view/Display.java +29 −0 Original line number Diff line number Diff line Loading @@ -338,6 +338,21 @@ public final class Display { /** @hide */ public static final int COLOR_MODE_DISPLAY_P3 = 9; /** * Indicates that when display is removed, all its activities will be moved to the primary * display and the topmost activity should become focused. * * @hide */ public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0; /** * Indicates that when display is removed, all its stacks and tasks will be removed, all * activities will be destroyed according to the usual lifecycle. * * @hide */ public static final int REMOVE_MODE_DESTROY_CONTENT = 1; /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} Loading Loading @@ -769,6 +784,20 @@ public final class Display { } } /** * @hide * Get current remove mode of the display - what actions should be performed with the display's * content when it is removed. Default behavior for public displays in this case is to move all * activities to the primary display and make it focused. For private display - destroy all * activities. * * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY * @see #REMOVE_MODE_DESTROY_CONTENT */ public int getRemoveMode() { return mDisplayInfo.removeMode; } /** * Returns the display's HDR capabilities. * Loading
core/java/android/view/DisplayInfo.java +16 −1 Original line number Diff line number Diff line Loading @@ -238,6 +238,15 @@ public final class DisplayInfo implements Parcelable { */ public String ownerPackageName; /** * @hide * Get current remove mode of the display - what actions should be performed with the display's * content when it is removed. * * @see Display#getRemoveMode() */ public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { @Override public DisplayInfo createFromParcel(Parcel source) { Loading Loading @@ -298,7 +307,8 @@ public final class DisplayInfo implements Parcelable { && presentationDeadlineNanos == other.presentationDeadlineNanos && state == other.state && ownerUid == other.ownerUid && Objects.equal(ownerPackageName, other.ownerPackageName); && Objects.equal(ownerPackageName, other.ownerPackageName) && removeMode == other.removeMode; } @Override Loading Loading @@ -341,6 +351,7 @@ public final class DisplayInfo implements Parcelable { state = other.state; ownerUid = other.ownerUid; ownerPackageName = other.ownerPackageName; removeMode = other.removeMode; } public void readFromParcel(Parcel source) { Loading Loading @@ -385,6 +396,7 @@ public final class DisplayInfo implements Parcelable { ownerUid = source.readInt(); ownerPackageName = source.readString(); uniqueId = source.readString(); removeMode = source.readInt(); } @Override Loading Loading @@ -428,6 +440,7 @@ public final class DisplayInfo implements Parcelable { dest.writeInt(ownerUid); dest.writeString(ownerPackageName); dest.writeString(uniqueId); dest.writeInt(removeMode); } @Override Loading Loading @@ -637,6 +650,8 @@ public final class DisplayInfo implements Parcelable { sb.append(" (uid ").append(ownerUid).append(")"); } sb.append(flagsToString(flags)); sb.append(", removeMode "); sb.append(removeMode); sb.append("}"); return sb.toString(); } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +1 −1 Original line number Diff line number Diff line Loading @@ -9916,7 +9916,7 @@ public class ActivityManagerService extends IActivityManager.Stub try { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId + " to displayId=" + displayId); mStackSupervisor.moveStackToDisplayLocked(stackId, displayId); mStackSupervisor.moveStackToDisplayLocked(stackId, displayId, ON_TOP); } finally { Binder.restoreCallingIdentity(ident); } Loading
services/core/java/com/android/server/am/ActivityStack.java +15 −2 Original line number Diff line number Diff line Loading @@ -477,6 +477,8 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL mTmpRect2.setEmpty(); mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2); postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); adjustFocusToNextFocusableStackLocked("reparent", true /* allowFocusSelf */); mStackSupervisor.resumeFocusedStackTopActivityLocked(); } /** Loading Loading @@ -3179,8 +3181,18 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL mStackSupervisor.topRunningActivityLocked(), myReason); } /** Find next proper focusable stack and make it focused. */ private boolean adjustFocusToNextFocusableStackLocked(String reason) { final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked(this); return adjustFocusToNextFocusableStackLocked(reason, false /* allowFocusSelf */); } /** * Find next proper focusable stack and make it focused. * @param allowFocusSelf Is the focus allowed to remain on the same stack. */ private boolean adjustFocusToNextFocusableStackLocked(String reason, boolean allowFocusSelf) { final ActivityStack stack = mStackSupervisor.getNextFocusableStackLocked( allowFocusSelf ? null : this); final String myReason = reason + " adjustFocusToNextFocusableStack"; if (stack == null) { return false; Loading @@ -3190,7 +3202,8 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL if (stack.isHomeOrRecentsStack() && (top == null || !top.visible)) { // If we will be focusing on the home stack next and its current top activity isn't // visible, then use the task return to value to determine the home task to display next. // visible, then use the task return to value to determine the home task to display // next. return mStackSupervisor.moveHomeStackTaskToTop(reason); } Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +18 −9 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS; Loading Loading @@ -2616,8 +2617,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * Move stack with all its existing content to specified display. * @param stackId Id of stack to move. * @param displayId Id of display to move stack to. * @param onTop Indicates whether container should be place on top or on bottom. */ void moveStackToDisplayLocked(int stackId, int displayId) { void moveStackToDisplayLocked(int stackId, int displayId, boolean onTop) { final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay == null) { throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId=" Loading @@ -2631,7 +2633,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D + " to its current displayId=" + displayId); } activityContainer.moveToDisplayLocked(activityDisplay); activityContainer.moveToDisplayLocked(activityDisplay, onTop); } else { throw new IllegalStateException("moveStackToDisplayLocked: Stack with stackId=" + stackId + " is not attached to any display."); Loading Loading @@ -3777,12 +3779,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D synchronized (mService) { ActivityDisplay activityDisplay = mActivityDisplays.get(displayId); if (activityDisplay != null) { final boolean destroyContentOnRemoval = activityDisplay.shouldDestroyContentOnRemove(); ArrayList<ActivityStack> stacks = activityDisplay.mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); // TODO: Implement proper stack removal and ability to choose the behavior - // remove stack completely or move it to other display. moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY); moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, !destroyContentOnRemoval /* onTop */); if (destroyContentOnRemoval) { stack.finishAllActivitiesLocked(true /* immediately */); } } mActivityDisplays.remove(displayId); } Loading Loading @@ -4451,8 +4457,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** * Move the stack to specified display. * @param activityDisplay Target display to move the stack to. * @param onTop Indicates whether container should be place on top or on bottom. */ void moveToDisplayLocked(ActivityDisplay activityDisplay) { void moveToDisplayLocked(ActivityDisplay activityDisplay, boolean onTop) { if (DEBUG_STACK) Slog.d(TAG_STACK, "moveToDisplayLocked: " + this + " from display=" + mActivityDisplay + " to display=" + activityDisplay + " Callers=" + Debug.getCallers(2)); Loading @@ -4460,7 +4467,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D removeFromDisplayLocked(); mActivityDisplay = activityDisplay; mStack.reparent(activityDisplay, ON_TOP); mStack.reparent(activityDisplay, onTop); } @Override Loading Loading @@ -4642,8 +4649,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Actual Display this object tracks. */ int mDisplayId; Display mDisplay; private final DisplayMetrics mRealMetrics = new DisplayMetrics(); private final Point mRealSize = new Point(); /** All of the stacks on this display. Order matters, topmost stack is in front of all other * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ Loading Loading @@ -4737,6 +4742,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } return mDisplayAccessUIDs; } boolean shouldDestroyContentOnRemove() { return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; } } class VirtualActivityDisplay extends ActivityDisplay { Loading