Merge changes from topic "stack-gone"

* changes:
  HOME_STACK_ID, ASSISTANT_STACK_ID, and RECENTS_STACK_ID be gone!
  Ability to getOrCreateStack by windowingMode/activityType in AM.
This commit is contained in:
Wale Ogunwale
2017-09-28 17:37:57 +00:00
committed by Android (Google) Code Review
57 changed files with 1398 additions and 1314 deletions

View File

@@ -3864,6 +3864,8 @@ package android.app {
method public void moveTaskToFront(int, int);
method public void moveTaskToFront(int, int, android.os.Bundle);
method public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
method public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException;
method public void removeStacksWithActivityTypes(int[]) throws java.lang.SecurityException;
method public deprecated void restartPackage(java.lang.String);
method public static void setVrThread(int);
method public void setWatchHeapLimit(long);
@@ -4017,14 +4019,11 @@ package android.app {
}
public static class ActivityManager.StackId {
field public static final int ASSISTANT_STACK_ID = 6; // 0x6
field public static final int DOCKED_STACK_ID = 3; // 0x3
field public static final int FREEFORM_WORKSPACE_STACK_ID = 2; // 0x2
field public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1; // 0x1
field public static final int HOME_STACK_ID = 0; // 0x0
field public static final int INVALID_STACK_ID = -1; // 0xffffffff
field public static final int PINNED_STACK_ID = 4; // 0x4
field public static final int RECENTS_STACK_ID = 5; // 0x5
}
public static class ActivityManager.TaskDescription implements android.os.Parcelable {

View File

@@ -16,10 +16,6 @@
package android.app;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -46,6 +42,7 @@ import android.content.pm.IPackageDataObserver;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -675,10 +672,7 @@ public class ActivityManager {
/** First static stack ID.
* @hide */
public static final int FIRST_STATIC_STACK_ID = 0;
/** Home activity stack ID. */
public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;
private static final int FIRST_STATIC_STACK_ID = 0;
/** ID of stack where fullscreen activities are normally launched into. */
public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
@@ -692,15 +686,9 @@ public class ActivityManager {
/** ID of stack that always on top (always visible) when it exist. */
public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;
/** ID of stack that contains the Recents activity. */
public static final int RECENTS_STACK_ID = PINNED_STACK_ID + 1;
/** ID of stack that contains activities launched by the assistant. */
public static final int ASSISTANT_STACK_ID = RECENTS_STACK_ID + 1;
/** Last static stack stack ID.
* @hide */
public static final int LAST_STATIC_STACK_ID = ASSISTANT_STACK_ID;
private static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
/** Start of ID range used by stacks that are created dynamically.
* @hide */
@@ -719,15 +707,6 @@ public class ActivityManager {
return stackId >= FIRST_DYNAMIC_STACK_ID;
}
/**
* Returns true if dynamic stacks are allowed to be visible behind the input stack.
* @hide
*/
// TODO: Figure-out a way to remove.
public static boolean isDynamicStacksVisibleBehindAllowed(int stackId) {
return stackId == PINNED_STACK_ID || stackId == ASSISTANT_STACK_ID;
}
/**
* Returns true if we try to maintain focus in the current stack when the top activity
* finishes.
@@ -739,15 +718,6 @@ public class ActivityManager {
|| stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID;
}
/**
* Returns true if the input stack is affected by drag resizing.
* @hide
*/
public static boolean isStackAffectedByDragResizing(int stackId) {
return isStaticStack(stackId) && stackId != PINNED_STACK_ID
&& stackId != ASSISTANT_STACK_ID;
}
/**
* Returns true if the windows of tasks being moved to the target stack from the source
* stack should be replaced, meaning that window manager will keep the old window around
@@ -759,26 +729,6 @@ public class ActivityManager {
|| targetStackId == FREEFORM_WORKSPACE_STACK_ID;
}
/**
* Return whether a stackId is a stack that be a backdrop to a translucent activity. These
* are generally fullscreen stacks.
* @hide
*/
public static boolean isBackdropToTranslucentActivity(int stackId) {
return stackId == FULLSCREEN_WORKSPACE_STACK_ID
|| stackId == ASSISTANT_STACK_ID;
}
/**
* Returns true if activities from stasks in the given {@param stackId} are allowed to
* enter picture-in-picture.
* @hide
*/
public static boolean isAllowedToEnterPictureInPicture(int stackId) {
return stackId != HOME_STACK_ID && stackId != ASSISTANT_STACK_ID &&
stackId != RECENTS_STACK_ID;
}
/**
* Returns true if the top task in the task is allowed to return home when finished and
* there are other tasks in the stack.
@@ -810,34 +760,18 @@ public class ActivityManager {
&& stackId != DOCKED_STACK_ID;
}
/**
* Returns true if the input stack id should only be present on a device that supports
* multi-window mode.
* @see android.app.ActivityManager#supportsMultiWindow
* @hide
*/
// TODO: What about the other side of docked stack if we move this to WindowConfiguration?
public static boolean isMultiWindowStack(int stackId) {
return stackId == PINNED_STACK_ID || stackId == FREEFORM_WORKSPACE_STACK_ID
|| stackId == DOCKED_STACK_ID;
}
/**
* Returns true if the input {@param stackId} is HOME_STACK_ID or RECENTS_STACK_ID
* @hide
*/
public static boolean isHomeOrRecentsStack(int stackId) {
return stackId == HOME_STACK_ID || stackId == RECENTS_STACK_ID;
}
/** Returns true if the input stack and its content can affect the device orientation.
/** Returns the stack id for the input windowing mode.
* @hide */
public static boolean canSpecifyOrientation(int stackId) {
return stackId == HOME_STACK_ID
|| stackId == RECENTS_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
|| stackId == ASSISTANT_STACK_ID
|| isDynamicStack(stackId);
// TODO: To be removed once we are not using stack id for stuff...
public static int getStackIdForWindowingMode(int windowingMode) {
switch (windowingMode) {
case WINDOWING_MODE_PINNED: return PINNED_STACK_ID;
case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID;
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID;
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return FULLSCREEN_WORKSPACE_STACK_ID;
case WINDOWING_MODE_FULLSCREEN: return FULLSCREEN_WORKSPACE_STACK_ID;
default: return INVALID_STACK_ID;
}
}
/** Returns the windowing mode that should be used for this input stack id.
@@ -847,14 +781,9 @@ public class ActivityManager {
final int windowingMode;
switch (stackId) {
case FULLSCREEN_WORKSPACE_STACK_ID:
case HOME_STACK_ID:
case RECENTS_STACK_ID:
windowingMode = inSplitScreenMode
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY : WINDOWING_MODE_FULLSCREEN;
break;
case ASSISTANT_STACK_ID:
windowingMode = WINDOWING_MODE_FULLSCREEN;
break;
case PINNED_STACK_ID:
windowingMode = WINDOWING_MODE_PINNED;
break;
@@ -869,51 +798,6 @@ public class ActivityManager {
}
return windowingMode;
}
/** Returns the stack id for the input windowing mode.
* @hide */
// TODO: To be removed once we are not using stack id for stuff...
public static int getStackIdForWindowingMode(int windowingMode) {
switch (windowingMode) {
case WINDOWING_MODE_PINNED: return PINNED_STACK_ID;
case WINDOWING_MODE_FREEFORM: return FREEFORM_WORKSPACE_STACK_ID;
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return DOCKED_STACK_ID;
default: return INVALID_STACK_ID;
}
}
/** Returns the activity type that should be used for this input stack id.
* @hide */
// TODO: To be removed once we are not using stack id for stuff...
public static int getActivityTypeForStackId(int stackId) {
final int activityType;
switch (stackId) {
case HOME_STACK_ID:
activityType = ACTIVITY_TYPE_HOME;
break;
case RECENTS_STACK_ID:
activityType = ACTIVITY_TYPE_RECENTS;
break;
case ASSISTANT_STACK_ID:
activityType = ACTIVITY_TYPE_ASSISTANT;
break;
default :
activityType = ACTIVITY_TYPE_STANDARD;
}
return activityType;
}
/** Returns the stack id for the input activity type.
* @hide */
// TODO: To be removed once we are not using stack id for stuff...
public static int getStackIdForActivityType(int activityType) {
switch (activityType) {
case ACTIVITY_TYPE_HOME: return HOME_STACK_ID;
case ACTIVITY_TYPE_RECENTS: return RECENTS_STACK_ID;
case ACTIVITY_TYPE_ASSISTANT: return ASSISTANT_STACK_ID;
default: return INVALID_STACK_ID;
}
}
}
/**
@@ -1910,6 +1794,12 @@ public class ActivityManager {
*/
public int resizeMode;
/**
* The full configuration the task is currently running in.
* @hide
*/
public Configuration configuration = new Configuration();
public RunningTaskInfo() {
}
@@ -1934,6 +1824,7 @@ public class ActivityManager {
dest.writeInt(numRunning);
dest.writeInt(supportsSplitScreenMultiWindow ? 1 : 0);
dest.writeInt(resizeMode);
configuration.writeToParcel(dest, flags);
}
public void readFromParcel(Parcel source) {
@@ -1951,6 +1842,7 @@ public class ActivityManager {
numRunning = source.readInt();
supportsSplitScreenMultiWindow = source.readInt() != 0;
resizeMode = source.readInt();
configuration.readFromParcel(source);
}
public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
@@ -2132,6 +2024,35 @@ public class ActivityManager {
}
}
/**
* Removes stacks in the windowing modes from the system if they are of activity type
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*
* @hide
*/
@TestApi
public void removeStacksInWindowingModes(int[] windowingModes) throws SecurityException {
try {
getService().removeStacksInWindowingModes(windowingModes);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Removes stack of the activity types from the system.
*
* @hide
*/
@TestApi
public void removeStacksWithActivityTypes(int[] activityTypes) throws SecurityException {
try {
getService().removeStacksWithActivityTypes(activityTypes);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Represents a task snapshot.
* @hide
@@ -2610,6 +2531,11 @@ public class ActivityManager {
public boolean visible;
// Index of the stack in the display's stack list, can be used for comparison of stack order
public int position;
/**
* The full configuration the stack is currently running in.
* @hide
*/
public Configuration configuration = new Configuration();
@Override
public int describeContents() {
@@ -2644,6 +2570,7 @@ public class ActivityManager {
} else {
dest.writeInt(0);
}
configuration.writeToParcel(dest, flags);
}
public void readFromParcel(Parcel source) {
@@ -2671,6 +2598,7 @@ public class ActivityManager {
if (source.readInt() > 0) {
topActivity = ComponentName.readFromParcel(source);
}
configuration.readFromParcel(source);
}
public static final Creator<StackInfo> CREATOR = new Creator<StackInfo>() {
@@ -2698,6 +2626,8 @@ public class ActivityManager {
sb.append(" displayId="); sb.append(displayId);
sb.append(" userId="); sb.append(userId);
sb.append("\n");
sb.append(" configuration="); sb.append(configuration);
sb.append("\n");
prefix = prefix + " ";
for (int i = 0; i < taskIds.length; ++i) {
sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]);

View File

@@ -380,7 +380,8 @@ interface IActivityManager {
boolean preserveWindows, boolean animate, int animationDuration);
List<ActivityManager.StackInfo> getAllStackInfos();
void setFocusedStack(int stackId);
ActivityManager.StackInfo getStackInfo(int stackId);
ActivityManager.StackInfo getFocusedStackInfo();
ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType);
boolean convertFromTranslucent(in IBinder token);
boolean convertToTranslucent(in IBinder token, in Bundle options);
void notifyActivityDrawn(in IBinder token);
@@ -440,7 +441,6 @@ interface IActivityManager {
// Start of M transactions
void notifyCleartextNetwork(int uid, in byte[] firstPacket);
int createStackOnDisplay(int displayId);
int getFocusedStackId();
void setTaskResizeable(int taskId, int resizeableMode);
boolean requestAssistContextExtras(int requestType, in IResultReceiver receiver,
in Bundle receiverExtras, in IBinder activityToken,
@@ -540,6 +540,13 @@ interface IActivityManager {
void notifyPinnedStackAnimationStarted();
void notifyPinnedStackAnimationEnded();
void removeStack(int stackId);
/**
* Removes stacks in the input windowing modes from the system if they are of activity type
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*/
void removeStacksInWindowingModes(in int[] windowingModes);
/** Removes stack of the activity types from the system. */
void removeStacksWithActivityTypes(in int[] activityTypes);
void makePackageIdle(String packageName, int userId);
int getMemoryTrimLevel();
/**

View File

@@ -500,10 +500,15 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* @hide
*/
public boolean supportSplitScreenWindowingMode() {
if (mActivityType == ACTIVITY_TYPE_ASSISTANT) {
return supportSplitScreenWindowingMode(mWindowingMode, mActivityType);
}
/** @hide */
public static boolean supportSplitScreenWindowingMode(int windowingMode, int activityType) {
if (activityType == ACTIVITY_TYPE_ASSISTANT) {
return false;
}
return mWindowingMode != WINDOWING_MODE_FREEFORM && mWindowingMode != WINDOWING_MODE_PINNED;
return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED;
}
private static String windowingModeToString(@WindowingMode int windowingMode) {

View File

@@ -358,10 +358,10 @@ interface IWindowManager
* Updates the dim layer used while resizing.
*
* @param visible Whether the dim layer should be visible.
* @param targetStackId The id of the task stack the dim layer should be placed on.
* @param targetWindowingMode The windowing mode of the stack the dim layer should be placed on.
* @param alpha The translucency of the dim layer, between 0 and 1.
*/
void setResizeDimLayer(boolean visible, int targetStackId, float alpha);
void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha);
/**
* Requests Keyboard Shortcuts from the displayed window.

View File

@@ -592,9 +592,10 @@ public interface WindowManagerPolicy {
int getDockedDividerInsetsLw();
/**
* Retrieves the {@param outBounds} from the stack with id {@param stackId}.
* Retrieves the {@param outBounds} from the stack matching the {@param windowingMode} and
* {@param activityType}.
*/
void getStackBounds(int stackId, Rect outBounds);
void getStackBounds(int windowingMode, int activityType, Rect outBounds);
/**
* Notifies window manager that {@link #isShowingDreamLw} has changed.

View File

@@ -1873,11 +1873,11 @@
<!-- @SystemApi @hide Allows an application to create/manage/remove stacks -->
<permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
android:protectionLevel="signature|privileged" />
android:protectionLevel="signature|privileged|development" />
<!-- @SystemApi @hide Allows an application to embed other activities -->
<permission android:name="android.permission.ACTIVITY_EMBEDDING"
android:protectionLevel="signature|privileged" />
android:protectionLevel="signature|privileged|development" />
<!-- Allows an application to start any activity, regardless of permission
protection or exported state.

View File

@@ -16,6 +16,8 @@
package com.android.keyguard;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.ACTION_USER_UNLOCKED;
import static android.os.BatteryManager.BATTERY_HEALTH_UNKNOWN;
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
@@ -1774,7 +1776,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
public void onTaskStackChangedBackground() {
try {
ActivityManager.StackInfo info = ActivityManager.getService().getStackInfo(
ActivityManager.StackId.ASSISTANT_STACK_ID);
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
if (info == null) {
return;
}

View File

@@ -17,6 +17,8 @@
package com.android.systemui.pip.phone;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
import android.app.ActivityManager;
@@ -199,7 +201,8 @@ public class PipManager implements BasePipManager {
public final void onBusEvent(ExpandPipEvent event) {
if (event.clearThumbnailWindows) {
try {
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
StackInfo stackInfo = mActivityManager.getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (stackInfo != null && stackInfo.taskIds != null) {
SystemServicesProxy ssp = SystemServicesProxy.getInstance(mContext);
for (int taskId : stackInfo.taskIds) {

View File

@@ -17,6 +17,8 @@
package com.android.systemui.pip.phone;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
@@ -383,7 +385,8 @@ public class PipMenuActivityController {
private void startMenuActivity(int menuState, Rect stackBounds, Rect movementBounds,
boolean allowMenuTimeout, boolean willResizeMenu) {
try {
StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
StackInfo pinnedStackInfo = mActivityManager.getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
pinnedStackInfo.taskIds.length > 0) {
Intent intent = new Intent(mContext, PipMenuActivity.class);
@@ -421,7 +424,8 @@ public class PipMenuActivityController {
// Fetch the pinned stack bounds
Rect stackBounds = null;
try {
StackInfo pinnedStackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
StackInfo pinnedStackInfo = mActivityManager.getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (pinnedStackInfo != null) {
stackBounds = pinnedStackInfo.bounds;
}

View File

@@ -18,6 +18,8 @@ package com.android.systemui.pip.phone;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static com.android.systemui.Interpolators.FAST_OUT_LINEAR_IN;
import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.systemui.Interpolators.LINEAR_OUT_SLOW_IN;
@@ -121,7 +123,8 @@ public class PipMotionHelper implements Handler.Callback {
void synchronizePinnedStackBounds() {
cancelAnimations();
try {
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
StackInfo stackInfo =
mActivityManager.getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (stackInfo != null) {
mBounds.set(stackInfo.bounds);
}
@@ -529,7 +532,8 @@ public class PipMotionHelper implements Handler.Callback {
Rect toBounds = (Rect) args.arg1;
int duration = args.argi1;
try {
StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
StackInfo stackInfo = mActivityManager.getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (stackInfo == null) {
// In the case where we've already re-expanded or dismissed the PiP, then
// just skip the resize

View File

@@ -17,6 +17,8 @@
package com.android.systemui.pip.phone;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityManager.StackInfo;
import android.app.IActivityManager;
@@ -38,7 +40,8 @@ public class PipUtils {
IActivityManager activityManager) {
try {
final String sysUiPackageName = context.getPackageName();
final StackInfo pinnedStackInfo = activityManager.getStackInfo(PINNED_STACK_ID);
final StackInfo pinnedStackInfo =
activityManager.getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
pinnedStackInfo.taskIds.length > 0) {
for (int i = pinnedStackInfo.taskNames.length - 1; i >= 0; i--) {

View File

@@ -54,6 +54,8 @@ import java.util.ArrayList;
import java.util.List;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
/**
@@ -502,7 +504,8 @@ public class PipManager implements BasePipManager {
private StackInfo getPinnedStackInfo() {
StackInfo stackInfo = null;
try {
stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
stackInfo = mActivityManager.getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
} catch (RemoteException e) {
Log.e(TAG, "getStackInfo failed", e);
}

View File

@@ -16,6 +16,9 @@
package com.android.systemui.recents;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
import android.app.ActivityManager;
@@ -437,9 +440,12 @@ public class Recents extends SystemUI
int currentUser = sSystemServicesProxy.getCurrentUser();
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
final int activityType = runningTask != null
? runningTask.configuration.windowConfiguration.getActivityType()
: ACTIVITY_TYPE_UNDEFINED;
boolean screenPinningActive = ssp.isScreenPinningActive();
boolean isRunningTaskInHomeOrRecentsStack = runningTask != null &&
ActivityManager.StackId.isHomeOrRecentsStack(runningTask.stackId);
boolean isRunningTaskInHomeOrRecentsStack =
activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS;
if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
if (runningTask.supportsSplitScreenMultiWindow) {

View File

@@ -17,8 +17,8 @@
package com.android.systemui.recents;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.isHomeOrRecentsStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.view.View.MeasureSpec;
import android.app.ActivityManager;
@@ -533,7 +533,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
if (runningTask == null) return;
// Find the task in the recents list
boolean isRunningTaskInHomeStack = SystemServicesProxy.isHomeStack(runningTask.stackId);
boolean isRunningTaskInHomeStack =
runningTask.configuration.windowConfiguration.getActivityType()
== ACTIVITY_TYPE_HOME;
ArrayList<Task> tasks = focusedStack.getStackTasks();
Task toTask = null;
ActivityOptions launchOpts = null;
@@ -583,9 +585,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Return early if there is no running task (can't determine affiliated tasks in this case)
ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
final int activityType = runningTask.configuration.windowConfiguration.getActivityType();
if (runningTask == null) return;
// Return early if the running task is in the home/recents stack (optimization)
if (isHomeOrRecentsStack(runningTask.stackId)) return;
if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) return;
// Find the task in the recents list
ArrayList<Task> tasks = focusedStack.getStackTasks();

View File

@@ -18,12 +18,12 @@ package com.android.systemui.recents.misc;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
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_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -38,6 +38,7 @@ import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -486,16 +487,22 @@ public class SystemServicesProxy {
public ActivityManager.RunningTaskInfo getRunningTask() {
// Note: The set of running tasks from the system is ordered by recency
List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(10);
if (tasks != null && !tasks.isEmpty()) {
// Find the first task in a valid stack, we ignore everything from the Recents and PiP
// stacks
for (int i = 0; i < tasks.size(); i++) {
ActivityManager.RunningTaskInfo task = tasks.get(i);
int stackId = task.stackId;
if (stackId != RECENTS_STACK_ID && stackId != PINNED_STACK_ID) {
return task;
}
if (tasks == null || tasks.isEmpty()) {
return null;
}
// Find the first task in a valid stack, we ignore everything from the Recents and PiP
// stacks
for (int i = 0; i < tasks.size(); i++) {
final ActivityManager.RunningTaskInfo task = tasks.get(i);
final WindowConfiguration winConfig = task.configuration.windowConfiguration;
if (winConfig.getActivityType() == ACTIVITY_TYPE_RECENTS) {
continue;
}
if (winConfig.getWindowingMode() == WINDOWING_MODE_PINNED) {
continue;
}
return task;
}
return null;
}
@@ -522,12 +529,17 @@ public class SystemServicesProxy {
ActivityManager.StackInfo fullscreenStackInfo = null;
ActivityManager.StackInfo recentsStackInfo = null;
for (int i = 0; i < stackInfos.size(); i++) {
StackInfo stackInfo = stackInfos.get(i);
if (stackInfo.stackId == HOME_STACK_ID) {
final StackInfo stackInfo = stackInfos.get(i);
final WindowConfiguration winConfig = stackInfo.configuration.windowConfiguration;
final int activityType = winConfig.getActivityType();
final int windowingMode = winConfig.getWindowingMode();
if (activityType == ACTIVITY_TYPE_HOME) {
homeStackInfo = stackInfo;
} else if (stackInfo.stackId == FULLSCREEN_WORKSPACE_STACK_ID) {
} else if (activityType == ACTIVITY_TYPE_STANDARD
&& (windowingMode == WINDOWING_MODE_FULLSCREEN
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)) {
fullscreenStackInfo = stackInfo;
} else if (stackInfo.stackId == RECENTS_STACK_ID) {
} else if (activityType == ACTIVITY_TYPE_RECENTS) {
recentsStackInfo = stackInfo;
}
}
@@ -605,27 +617,6 @@ public class SystemServicesProxy {
return false;
}
/**
* Returns whether the given stack id is the home stack id.
*/
public static boolean isHomeStack(int stackId) {
return stackId == HOME_STACK_ID;
}
/**
* Returns whether the given stack id is the pinned stack id.
*/
public static boolean isPinnedStack(int stackId){
return stackId == PINNED_STACK_ID;
}
/**
* Returns whether the given stack id is the docked stack id.
*/
public static boolean isDockedStack(int stackId) {
return stackId == DOCKED_STACK_ID;
}
/**
* Returns whether the given stack id is the freeform workspace stack id.
*/
@@ -641,7 +632,8 @@ public class SystemServicesProxy {
ActivityManager.StackInfo stackInfo = null;
try {
stackInfo = mIam.getStackInfo(DOCKED_STACK_ID);
stackInfo =
mIam.getStackInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -1106,9 +1098,10 @@ public class SystemServicesProxy {
try {
// Use the recents stack bounds, fallback to fullscreen stack if it is null
ActivityManager.StackInfo stackInfo = mIam.getStackInfo(RECENTS_STACK_ID);
ActivityManager.StackInfo stackInfo =
mIam.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
if (stackInfo == null) {
stackInfo = mIam.getStackInfo(FULLSCREEN_WORKSPACE_STACK_ID);
stackInfo = mIam.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
}
if (stackInfo != null) {
windowRect.set(stackInfo.bounds);

View File

@@ -16,11 +16,6 @@
package com.android.systemui.recents.views;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -32,7 +27,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECOND
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.annotation.Nullable;
import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.ActivityOptions.OnAnimationStartedListener;
import android.content.Context;

View File

@@ -16,6 +16,9 @@
package com.android.systemui.stackdivider;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
@@ -23,7 +26,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.app.ActivityManager.StackId;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -36,8 +38,6 @@ import android.util.AttributeSet;
import android.view.Choreographer;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.VelocityTracker;
@@ -62,7 +62,6 @@ import com.android.internal.policy.DockedDividerUtils;
import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
@@ -662,7 +661,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
} else {
mWindowManagerProxy.maximizeDockedStack();
}
mWindowManagerProxy.setResizeDimLayer(false, -1, 0f);
mWindowManagerProxy.setResizeDimLayer(false, WINDOWING_MODE_UNDEFINED, 0f);
}
private void liftBackground() {
@@ -998,8 +997,7 @@ public class DividerView extends FrameLayout implements OnTouchListener,
SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position);
float dimFraction = getDimFraction(position, closestDismissTarget);
mWindowManagerProxy.setResizeDimLayer(dimFraction != 0f,
getStackIdForDismissTarget(closestDismissTarget),
dimFraction);
getWindowingModeForDismissTarget(closestDismissTarget), dimFraction);
}
private void applyExitAnimationParallax(Rect taskRect, int position) {
@@ -1133,13 +1131,13 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
}
private int getStackIdForDismissTarget(SnapTarget dismissTarget) {
private int getWindowingModeForDismissTarget(SnapTarget dismissTarget) {
if ((dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide))
|| (dismissTarget.flag == SnapTarget.FLAG_DISMISS_END
&& dockSideBottomRight(mDockSide))) {
return StackId.DOCKED_STACK_ID;
return WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
} else {
return StackId.RECENTS_STACK_ID;
return WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
}

View File

@@ -56,7 +56,7 @@ public class WindowManagerProxy {
private final Rect mTouchableRegion = new Rect();
private boolean mDimLayerVisible;
private int mDimLayerTargetStack;
private int mDimLayerTargetWindowingMode;
private float mDimLayerAlpha;
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
@@ -113,7 +113,7 @@ public class WindowManagerProxy {
public void run() {
try {
WindowManagerGlobal.getWindowManagerService().setResizeDimLayer(mDimLayerVisible,
mDimLayerTargetStack, mDimLayerAlpha);
mDimLayerTargetWindowingMode, mDimLayerAlpha);
} catch (RemoteException e) {
Log.w(TAG, "Failed to resize stack: " + e);
}
@@ -200,9 +200,9 @@ public class WindowManagerProxy {
return DOCKED_INVALID;
}
public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
public void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
mDimLayerVisible = visible;
mDimLayerTargetStack = targetStackId;
mDimLayerTargetWindowingMode = targetWindowingMode;
mDimLayerAlpha = alpha;
mExecutor.execute(mDimLayerRunnable);
}

View File

@@ -21,7 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -107,7 +107,7 @@ class CarNavigationBarController {
}
}
public void taskChanged(String packageName, int stackId) {
public void taskChanged(String packageName, ActivityManager.RunningTaskInfo taskInfo) {
// If the package name belongs to a filter, then highlight appropriate button in
// the navigation bar.
if (mFacetPackageMap.containsKey(packageName)) {
@@ -121,8 +121,9 @@ class CarNavigationBarController {
}
// Set up the persistent docked task if needed.
if (mPersistentTaskIntent != null && !mStatusBar.hasDockedTask()
&& stackId != StackId.HOME_STACK_ID) {
boolean isHomeTask =
taskInfo.configuration.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME;
if (mPersistentTaskIntent != null && !mStatusBar.hasDockedTask() && !isHomeTask) {
mStatusBar.startActivityOnStack(mPersistentTaskIntent,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
}

View File

@@ -314,7 +314,7 @@ public class CarStatusBar extends StatusBar implements
ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getRunningTask();
if (runningTaskInfo != null && runningTaskInfo.baseActivity != null) {
mController.taskChanged(runningTaskInfo.baseActivity.getPackageName(),
runningTaskInfo.stackId);
runningTaskInfo);
}
}
}

View File

@@ -16,8 +16,12 @@
package com.android.systemui.statusbar.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
@@ -523,12 +527,18 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mCurrentNotifs.clear();
mUiOffloadThread.submit(() -> {
try {
int focusedId = ActivityManager.getService().getFocusedStackId();
if (focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID) {
checkStack(StackId.FULLSCREEN_WORKSPACE_STACK_ID, notifs, noMan, pm);
final StackInfo focusedStack = ActivityManager.getService().getFocusedStackInfo();
if (focusedStack != null) {
final int windowingMode =
focusedStack.configuration.windowConfiguration.getWindowingMode();
if (windowingMode == WINDOWING_MODE_FULLSCREEN
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
checkStack(focusedStack, notifs, noMan, pm);
}
}
if (mDockedStackExists) {
checkStack(StackId.DOCKED_STACK_ID, notifs, noMan, pm);
checkStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED,
notifs, noMan, pm);
}
} catch (RemoteException e) {
e.rethrowFromSystemServer();
@@ -539,10 +549,19 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
});
}
private void checkStack(int stackId, ArraySet<Pair<String, Integer>> notifs,
private void checkStack(int windowingMode, int activityType,
ArraySet<Pair<String, Integer>> notifs, NotificationManager noMan, IPackageManager pm) {
try {
final StackInfo info =
ActivityManager.getService().getStackInfo(windowingMode, activityType);
checkStack(info, notifs, noMan, pm);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
private void checkStack(StackInfo info, ArraySet<Pair<String, Integer>> notifs,
NotificationManager noMan, IPackageManager pm) {
try {
StackInfo info = ActivityManager.getService().getStackInfo(stackId);
if (info == null || info.topActivity == null) return;
String pkg = info.topActivity.getPackageName();
if (!hasNotif(notifs, pkg, info.userId)) {

View File

@@ -16,6 +16,19 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
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_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
@@ -27,10 +40,12 @@ import static com.android.server.am.proto.ActivityDisplayProto.STACKS;
import static com.android.server.am.proto.ActivityDisplayProto.ID;
import android.app.ActivityManagerInternal;
import android.app.WindowConfiguration;
import android.util.IntArray;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.ConfigurationContainer;
import java.util.ArrayList;
@@ -129,6 +144,204 @@ class ActivityDisplay extends ConfigurationContainer {
return null;
}
/**
* @return the topmost stack on the display that is compatible with the input windowing mode and
* activity type. {@code null} means no compatible stack on the display.
* @see ConfigurationContainer#isCompatible(int, int)
*/
<T extends ActivityStack> T getStack(int windowingMode, int activityType) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
// TODO: Should undefined windowing and activity type be compatible with standard type?
if (stack.isCompatible(windowingMode, activityType)) {
return (T) stack;
}
}
return null;
}
/**
* @see #getStack(int, int)
* @see #createStack(int, int, boolean)
*/
<T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
boolean onTop) {
T stack = getStack(windowingMode, activityType);
if (stack != null) {
return stack;
}
return createStack(windowingMode, activityType, onTop);
}
/**
* Creates a stack matching the input windowing mode and activity type on this display.
* @param windowingMode The windowing mode the stack should be created in. If
* {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
* be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
* @param activityType The activityType the stack should be created in. If
* {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
* be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
* @param onTop If true the stack will be created at the top of the display, else at the bottom.
* @return The newly created stack.
*/
<T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
if (activityType == ACTIVITY_TYPE_UNDEFINED) {
// Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
// anything else should be passing it in anyways...
activityType = ACTIVITY_TYPE_STANDARD;
}
if (activityType != ACTIVITY_TYPE_STANDARD) {
// For now there can be only one stack of a particular non-standard activity type on a
// display. So, get that ignoring whatever windowing mode it is currently in.
T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
if (stack != null) {
throw new IllegalArgumentException("Stack=" + stack + " of activityType="
+ activityType + " already on display=" + this + ". Can't have multiple.");
}
}
final ActivityManagerService service = mSupervisor.mService;
if (!mSupervisor.isWindowingModeSupported(windowingMode, service.mSupportsMultiWindow,
service.mSupportsSplitScreenMultiWindow, service.mSupportsFreeformWindowManagement,
service.mSupportsPictureInPicture, activityType)) {
throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
+ windowingMode);
}
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
// TODO: Should be okay to have stacks with with undefined windowing mode long term, but
// have to set them to something for now due to logic that depending on them.
windowingMode = WINDOWING_MODE_FULLSCREEN;
}
final boolean inSplitScreenMode = hasSplitScreenStack();
if (!inSplitScreenMode
&& windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
// Switch to fullscreen windowing mode if we are not in split-screen mode and we are
// trying to launch in split-screen secondary.
windowingMode = WINDOWING_MODE_FULLSCREEN;
} else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
&& WindowConfiguration.supportSplitScreenWindowingMode(
windowingMode, activityType)) {
windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
int stackId = INVALID_STACK_ID;
if (mDisplayId == DEFAULT_DISPLAY && (activityType == ACTIVITY_TYPE_STANDARD
|| activityType == ACTIVITY_TYPE_UNDEFINED)) {
// TODO: Will be removed once we are no longer using static stack ids.
stackId = getStackIdForWindowingMode(windowingMode);
if (stackId == INVALID_STACK_ID) {
// Whatever...put in fullscreen stack for now.
stackId = FULLSCREEN_WORKSPACE_STACK_ID;
}
final T stack = getStack(stackId);
if (stack != null) {
return stack;
}
}
if (stackId == INVALID_STACK_ID) {
stackId = mSupervisor.getNextStackId();
}
final T stack = createStackUnchecked(windowingMode, activityType, stackId, onTop);
if (mDisplayId == DEFAULT_DISPLAY && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// Make sure recents stack exist when creating a dock stack as it normally need to be on
// the other side of the docked stack and we make visibility decisions based on that.
// TODO: Not sure if this is needed after we change to calculate visibility based on
// stack z-order vs. id.
getOrCreateStack(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS, onTop);
}
return stack;
}
@VisibleForTesting
<T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
int stackId, boolean onTop) {
switch (windowingMode) {
case WINDOWING_MODE_PINNED:
return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop);
default:
return (T) new ActivityStack(
this, stackId, mSupervisor, windowingMode, activityType, onTop);
}
}
/**
* Removes stacks in the input windowing modes from the system if they are of activity type
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*/
void removeStacksInWindowingModes(int... windowingModes) {
if (windowingModes == null || windowingModes.length == 0) {
return;
}
for (int j = windowingModes.length - 1 ; j >= 0; --j) {
final int windowingMode = windowingModes[j];
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (!stack.isActivityTypeStandardOrUndefined()) {
continue;
}
if (stack.getWindowingMode() != windowingMode) {
continue;
}
mSupervisor.removeStackLocked(stack.mStackId);
}
}
}
void removeStacksWithActivityTypes(int... activityTypes) {
if (activityTypes == null || activityTypes.length == 0) {
return;
}
for (int j = activityTypes.length - 1 ; j >= 0; --j) {
final int activityType = activityTypes[j];
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getActivityType() == activityType) {
mSupervisor.removeStackLocked(stack.mStackId);
}
}
}
}
/** Returns the top visible stack activity type that isn't in the exclude windowing mode. */
int getTopVisibleStackActivityType(int excludeWindowingMode) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getWindowingMode() == excludeWindowingMode) {
continue;
}
if (stack.shouldBeVisible(null /* starting */)) {
return stack.getActivityType();
}
}
return ACTIVITY_TYPE_UNDEFINED;
}
ActivityStack getSplitScreenStack() {
return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
}
boolean hasSplitScreenStack() {
return getSplitScreenStack() != null;
}
PinnedActivityStack getPinnedStack() {
return getStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
}
boolean hasPinnedStack() {
return getPinnedStack() != null;
}
@Override
public String toString() {
return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";

View File

@@ -33,6 +33,13 @@ import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.ActivityManager.StackId.isStaticStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
@@ -164,7 +171,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_URI_PERMI
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
@@ -177,7 +183,6 @@ import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.am.proto.ActivityManagerServiceProto.ACTIVITIES;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH;
import static com.android.server.wm.AppTransition.TRANSIT_NONE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
@@ -2372,11 +2377,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (disableNonVrUi) {
// If we are in a VR mode where Picture-in-Picture mode is unsupported,
// then remove the pinned stack.
final PinnedActivityStack pinnedStack = mStackSupervisor.getStack(
PINNED_STACK_ID);
if (pinnedStack != null) {
mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
}
mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
}
}
} break;
@@ -8105,7 +8106,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final Rect sourceBounds = new Rect(r.pictureInPictureArgs.getSourceRectHint());
mStackSupervisor.moveActivityToPinnedStackLocked(r, sourceBounds, aspectRatio,
true /* moveHomeStackToFront */, "enterPictureInPictureMode");
final PinnedActivityStack stack = mStackSupervisor.getStack(PINNED_STACK_ID);
final PinnedActivityStack stack = r.getStack();
stack.setPictureInPictureAspectRatio(aspectRatio);
stack.setPictureInPictureActions(actions);
@@ -8220,11 +8221,6 @@ public class ActivityManagerService extends IActivityManager.Stub
+ ": Current activity does not support picture-in-picture.");
}
if (!StackId.isAllowedToEnterPictureInPicture(r.getStack().getStackId())) {
throw new IllegalStateException(caller
+ ": Activities on the home, assistant, or recents stack not supported");
}
if (params.hasSetAspectRatio()
&& !mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
params.getAspectRatio())) {
@@ -9862,7 +9858,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (tr.mBounds != null) {
rti.bounds = new Rect(tr.mBounds);
}
rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreen();
rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
rti.resizeMode = tr.mResizeMode;
ActivityRecord base = null;
@@ -10181,21 +10177,23 @@ public class ActivityManagerService extends IActivityManager.Stub
// - a non-null bounds on a non-freeform (fullscreen OR docked) task moves
// that task to freeform
// - otherwise the task is not moved
int stackId = task.getStackId();
ActivityStack stack = task.getStack();
if (!task.getWindowConfiguration().canResizeTask()) {
throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
}
if (bounds == null && stackId == FREEFORM_WORKSPACE_STACK_ID) {
stackId = FULLSCREEN_WORKSPACE_STACK_ID;
} else if (bounds != null && stackId != FREEFORM_WORKSPACE_STACK_ID ) {
stackId = FREEFORM_WORKSPACE_STACK_ID;
if (bounds == null && stack.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
stack = stack.getDisplay().getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), ON_TOP);
} else if (bounds != null && stack.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
stack = stack.getDisplay().getOrCreateStack(
WINDOWING_MODE_FREEFORM, stack.getActivityType(), ON_TOP);
}
// Reparent the task to the right stack if necessary
boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0;
if (stackId != task.getStackId()) {
if (stack != task.getStack()) {
// Defer resume until the task is resized below
task.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
DEFER_RESUME, "resizeTask");
preserveWindow = false;
}
@@ -10368,13 +10366,14 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void removeStack(int stackId) {
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException("Removing home or recents stack is not allowed.");
}
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
final ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack != null && !stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
"Removing non-standard stack is not allowed.");
}
mStackSupervisor.removeStackLocked(stackId);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10382,6 +10381,36 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
/**
* Removes stacks in the input windowing modes from the system if they are of activity type
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*/
@Override
public void removeStacksInWindowingModes(int[] windowingModes) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "removeStacksInWindowingModes()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
mStackSupervisor.removeStacksInWindowingModes(windowingModes);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
@Override
public void removeStacksWithActivityTypes(int[] activityTypes) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "removeStacksWithActivityTypes()");
synchronized (this) {
final long ident = Binder.clearCallingIdentity();
try {
mStackSupervisor.removeStacksWithActivityTypes(activityTypes);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
@Override
public void moveStackToDisplay(int stackId, int displayId) {
enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()");
@@ -10525,13 +10554,15 @@ public class ActivityManagerService extends IActivityManager.Stub
public int createStackOnDisplay(int displayId) throws RemoteException {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createStackOnDisplay()");
synchronized (this) {
final int stackId = mStackSupervisor.getNextStackId();
final ActivityStack stack =
mStackSupervisor.createStackOnDisplay(stackId, displayId, true /*onTop*/);
if (stack == null) {
final ActivityDisplay display =
mStackSupervisor.getActivityDisplayOrCreateLocked(displayId);
if (display == null) {
return INVALID_STACK_ID;
}
return stack.mStackId;
// TODO(multi-display): Have the caller pass in the windowing mode and activity type.
final ActivityStack stack = display.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /*onTop*/);
return (stack != null) ? stack.mStackId : INVALID_STACK_ID;
}
}
@@ -10563,8 +10594,12 @@ public class ActivityManagerService extends IActivityManager.Stub
"exitFreeformMode: You can only go fullscreen from freeform.");
}
final ActivityStack fullscreenStack = stack.getDisplay().getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), ON_TOP);
if (DEBUG_STACK) Slog.d(TAG_STACK, "exitFreeformMode: " + r);
r.getTask().reparent(FULLSCREEN_WORKSPACE_STACK_ID, ON_TOP,
// TODO: Should just change windowing mode vs. re-parenting...
r.getTask().reparent(fullscreenStack, ON_TOP,
REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "exitFreeformMode");
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10575,10 +10610,6 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException(
"moveTaskToStack: Attempt to move task " + taskId + " to stack " + stackId);
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
@@ -10594,8 +10625,25 @@ public class ActivityManagerService extends IActivityManager.Stub
mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
null /* initialBounds */);
}
task.reparent(stackId, toTop,
REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME, "moveTaskToStack");
ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
if (!isStaticStack(stackId)) {
throw new IllegalStateException(
"moveTaskToStack: No stack for stackId=" + stackId);
}
final ActivityDisplay display = task.getStack().getDisplay();
final int windowingMode =
getWindowingModeForStackId(stackId, display.hasSplitScreenStack());
stack = display.getOrCreateStack(windowingMode,
task.getStack().getActivityType(), toTop);
}
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
+ taskId + " to stack " + stackId);
}
task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
"moveTaskToStack");
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10628,13 +10676,18 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.w(TAG, "moveTaskToDockedStack: No task for id=" + taskId);
return false;
}
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
+ " to createMode=" + createMode + " toTop=" + toTop);
mWindowManager.setDockedStackCreateState(createMode, initialBounds);
final ActivityDisplay display = task.getStack().getDisplay();
final ActivityStack stack = display.getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, task.getStack().getActivityType(),
toTop);
// Defer resuming until we move the home stack to the front below
final boolean moved = task.reparent(DOCKED_STACK_ID, toTop,
// TODO: Should just change windowing mode vs. re-parenting...
final boolean moved = task.reparent(stack, toTop,
REPARENT_KEEP_STACK_AT_FRONT, animate, !DEFER_RESUME,
"moveTaskToDockedStack");
if (moved) {
@@ -10682,17 +10735,16 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized (this) {
if (animate) {
if (stackId == PINNED_STACK_ID) {
final PinnedActivityStack pinnedStack =
mStackSupervisor.getStack(PINNED_STACK_ID);
if (pinnedStack != null) {
pinnedStack.animateResizePinnedStack(null /* sourceHintBounds */,
destBounds, animationDuration, false /* fromFullscreen */);
}
} else {
final PinnedActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
return;
}
if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
throw new IllegalArgumentException("Stack: " + stackId
+ " doesn't support animated resize.");
}
stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
animationDuration, false /* fromFullscreen */);
} else {
mStackSupervisor.resizeStackLocked(stackId, destBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, preserveWindows,
@@ -10744,11 +10796,6 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void positionTaskInStack(int taskId, int stackId, int position) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
if (StackId.isHomeOrRecentsStack(stackId)) {
throw new IllegalArgumentException(
"positionTaskInStack: Attempt to change the position of task "
+ taskId + " in/to home/recents stack");
}
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
@@ -10760,8 +10807,16 @@ public class ActivityManagerService extends IActivityManager.Stub
+ taskId);
}
final ActivityStack stack = mStackSupervisor.getStack(stackId, CREATE_IF_NEEDED,
!ON_TOP);
final ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
throw new IllegalArgumentException("positionTaskInStack: no stack for id="
+ stackId);
}
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException("positionTaskInStack: Attempt to change"
+ " the position of task " + taskId + " in/to non-standard stack");
}
// TODO: Have the callers of this API call a separate reparent method if that is
// what they intended to do vs. having this method also do reparenting.
@@ -10770,8 +10825,8 @@ public class ActivityManagerService extends IActivityManager.Stub
stack.positionChildAt(task, position);
} else {
// Reparent to new stack.
task.reparent(stackId, position, REPARENT_LEAVE_STACK_IN_PLACE,
!ANIMATE, !DEFER_RESUME, "positionTaskInStack");
task.reparent(stack, position, REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
!DEFER_RESUME, "positionTaskInStack");
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10793,12 +10848,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
public StackInfo getStackInfo(int stackId) {
public StackInfo getStackInfo(int windowingMode, int activityType) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
return mStackSupervisor.getStackInfoLocked(stackId);
return mStackSupervisor.getStackInfo(windowingMode, activityType);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -10849,11 +10904,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// When a task is locked, dismiss the pinned stack if it exists
final PinnedActivityStack pinnedStack = mStackSupervisor.getStack(
PINNED_STACK_ID);
if (pinnedStack != null) {
mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
}
mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
// isAppPinning is used to distinguish between locked and pinned mode, as pinned mode
// is initiated by system after the pinning request was shown and locked mode is initiated
@@ -20049,12 +20100,20 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
public int getFocusedStackId() throws RemoteException {
ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
return focusedStack.getStackId();
public StackInfo getFocusedStackInfo() throws RemoteException {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
return mStackSupervisor.getStackInfo(focusedStack.mStackId);
}
return null;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
return -1;
}
public Configuration getConfiguration() {
@@ -20080,16 +20139,18 @@ public class ActivityManagerService extends IActivityManager.Stub
* activity and clearing the task at the same time.
*/
@Override
// TODO: API should just be about changing windowing modes...
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
if (StackId.isHomeOrRecentsStack(fromStackId)) {
throw new IllegalArgumentException("You can't move tasks from the home/recents stack.");
}
synchronized (this) {
final long origId = Binder.clearCallingIdentity();
try {
final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
if (stack != null){
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
"You can't move tasks from non-standard stacks.");
}
mStackSupervisor.moveTasksToFullscreenStackLocked(stack, onTop);
}
} finally {

View File

@@ -76,6 +76,7 @@ import static android.app.ActivityManager.RESIZE_MODE_USER;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
@@ -2113,9 +2114,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
}
int runStackInfo(PrintWriter pw) throws RemoteException {
String stackIdStr = getNextArgRequired();
int stackId = Integer.parseInt(stackIdStr);
ActivityManager.StackInfo info = mInterface.getStackInfo(stackId);
int windowingMode = Integer.parseInt(getNextArgRequired());
int activityType = Integer.parseInt(getNextArgRequired());
ActivityManager.StackInfo info = mInterface.getStackInfo(windowingMode, activityType);
pw.println(info);
return 0;
}
@@ -2149,7 +2150,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
final String delayStr = getNextArg();
final int delayMs = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
ActivityManager.StackInfo info = mInterface.getStackInfo(DOCKED_STACK_ID);
ActivityManager.StackInfo info = mInterface.getStackInfo(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
if (info == null) {
err.println("Docked stack doesn't exist");
return -1;
@@ -2252,10 +2254,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runTaskResizeable(pw);
} else if (op.equals("resize")) {
return runTaskResize(pw);
} else if (op.equals("drag-task-test")) {
return runTaskDragTaskTest(pw);
} else if (op.equals("size-task-test")) {
return runTaskSizeTaskTest(pw);
} else if (op.equals("focus")) {
return runTaskFocus(pw);
} else {
@@ -2308,58 +2306,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
}
}
int runTaskDragTaskTest(PrintWriter pw) throws RemoteException {
final int taskId = Integer.parseInt(getNextArgRequired());
final int stepSize = Integer.parseInt(getNextArgRequired());
final String delayStr = getNextArg();
final int delay_ms = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
final ActivityManager.StackInfo stackInfo;
Rect taskBounds;
stackInfo = mInterface.getStackInfo(mInterface.getFocusedStackId());
taskBounds = mInterface.getTaskBounds(taskId);
final Rect stackBounds = stackInfo.bounds;
int travelRight = stackBounds.width() - taskBounds.width();
int travelLeft = -travelRight;
int travelDown = stackBounds.height() - taskBounds.height();
int travelUp = -travelDown;
int passes = 0;
// We do 2 passes to get back to the original location of the task.
while (passes < 2) {
// Move right
pw.println("Moving right...");
pw.flush();
travelRight = moveTask(taskId, taskBounds, stackBounds, stepSize,
travelRight, MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms);
pw.println("Still need to travel right by " + travelRight);
// Move down
pw.println("Moving down...");
pw.flush();
travelDown = moveTask(taskId, taskBounds, stackBounds, stepSize,
travelDown, MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms);
pw.println("Still need to travel down by " + travelDown);
// Move left
pw.println("Moving left...");
pw.flush();
travelLeft = moveTask(taskId, taskBounds, stackBounds, stepSize,
travelLeft, !MOVING_FORWARD, MOVING_HORIZONTALLY, delay_ms);
pw.println("Still need to travel left by " + travelLeft);
// Move up
pw.println("Moving up...");
pw.flush();
travelUp = moveTask(taskId, taskBounds, stackBounds, stepSize,
travelUp, !MOVING_FORWARD, !MOVING_HORIZONTALLY, delay_ms);
pw.println("Still need to travel up by " + travelUp);
taskBounds = mInterface.getTaskBounds(taskId);
passes++;
}
return 0;
}
int moveTask(int taskId, Rect taskRect, Rect stackRect, int stepSize,
int maxToTravel, boolean movingForward, boolean horizontal, int delay_ms)
throws RemoteException {
@@ -2422,133 +2368,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return stepSize;
}
int runTaskSizeTaskTest(PrintWriter pw) throws RemoteException {
final int taskId = Integer.parseInt(getNextArgRequired());
final int stepSize = Integer.parseInt(getNextArgRequired());
final String delayStr = getNextArg();
final int delay_ms = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
final ActivityManager.StackInfo stackInfo;
final Rect initialTaskBounds;
stackInfo = mInterface.getStackInfo(mInterface.getFocusedStackId());
initialTaskBounds = mInterface.getTaskBounds(taskId);
final Rect stackBounds = stackInfo.bounds;
stackBounds.inset(STACK_BOUNDS_INSET, STACK_BOUNDS_INSET);
final Rect currentTaskBounds = new Rect(initialTaskBounds);
// Size by top-left
pw.println("Growing top-left");
pw.flush();
do {
currentTaskBounds.top -= getStepSize(
currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET);
currentTaskBounds.left -= getStepSize(
currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (stackBounds.top < currentTaskBounds.top
|| stackBounds.left < currentTaskBounds.left);
// Back to original size
pw.println("Shrinking top-left");
pw.flush();
do {
currentTaskBounds.top += getStepSize(
currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET);
currentTaskBounds.left += getStepSize(
currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (initialTaskBounds.top > currentTaskBounds.top
|| initialTaskBounds.left > currentTaskBounds.left);
// Size by top-right
pw.println("Growing top-right");
pw.flush();
do {
currentTaskBounds.top -= getStepSize(
currentTaskBounds.top, stackBounds.top, stepSize, GREATER_THAN_TARGET);
currentTaskBounds.right += getStepSize(
currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (stackBounds.top < currentTaskBounds.top
|| stackBounds.right > currentTaskBounds.right);
// Back to original size
pw.println("Shrinking top-right");
pw.flush();
do {
currentTaskBounds.top += getStepSize(
currentTaskBounds.top, initialTaskBounds.top, stepSize, !GREATER_THAN_TARGET);
currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right,
stepSize, GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (initialTaskBounds.top > currentTaskBounds.top
|| initialTaskBounds.right < currentTaskBounds.right);
// Size by bottom-left
pw.println("Growing bottom-left");
pw.flush();
do {
currentTaskBounds.bottom += getStepSize(
currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET);
currentTaskBounds.left -= getStepSize(
currentTaskBounds.left, stackBounds.left, stepSize, GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (stackBounds.bottom > currentTaskBounds.bottom
|| stackBounds.left < currentTaskBounds.left);
// Back to original size
pw.println("Shrinking bottom-left");
pw.flush();
do {
currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom,
initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET);
currentTaskBounds.left += getStepSize(
currentTaskBounds.left, initialTaskBounds.left, stepSize, !GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (initialTaskBounds.bottom < currentTaskBounds.bottom
|| initialTaskBounds.left > currentTaskBounds.left);
// Size by bottom-right
pw.println("Growing bottom-right");
pw.flush();
do {
currentTaskBounds.bottom += getStepSize(
currentTaskBounds.bottom, stackBounds.bottom, stepSize, !GREATER_THAN_TARGET);
currentTaskBounds.right += getStepSize(
currentTaskBounds.right, stackBounds.right, stepSize, !GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (stackBounds.bottom > currentTaskBounds.bottom
|| stackBounds.right > currentTaskBounds.right);
// Back to original size
pw.println("Shrinking bottom-right");
pw.flush();
do {
currentTaskBounds.bottom -= getStepSize(currentTaskBounds.bottom,
initialTaskBounds.bottom, stepSize, GREATER_THAN_TARGET);
currentTaskBounds.right -= getStepSize(currentTaskBounds.right, initialTaskBounds.right,
stepSize, GREATER_THAN_TARGET);
taskResize(taskId, currentTaskBounds, delay_ms, true);
} while (initialTaskBounds.bottom < currentTaskBounds.bottom
|| initialTaskBounds.right < currentTaskBounds.right);
return 0;
}
int runTaskFocus(PrintWriter pw) throws RemoteException {
final int taskId = Integer.parseInt(getNextArgRequired());
pw.println("Setting focus to task " + taskId);
@@ -2880,8 +2699,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" Place <TASK_ID> in <STACK_ID> at <POSITION>");
pw.println(" list");
pw.println(" List all of the activity stacks and their sizes.");
pw.println(" info <STACK_ID>");
pw.println(" Display the information about activity stack <STACK_ID>.");
pw.println(" info <WINDOWING_MODE> <ACTIVITY_TYPE>");
pw.println(" Display the information about activity stack in <WINDOWING_MODE> and <ACTIVITY_TYPE>.");
pw.println(" remove <STACK_ID>");
pw.println(" Remove stack <STACK_ID>.");
pw.println(" task [COMMAND] [...]: sub-commands for operating on activity tasks.");
@@ -2899,14 +2718,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" Makes sure <TASK_ID> is in a stack with the specified bounds.");
pw.println(" Forces the task to be resizeable and creates a stack if no existing stack");
pw.println(" has the specified bounds.");
pw.println(" drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]");
pw.println(" Test command for dragging/moving <TASK_ID> by");
pw.println(" <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]");
pw.println(" between each step.");
pw.println(" size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS]");
pw.println(" Test command for sizing <TASK_ID> by <STEP_SIZE>");
pw.println(" increments within the screen applying the optional [DELAY_MS] between");
pw.println(" each step.");
pw.println(" update-appinfo <USER_ID> <PACKAGE_NAME> [<PACKAGE_NAME>...]");
pw.println(" Update the ApplicationInfo objects of the listed packages for <USER_ID>");
pw.println(" without restarting any processes.");

View File

@@ -2,12 +2,9 @@ package com.android.server.am;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -32,13 +29,10 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_T
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import android.app.ActivityManager.StackId;
import android.content.Context;
import android.metrics.LogMaker;
import android.os.SystemClock;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;

View File

@@ -17,7 +17,6 @@
package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
@@ -103,7 +102,6 @@ import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStack.LAUNCH_TICK;
import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME;
import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
@@ -1069,6 +1067,11 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
return getStack() != null ? getStack().mStackId : INVALID_STACK_ID;
}
ActivityDisplay getDisplay() {
final ActivityStack stack = getStack();
return stack != null ? stack.getDisplay() : null;
}
boolean changeWindowTranslucency(boolean toOpaque) {
if (fullscreen == toOpaque) {
return false;
@@ -1134,10 +1137,12 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
* @return whether this activity supports split-screen multi-window and can be put in the docked
* stack.
*/
boolean supportsSplitScreen() {
@Override
public boolean supportsSplitScreenWindowingMode() {
// An activity can not be docked even if it is considered resizeable because it only
// supports picture-in-picture mode but has a non-resizeable resizeMode
return service.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
return super.supportsSplitScreenWindowingMode()
&& service.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
}
/**
@@ -1198,7 +1203,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
boolean isKeyguardLocked = service.isKeyguardLocked();
boolean isCurrentAppLocked = service.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
final ActivityDisplay display = getDisplay();
boolean hasPinnedStack = display != null && display.hasPinnedStack();
// Don't return early if !isNotLocked, since we want to throw an exception if the activity
// is in an incorrect state
boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
@@ -1544,8 +1550,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
if (service.mSupportsLeanbackOnly && isVisible && isActivityTypeRecents()) {
// On devices that support leanback only (Android TV), Recents activity can only be
// visible if the home stack is the focused stack or we are in split-screen mode.
isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null
|| mStackSupervisor.isFocusedStack(getStack());
final ActivityDisplay display = getDisplay();
boolean hasSplitScreenStack = display != null && display.hasSplitScreenStack();
isVisible = hasSplitScreenStack || mStackSupervisor.isFocusedStack(getStack());
}
return isVisible;

View File

@@ -16,20 +16,19 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.getActivityTypeForStackId;
import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
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_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
@@ -77,7 +76,6 @@ import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
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;
@@ -112,7 +110,6 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -243,11 +240,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
DESTROYED
}
// Stack is not considered visible.
static final int STACK_INVISIBLE = 0;
// Stack is considered visible
static final int STACK_VISIBLE = 1;
@VisibleForTesting
/* The various modes for the method {@link #removeTask}. */
// Task is being completely removed from all stacks in the system.
@@ -461,7 +453,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
boolean onTop) {
int windowingMode, int activityType, boolean onTop) {
mStackSupervisor = supervisor;
mService = supervisor.mService;
mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
@@ -471,7 +463,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
? new LaunchingTaskPositioner() : null;
mTmpRect2.setEmpty();
updateOverrideConfiguration();
setWindowingMode(windowingMode);
setActivityType(activityType);
mWindowContainerController = createStackWindowController(display.mDisplayId, onTop,
mTmpRect2);
postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop);
@@ -485,20 +478,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return mWindowContainerController;
}
// TODO: Not needed once we are no longer using stack ids as the override config. can be passed
// in.
private void updateOverrideConfiguration() {
final int windowingMode = getWindowingModeForStackId(
mStackId, mStackSupervisor.getStack(DOCKED_STACK_ID) != null);
if (windowingMode != WINDOWING_MODE_UNDEFINED) {
setWindowingMode(windowingMode);
}
final int activityType = getActivityTypeForStackId(mStackId);
if (activityType != ACTIVITY_TYPE_UNDEFINED) {
setActivityType(activityType);
}
}
/** Adds the stack to specified display and calls WindowManager to do the same. */
void reparent(ActivityDisplay activityDisplay, boolean onTop) {
removeFromDisplay();
@@ -518,8 +497,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
* @param activityDisplay New display to which this stack was attached.
* @param bounds Updated bounds.
*/
private void postAddToDisplay(ActivityDisplay activityDisplay,
Rect bounds, boolean onTop) {
private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) {
mDisplayId = activityDisplay.mDisplayId;
mBounds = bounds != null ? new Rect(bounds) : null;
mFullscreen = mBounds == null;
@@ -571,12 +549,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return mStackSupervisor.getActivityDisplay(mDisplayId);
}
void getDisplaySize(Point out) {
getDisplay().mDisplay.getSize(out);
}
/**
* @see ActivityStack.getStackDockedModeBounds(Rect, Rect, Rect, boolean)
* @see #getStackDockedModeBounds(Rect, Rect, Rect, boolean)
*/
void getStackDockedModeBounds(Rect currentTempTaskBounds, Rect outStackBounds,
Rect outTempTaskBounds, boolean ignoreVisibility) {
@@ -840,7 +814,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
final boolean isHomeOrRecentsStack() {
return StackId.isHomeOrRecentsStack(mStackId);
return isActivityTypeHome() || isActivityTypeRecents();
}
final boolean isDockedStack() {
@@ -1068,7 +1042,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
"Launch completed; removing icicle of " + r.icicle);
}
private void startLaunchTraces(String packageName) {
if (mFullyDrawnStartTime != 0) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
@@ -1483,7 +1456,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// focus). Also if there is an active pinned stack - we always want to notify it about
// task stack changes, because its positioning may depend on it.
if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
|| mService.mStackSupervisor.getStack(PINNED_STACK_ID) != null) {
|| getDisplay().hasPinnedStack()) {
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
}
@@ -1558,9 +1531,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
final ActivityStack stackBehind = mStackSupervisor.getStack(stackBehindId);
final boolean stackBehindHomeOrRecent = stackBehind != null
&& stackBehind.isHomeOrRecentsStack();
if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()
&& !StackId.isHomeOrRecentsStack(stackBehindId)
&& !isActivityTypeAssistant()) {
&& !stackBehindHomeOrRecent && !isActivityTypeAssistant()) {
// Stack isn't translucent if it's top activity should have the home stack
// behind it and the stack currently behind it isn't the home or recents stack
// or the assistant stack.
@@ -1591,7 +1566,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
final ArrayList<ActivityStack> displayStacks = getDisplay().mStacks;
final ActivityDisplay display = getDisplay();
final ArrayList<ActivityStack> displayStacks = display.mStacks;
final int stackIndex = displayStacks.indexOf(this);
if (stackIndex == displayStacks.size() - 1) {
@@ -1603,8 +1579,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Check position and visibility of this stack relative to the front stack on its display.
final ActivityStack topStack = getTopStackOnDisplay();
final int topStackId = topStack.mStackId;
final int windowingMode = getWindowingMode();
final int activityType = getActivityType();
if (mStackId == DOCKED_STACK_ID) {
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// If the assistant stack is focused and translucent, then the docked stack is always
// visible
if (topStack.isActivityTypeAssistant()) {
@@ -1616,9 +1594,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Set home stack to invisible when it is below but not immediately below the docked stack
// A case would be if recents stack exists but has no tasks and is below the docked stack
// and home stack is below recents
if (mStackId == HOME_STACK_ID) {
int dockedStackIndex = displayStacks.indexOf
(mStackSupervisor.getStack(DOCKED_STACK_ID));
if (activityType == ACTIVITY_TYPE_HOME) {
final ActivityStack splitScreenStack = display.getStack(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
int dockedStackIndex = displayStacks.indexOf(splitScreenStack);
if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
return false;
}
@@ -1630,26 +1609,35 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
displayStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
stackBehindTopIndex--;
}
final int stackBehindTopId = (stackBehindTopIndex >= 0)
? displayStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
final ActivityStack stackBehindTop = (stackBehindTopIndex >= 0)
? displayStacks.get(stackBehindTopIndex) : null;
int stackBehindTopId = INVALID_STACK_ID;
int stackBehindTopWindowingMode = WINDOWING_MODE_UNDEFINED;
int stackBehindTopActivityType = ACTIVITY_TYPE_UNDEFINED;
if (stackBehindTop != null) {
stackBehindTopId = stackBehindTop.mStackId;
stackBehindTopWindowingMode = stackBehindTop.getWindowingMode();
stackBehindTopActivityType = stackBehindTop.getActivityType();
}
final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop();
if (topStackId == DOCKED_STACK_ID || alwaysOnTop) {
if (topStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || alwaysOnTop) {
if (stackIndex == stackBehindTopIndex) {
// Stacks directly behind the docked or pinned stack are always visible.
return true;
} else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) {
// Otherwise, this stack can also be visible if it is directly behind a docked stack
// or translucent assistant stack behind an always-on-top top-most stack
if (stackBehindTopId == DOCKED_STACK_ID) {
if (stackBehindTopWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
return true;
} else if (stackBehindTopId == ASSISTANT_STACK_ID) {
} else if (stackBehindTopActivityType == ACTIVITY_TYPE_ASSISTANT) {
return displayStacks.get(stackBehindTopIndex).isStackTranslucent(
starting, mStackId);
}
}
}
if (StackId.isBackdropToTranslucentActivity(topStackId)
if (topStack.isBackdropToTranslucentActivity()
&& topStack.isStackTranslucent(starting, stackBehindTopId)) {
// Stacks behind the fullscreen or assistant stack with a translucent activity are
// always visible so they can act as a backdrop to the translucent activity.
@@ -1658,8 +1646,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
if (stackBehindTopIndex >= 0) {
if ((stackBehindTopId == DOCKED_STACK_ID
|| stackBehindTopId == PINNED_STACK_ID)
if ((stackBehindTopWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|| stackBehindTopWindowingMode == WINDOWING_MODE_PINNED)
&& stackIndex == (stackBehindTopIndex - 1)) {
// The stack behind the docked or pinned stack is also visible so we can have a
// complete backdrop to the translucent activity when the docked stack is up.
@@ -1668,7 +1656,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
}
if (StackId.isStaticStack(mStackId)) {
if (StackId.isStaticStack(mStackId)
|| isHomeOrRecentsStack() || isActivityTypeAssistant()) {
// Visibility of any static stack should have been determined by the conditions above.
return false;
}
@@ -1680,7 +1669,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
continue;
}
if (!StackId.isDynamicStacksVisibleBehindAllowed(stack.mStackId)) {
if (!stack.isDynamicStacksVisibleBehindAllowed()) {
// These stacks can't have any dynamic stacks visible behind them.
return false;
}
@@ -1693,6 +1682,19 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
private boolean isBackdropToTranslucentActivity() {
if (isActivityTypeAssistant()) {
return true;
}
final int windowingMode = getWindowingMode();
return windowingMode == WINDOWING_MODE_FULLSCREEN
|| windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
private boolean isDynamicStacksVisibleBehindAllowed() {
return isActivityTypeAssistant() || getWindowingMode() == WINDOWING_MODE_PINNED;
}
final int rankTaskLayers(int baseLayer) {
int layer = 0;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -1727,8 +1729,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
boolean aboveTop = top != null;
final boolean stackVisible = shouldBeVisible(starting);
boolean behindFullscreenActivity = !stackVisible;
final boolean stackShouldBeVisible = shouldBeVisible(starting);
boolean behindFullscreenActivity = !stackShouldBeVisible;
boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
&& (isInStackLocked(starting) == null);
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
@@ -1754,7 +1756,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean reallyVisible = checkKeyguardVisibility(r,
visibleIgnoringKeyguard, isTop);
if (visibleIgnoringKeyguard) {
behindFullscreenActivity = updateBehindFullscreen(!stackVisible,
behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible,
behindFullscreenActivity, task, r);
}
if (reallyVisible) {
@@ -1792,7 +1794,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
} else {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+ " finishing=" + r.finishing + " state=" + r.state
+ " stackVisible=" + stackVisible
+ " stackShouldBeVisible=" + stackShouldBeVisible
+ " behindFullscreenActivity=" + behindFullscreenActivity
+ " mLaunchTaskBehind=" + r.mLaunchTaskBehind);
makeInvisible(r);
@@ -1802,10 +1804,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// The visibility of tasks and the activities they contain in freeform stack are
// determined individually unlike other stacks where the visibility or fullscreen
// status of an activity in a previous task affects other.
behindFullscreenActivity = !stackVisible;
} else if (mStackId == HOME_STACK_ID) {
behindFullscreenActivity = !stackShouldBeVisible;
} else if (isActivityTypeHome()) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
+ " stackVisible=" + stackVisible
+ " stackShouldBeVisible=" + stackShouldBeVisible
+ " behindFullscreenActivity=" + behindFullscreenActivity);
// No other task in the home stack should be visible behind the home activity.
// Home activities is usually a translucent activity with the wallpaper behind
@@ -2898,9 +2900,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Ensure that we do not trigger entering PiP an activity on the pinned stack
return false;
}
final int targetStackId = toFrontTask != null ? toFrontTask.getStackId()
: toFrontActivity.getStackId();
if (targetStackId == ASSISTANT_STACK_ID) {
final ActivityStack targetStack = toFrontTask != null
? toFrontTask.getStack() : toFrontActivity.getStack();
if (targetStack != null && targetStack.isActivityTypeAssistant()) {
// Ensure the task/activity being brought forward is not the assistant
return false;
}
@@ -4891,8 +4893,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
ci.numActivities = numActivities;
ci.numRunning = numRunning;
ci.supportsSplitScreenMultiWindow = task.supportsSplitScreen();
ci.supportsSplitScreenMultiWindow = task.supportsSplitScreenWindowingMode();
ci.resizeMode = task.mResizeMode;
ci.configuration = task.getConfiguration();
list.add(ci);
}
}

View File

@@ -27,18 +27,18 @@ import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.app.ActivityManager.StackId.isDynamicStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
@@ -77,7 +77,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.ANIMATE;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -590,9 +589,7 @@ class ActivityStarter {
auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
}
void postStartActivityProcessing(
ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
ActivityStack targetStack) {
void postStartActivityProcessing(ActivityRecord r, int result, ActivityStack targetStack) {
if (ActivityManager.isStartResultFatalError(result)) {
return;
@@ -614,7 +611,8 @@ class ActivityStarter {
}
if (startedActivityStackId == DOCKED_STACK_ID) {
final ActivityStack homeStack = mSupervisor.getStack(HOME_STACK_ID);
final ActivityStack homeStack = mSupervisor.getDefaultDisplay().getStack(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
if (homeStackVisible) {
// We launch an activity while being in home stack, which means either launcher or
@@ -1002,8 +1000,7 @@ class ActivityStarter {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
mTargetStack);
postStartActivityProcessing(r, result, mTargetStack);
return result;
}
@@ -1612,12 +1609,11 @@ class ActivityStarter {
mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "bringingFoundTaskToFront");
mMovedToFront = true;
} else if (launchStack.mStackId == DOCKED_STACK_ID
|| launchStack.mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
} else if (launchStack.inSplitScreenWindowingMode()) {
if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// If we want to launch adjacent and mTargetStack is not the computed
// launch stack - move task to top of computed stack.
intentTask.reparent(launchStack.mStackId, ON_TOP,
intentTask.reparent(launchStack, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"launchToSide");
} else {
@@ -1634,17 +1630,17 @@ class ActivityStarter {
// Target and computed stacks are on different displays and we've
// found a matching task - move the existing instance to that display and
// move it to front.
intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
intentActivity.getTask().reparent(launchStack, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentToDisplay");
mMovedToFront = true;
} else if (launchStack.getStackId() == StackId.HOME_STACK_ID
&& mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
} else if (launchStack.isActivityTypeHome()
&& !mTargetStack.isActivityTypeHome()) {
// It is possible for the home activity to be in another stack initially.
// For example, the activity may have been initially started with an intent
// which placed it in the fullscreen stack. To ensure the proper handling of
// the activity based on home stack assumptions, we must move it over.
intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
intentActivity.getTask().reparent(launchStack, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentingHome");
mMovedToFront = true;
@@ -1879,8 +1875,8 @@ class ActivityStarter {
if (mTargetStack == null) {
mTargetStack = sourceStack;
} else if (mTargetStack != sourceStack) {
sourceTask.reparent(mTargetStack.mStackId, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT,
!ANIMATE, DEFER_RESUME, "launchToSide");
sourceTask.reparent(mTargetStack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
DEFER_RESUME, "launchToSide");
}
final TaskRecord topTask = mTargetStack.topTask();
@@ -1977,15 +1973,16 @@ class ActivityStarter {
if (mLaunchBounds != null) {
mInTask.updateOverrideConfiguration(mLaunchBounds);
// TODO: Shouldn't we already know what stack to use by the time we get here?
int stackId = mSupervisor.getLaunchStackId(null, null, mInTask);
if (stackId != mInTask.getStackId()) {
mInTask.reparent(stackId, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
ActivityStack stack = mSupervisor.getLaunchStack(null, null, mInTask, ON_TOP);
if (stack != mInTask.getStack()) {
mInTask.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, !ANIMATE,
DEFER_RESUME, "inTaskToFront");
stackId = mInTask.getStackId();
stack = mInTask.getStack();
mTargetStack = mInTask.getStack();
}
if (StackId.resizeStackWithLaunchBounds(stackId)) {
mService.resizeStack(stackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
if (StackId.resizeStackWithLaunchBounds(stack.mStackId)) {
mService.resizeStack(
stack.mStackId, mLaunchBounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
}
}
@@ -2116,11 +2113,7 @@ class ActivityStarter {
}
}
// If there is no suitable dynamic stack then we figure out which static stack to use.
final int stackId = task != null ? mSupervisor.getLaunchStackId(r, aOptions, task)
// TODO: This should go in mSupervisor.getLaunchStackId method...
: bounds != null && mService.mSupportsFreeformWindowManagement
? FREEFORM_WORKSPACE_STACK_ID : FULLSCREEN_WORKSPACE_STACK_ID;
stack = mSupervisor.getStack(stackId, CREATE_IF_NEEDED, ON_TOP);
stack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP);
}
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, "computeStackFocus: New stack r="
+ r + " stackId=" + stack.mStackId);
@@ -2128,36 +2121,39 @@ class ActivityStarter {
}
/** Check if provided activity record can launch in currently focused stack. */
// TODO: This method can probably be consolidated into getLaunchStack() below.
private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
final ActivityStack focusedStack = mSupervisor.mFocusedStack;
final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
final boolean canUseFocusedStack;
switch (focusedStackId) {
case FULLSCREEN_WORKSPACE_STACK_ID:
// The fullscreen stack can contain any task regardless of if the task is resizeable
// or not. So, we let the task go in the fullscreen task if it is the focus stack.
canUseFocusedStack = true;
break;
case ASSISTANT_STACK_ID:
canUseFocusedStack = r.isActivityTypeAssistant();
break;
case DOCKED_STACK_ID:
// Any activity which supports split screen can go in the docked stack.
canUseFocusedStack = r.supportsSplitScreen();
break;
case FREEFORM_WORKSPACE_STACK_ID:
// Any activity which supports freeform can go in the freeform stack.
canUseFocusedStack = r.supportsFreeform();
break;
default:
// Dynamic stacks behave similarly to the fullscreen stack and can contain any
// resizeable task.
canUseFocusedStack = isDynamicStack(focusedStackId)
&& r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
if (focusedStack.isActivityTypeAssistant()) {
canUseFocusedStack = r.isActivityTypeAssistant();
} else {
switch (focusedStack.getWindowingMode()) {
case WINDOWING_MODE_FULLSCREEN:
// The fullscreen stack can contain any task regardless of if the task is
// resizeable or not. So, we let the task go in the fullscreen task if it is the
// focus stack.
canUseFocusedStack = true;
break;
case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
// Any activity which supports split screen can go in the docked stack.
canUseFocusedStack = r.supportsSplitScreenWindowingMode();
break;
case WINDOWING_MODE_FREEFORM:
// Any activity which supports freeform can go in the freeform stack.
canUseFocusedStack = r.supportsFreeform();
break;
default:
// Dynamic stacks behave similarly to the fullscreen stack and can contain any
// resizeable task.
canUseFocusedStack = isDynamicStack(focusedStackId)
&& r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
}
}
return canUseFocusedStack && !newTask
// Using the focus stack isn't important enough to override the prefered display.
// Using the focus stack isn't important enough to override the preferred display.
&& (mPreferredDisplayId == focusedStack.mDisplayId);
}
@@ -2168,50 +2164,12 @@ class ActivityStarter {
return mReuseTask.getStack();
}
// If the activity is of a specific type, return the associated stack, creating it if
// necessary
if (r.isActivityTypeHome()) {
return mSupervisor.mHomeStack;
}
if (r.isActivityTypeRecents()) {
return mSupervisor.getStack(RECENTS_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
if (r.isActivityTypeAssistant()) {
return mSupervisor.getStack(ASSISTANT_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY;
final ActivityStack launchStack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
vrDisplayId);
int launchDisplayId = INVALID_DISPLAY;
int launchStackId = INVALID_STACK_ID;
if (aOptions != null) {
launchDisplayId = aOptions.getLaunchDisplayId();
final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY;
launchStackId = mSupervisor.getLaunchStackId(r, aOptions, task, vrDisplayId);
}
// TODO: Will no longer be needed once we are on longer using static stack ids.
if (mSupervisor.isValidLaunchStackId(launchStackId, launchDisplayId, r)) {
return mSupervisor.getStack(launchStackId, CREATE_IF_NEEDED, ON_TOP);
}
if (launchStackId == DOCKED_STACK_ID) {
// The preferred launch stack is the docked stack, but it isn't a valid launch stack
// for this activity, so we put the activity in the fullscreen stack.
return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED, ON_TOP);
}
// TODO: Can probably be removed since ASS.getLaunchStackId() does display resolution.
if (launchDisplayId != INVALID_DISPLAY) {
// Stack id has higher priority than display id.
return mSupervisor.getValidLaunchStackOnDisplay(launchDisplayId, r);
}
// If we are using Vr2d display, find the virtual display stack.
// TODO: Can be removed.
if (mUsingVr2dDisplay) {
ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r);
if (DEBUG_STACK) {
Slog.v(TAG, "Launch stack for app: " + r.toString() +
", on virtual display stack:" + as.toString());
}
return as;
if (launchStack != null) {
return launchStack;
}
if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
@@ -2237,13 +2195,15 @@ class ActivityStarter {
if (parentStack != null && parentStack.isDockedStack()) {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
return mSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID, CREATE_IF_NEEDED,
ON_TOP);
final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
return parentStack.getDisplay().getOrCreateStack(
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, activityType, ON_TOP);
} else {
// If the parent is not in the docked stack, we check if there is docked window
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID);
final ActivityStack dockedStack = mSupervisor.getDefaultDisplay().getStack(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
@@ -2267,15 +2227,6 @@ class ActivityStarter {
mWindowManager = wm;
}
void removePendingActivityLaunchesLocked(ActivityStack stack) {
for (int palNdx = mPendingActivityLaunches.size() - 1; palNdx >= 0; --palNdx) {
PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
if (pal.stack == stack) {
mPendingActivityLaunches.remove(palNdx);
}
}
}
static boolean isDocumentLaunchesIntoExisting(int flags) {
return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0 &&
(flags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0;

View File

@@ -342,7 +342,7 @@ class KeyguardController {
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
final ActivityStack stack = mStackSupervisor.getStack(DOCKED_STACK_ID);
final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
if (stack == null) {
return;
}

View File

@@ -16,6 +16,9 @@
package com.android.server.am;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.RemoteAction;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -34,7 +37,7 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
PinnedActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
boolean onTop) {
super(display, stackId, supervisor, onTop);
super(display, stackId, supervisor, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, onTop);
}
@Override

View File

@@ -54,9 +54,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
public class TaskPersister {

View File

@@ -18,20 +18,19 @@ package com.android.server.am;
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
@@ -573,36 +572,36 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
/**
* Convenience method to reparent a task to the top or bottom position of the stack.
*/
boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
boolean animate, boolean deferResume, String reason) {
return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
deferResume, true /* schedulePictureInPictureModeChange */, reason);
boolean reparent(ActivityStack preferredStack, boolean toTop,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
String reason) {
return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
true /* schedulePictureInPictureModeChange */, reason);
}
/**
* Convenience method to reparent a task to the top or bottom position of the stack, with
* an option to skip scheduling the picture-in-picture mode change.
*/
boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
String reason) {
return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
boolean reparent(ActivityStack preferredStack, boolean toTop,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
deferResume, schedulePictureInPictureModeChange, reason);
}
/**
* Convenience method to reparent a task to a specific position of the stack.
*/
boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
boolean animate, boolean deferResume, String reason) {
return reparent(preferredStackId, position, moveStackMode, animate, deferResume,
/** Convenience method to reparent a task to a specific position of the stack. */
boolean reparent(ActivityStack preferredStack, int position,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
String reason) {
return reparent(preferredStack, position, moveStackMode, animate, deferResume,
true /* schedulePictureInPictureModeChange */, reason);
}
/**
* Reparents the task into a preferred stack, creating it if necessary.
*
* @param preferredStackId the stack id of the target stack to move this task
* @param preferredStack the target stack to move this task
* @param position the position to place this task in the new stack
* @param animate whether or not we should wait for the new window created as a part of the
* reparenting to be drawn and animated in
@@ -616,13 +615,16 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
* @param reason the caller of this reparenting
* @return whether the task was reparented
*/
boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
String reason) {
// TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
// re-parenting the task. Can only be done when we are no longer using static stack Ids like
/** {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} */
boolean reparent(ActivityStack preferredStack, int position,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
final WindowManagerService windowManager = mService.mWindowManager;
final ActivityStack sourceStack = getStack();
final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStackId,
final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
position == MAX_VALUE);
if (toStack == sourceStack) {
return false;
@@ -705,19 +707,22 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
toStack.prepareFreezingTaskBounds();
// Make sure the task has the appropriate bounds/size for the stack it is in.
final int toStackWindowingMode = toStack.getWindowingMode();
final boolean toStackSplitScreenPrimary =
toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
&& !Objects.equals(mBounds, toStack.mBounds)) {
kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
deferResume);
} else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
} else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Rect bounds = getLaunchBounds();
if (bounds == null) {
toStack.layoutTaskInStack(this, null);
bounds = mBounds;
}
kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
} else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
if (stackId == DOCKED_STACK_ID && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
} else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
// Move recents to front so it is not behind home stack when going into docked
// mode
mService.mStackSupervisor.moveRecentsStackToFront(reason);
@@ -744,11 +749,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
// TODO: Handle incorrect request to move before the actual move, not after.
supervisor.handleNonResizableTaskIfNeeded(this, getWindowingModeForStackId(preferredStackId,
supervisor.getStack(DOCKED_STACK_ID) != null), DEFAULT_DISPLAY, stackId);
final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenStack();
supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
DEFAULT_DISPLAY, stackId);
boolean successful = (preferredStackId == stackId);
if (successful && stackId == DOCKED_STACK_ID) {
boolean successful = (preferredStack == toStack);
if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// If task moved to docked stack - show recents if needed.
mService.mWindowManager.showRecentApps(false /* fromHome */);
}
@@ -941,8 +947,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
}
ActivityStack getStack() {
return mStack;
<T extends ActivityStack> T getStack() {
return (T) mStack;
}
/**
@@ -1457,10 +1463,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return isResizeable(true /* checkSupportsPip */);
}
boolean supportsSplitScreen() {
@Override
public boolean supportsSplitScreenWindowingMode() {
// A task can not be docked even if it is considered resizeable because it only supports
// picture-in-picture mode but has a non-resizeable resizeMode
return mService.mSupportsSplitScreenMultiWindow
return super.supportsSplitScreenWindowingMode()
&& mService.mSupportsSplitScreenMultiWindow
&& (mService.mForceResizableActivities
|| (isResizeable(false /* checkSupportsPip */)
&& !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
@@ -2101,12 +2109,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return null;
}
final int stackId = mStack.mStackId;
if (stackId == HOME_STACK_ID
|| stackId == RECENTS_STACK_ID
|| stackId == ASSISTANT_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
|| (stackId == DOCKED_STACK_ID && !isResizeable())) {
final int windowingMode = getWindowingMode();
if (!isActivityTypeStandardOrUndefined()
|| windowingMode == WINDOWING_MODE_FULLSCREEN
|| (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
return isResizeable() ? mStack.mBounds : null;
} else if (!getWindowConfiguration().persistTaskBounds()) {
return mStack.mBounds;

View File

@@ -20,9 +20,12 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
@@ -7917,8 +7920,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds);
mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds);
mWindowManagerFuncs.getStackBounds(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mNonDockedStackBounds);
mWindowManagerFuncs.getStackBounds(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, mDockedStackBounds);
final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int diff = visibility ^ mLastSystemUiFlags;
final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;

View File

@@ -21,8 +21,10 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
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_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.activityTypeToString;
import static com.android.server.wm.proto.ConfigurationContainerProto.FULL_CONFIGURATION;
import static com.android.server.wm.proto.ConfigurationContainerProto.MERGED_OVERRIDE_CONFIGURATION;
@@ -152,6 +154,17 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
onOverrideConfigurationChanged(mTmpConfig);
}
/**
* Returns true if this container is currently in multi-window mode. I.e. sharing the screen
* with another activity.
*/
public boolean inMultiWindowMode() {
/*@WindowConfiguration.WindowingMode*/ int windowingMode =
mFullConfiguration.windowConfiguration.getWindowingMode();
return windowingMode != WINDOWING_MODE_FULLSCREEN
&& windowingMode != WINDOWING_MODE_UNDEFINED;
}
/** Returns true if this container is currently in split-screen windowing mode. */
public boolean inSplitScreenWindowingMode() {
/*@WindowConfiguration.WindowingMode*/ int windowingMode =
@@ -175,7 +188,7 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
* {@link WindowConfiguration##WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} windowing modes based on
* its current state.
*/
public boolean supportSplitScreenWindowingMode() {
public boolean supportsSplitScreenWindowingMode() {
return mFullConfiguration.windowConfiguration.supportSplitScreenWindowingMode();
}
@@ -238,6 +251,16 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
/**
* Returns true if this container is compatible with the input windowing mode and activity type.
* The container is compatible:
* - If {@param activityType} and {@param windowingMode} match this container activity type and
* windowing mode.
* - If {@param activityType} is {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} or
* {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} and this containers activity type is also
* standard or undefined and its windowing mode matches {@param windowingMode}.
* - If {@param activityType} isn't {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} or
* {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} or this containers activity type isn't
* also standard or undefined and its activity type matches {@param activityType} regardless of
* if {@param windowingMode} matches the containers windowing mode.
*/
public boolean isCompatible(int windowingMode, int activityType) {
final int thisActivityType = getActivityType();
@@ -249,7 +272,8 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return true;
}
if (activityType != ACTIVITY_TYPE_UNDEFINED && activityType != ACTIVITY_TYPE_STANDARD) {
if ((activityType != ACTIVITY_TYPE_UNDEFINED && activityType != ACTIVITY_TYPE_STANDARD)
|| !isActivityTypeStandardOrUndefined()) {
// Only activity type need to match for non-standard activity types that are defined.
return sameActivityType;
}

View File

@@ -18,7 +18,6 @@ package com.android.server.wm;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -1470,7 +1469,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* Returns the topmost stack on the display that is compatible with the input windowing mode and
* activity type. Null is no compatible stack on the display.
*/
private TaskStack getStack(int windowingMode, int activityType) {
TaskStack getStack(int windowingMode, int activityType) {
for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
final TaskStack stack = mTaskStackContainers.get(i);
if (stack.isCompatible(windowingMode, activityType)) {
@@ -1486,10 +1485,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
@VisibleForTesting
int getStackPosById(int stackId) {
int getStackPosition(int windowingMode, int activityType) {
for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
final TaskStack stack = mTaskStackContainers.get(i);
if (stack.mStackId == stackId) {
if (stack.isCompatible(windowingMode, activityType)) {
return i;
}
}
@@ -2049,8 +2048,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
final TaskStack stack = mTaskStackContainers.get(i);
final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
if (stack.isVisible() && (imeOnBottom || isDockedOnBottom) &&
StackId.isStackAffectedByDragResizing(stack.mStackId)) {
if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)
&& stack.inSplitScreenWindowingMode()) {
stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
} else {
stack.resetAdjustedForIme(false);
@@ -3379,7 +3378,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* @see WindowManagerService#addStackToDisplay(int, int, boolean)
*/
void addStackToDisplay(TaskStack stack, boolean onTop) {
if (stack.mStackId == HOME_STACK_ID) {
if (stack.isActivityTypeHome()) {
if (mHomeStack != null) {
throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
}

View File

@@ -20,6 +20,7 @@ import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Surface.ROTATION_270;
@@ -331,7 +332,7 @@ public class DockedStackDividerController implements DimLayerUser {
mLastVisibility = visible;
notifyDockedDividerVisibilityChanged(visible);
if (!visible) {
setResizeDimLayer(false, INVALID_STACK_ID, 0f);
setResizeDimLayer(false, WINDOWING_MODE_UNDEFINED, 0f);
}
}
@@ -519,9 +520,18 @@ public class DockedStackDividerController implements DimLayerUser {
}
void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
/**
* Shows a dim layer with {@param alpha} if {@param visible} is true and
* {@param targetWindowingMode} isn't
* {@link android.app.WindowConfiguration#WINDOWING_MODE_UNDEFINED} and there is a stack on the
* display in that windowing mode.
*/
void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
mService.openSurfaceTransaction();
final TaskStack stack = mDisplayContent.getStackById(targetStackId);
// TODO: Maybe only allow split-screen windowing modes?
final TaskStack stack = targetWindowingMode != WINDOWING_MODE_UNDEFINED
? mDisplayContent.getStack(targetWindowingMode)
: null;
final TaskStack dockedStack = mDisplayContent.getDockedStackLocked();
boolean visibleAndValid = visible && stack != null && dockedStack != null;
if (visibleAndValid) {

View File

@@ -16,11 +16,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
/**
* Describes the mode in which a window is drag resizing.
@@ -39,15 +35,12 @@ class DragResizeMode {
*/
static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1;
static boolean isModeAllowedForStack(int stackId, int mode) {
static boolean isModeAllowedForStack(TaskStack stack, int mode) {
switch (mode) {
case DRAG_RESIZE_MODE_FREEFORM:
return stackId == FREEFORM_WORKSPACE_STACK_ID;
return stack.getWindowingMode() == WINDOWING_MODE_FREEFORM;
case DRAG_RESIZE_MODE_DOCKED_DIVIDER:
return stackId == DOCKED_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID
|| stackId == HOME_STACK_ID
|| stackId == RECENTS_STACK_ID;
return stack.inSplitScreenWindowingMode();
default:
return false;
}

View File

@@ -16,7 +16,7 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.util.TypedValue.COMPLEX_UNIT_DIP;
@@ -494,7 +494,7 @@ class PinnedStackController {
pw.println(prefix + "PinnedStackController");
pw.print(prefix + " defaultBounds="); getDefaultBounds().printShortString(pw);
pw.println();
mService.getStackBounds(PINNED_STACK_ID, mTmpRect);
mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
pw.print(prefix + " movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
pw.println();
pw.println(prefix + " mIsImeShowing=" + mIsImeShowing);
@@ -515,7 +515,7 @@ class PinnedStackController {
void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
getDefaultBounds().writeToProto(proto, DEFAULT_BOUNDS);
mService.getStackBounds(PINNED_STACK_ID, mTmpRect);
mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
getMovementBounds(mTmpRect).writeToProto(proto, MOVEMENT_BOUNDS);
proto.end(token);
}

View File

@@ -16,19 +16,16 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
import android.app.RemoteAction;
import android.content.res.Configuration;
import android.graphics.Rect;
import com.android.server.UiThread;
import java.util.List;
/**
@@ -101,7 +98,8 @@ public class PinnedStackWindowController extends StackWindowController {
}
schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpToBounds);
mService.getStackBounds(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds);
if (!mTmpToBounds.isEmpty()) {
// If there is a fullscreen bounds, use that
toBounds = new Rect(mTmpToBounds);

View File

@@ -422,6 +422,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
return null;
}
TaskStack getStack(int windowingMode, int activityType) {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final DisplayContent dc = mChildren.get(i);
final TaskStack stack = dc.getStack(windowingMode, activityType);
if (stack != null) {
return stack;
}
}
return null;
}
void setSecureSurfaceState(int userId, boolean disabled) {
forAllWindows((w) -> {
if (w.mHasSurface && userId == UserHandle.getUserId(w.mOwnerUid)) {

View File

@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSC
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.EMPTY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
@@ -37,7 +38,6 @@ import static com.android.server.wm.proto.TaskProto.TEMP_INSET_BOUNDS;
import static com.android.server.wm.proto.TaskProto.WINDOW_CONTAINER;
import android.annotation.CallSuper;
import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskDescription;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -280,15 +280,9 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
// WindowConfiguration long term.
private int setBounds(Rect bounds, Configuration overrideConfig) {
if (overrideConfig == null) {
overrideConfig = Configuration.EMPTY;
}
if (bounds == null && !Configuration.EMPTY.equals(overrideConfig)) {
throw new IllegalArgumentException("null bounds but non empty configuration: "
+ overrideConfig);
}
if (bounds != null && Configuration.EMPTY.equals(overrideConfig)) {
throw new IllegalArgumentException("non null bounds, but empty configuration");
overrideConfig = EMPTY;
}
boolean oldFullscreen = mFillsParent;
int rotation = Surface.ROTATION_0;
final DisplayContent displayContent = mStack.getDisplayContent();
@@ -323,7 +317,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
if (displayContent != null) {
displayContent.mDimLayerController.updateDimLayer(this);
}
onOverrideConfigurationChanged(mFillsParent ? Configuration.EMPTY : overrideConfig);
onOverrideConfigurationChanged(overrideConfig);
return boundsChange;
}
@@ -406,7 +400,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
* the adjusted bounds's top.
*/
void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
if (!isResizeable() || Configuration.EMPTY.equals(getOverrideConfiguration())) {
if (!isResizeable() || EMPTY.equals(getOverrideConfiguration())) {
return;
}
@@ -531,7 +525,7 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
void setDragResizing(boolean dragResizing, int dragResizeMode) {
if (mDragResizing != dragResizing) {
if (!DragResizeMode.isModeAllowedForStack(mStack.mStackId, dragResizeMode)) {
if (!DragResizeMode.isModeAllowedForStack(mStack, dragResizeMode)) {
throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
+ mStack.mStackId + " dragResizeMode=" + dragResizeMode);
}
@@ -554,7 +548,9 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
return;
}
if (mFillsParent) {
setBounds(null, Configuration.EMPTY);
// TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
// problem once we move mBounds into WindowConfiguration.
setBounds(null, getOverrideConfiguration());
return;
}
final int newRotation = displayContent.getDisplayInfo().rotation;

View File

@@ -254,7 +254,7 @@ class TaskSnapshotController {
@VisibleForTesting
int getSnapshotMode(Task task) {
final AppWindowToken topChild = task.getTopChild();
if (StackId.isHomeOrRecentsStack(task.mStack.mStackId)) {
if (!task.isActivityTypeStandardOrUndefined()) {
return SNAPSHOT_MODE_NONE;
} else if (topChild != null && topChild.shouldUseAppThemeSnapshot()) {
return SNAPSHOT_MODE_APP_THEME;

View File

@@ -19,8 +19,11 @@ package com.android.server.wm;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -44,7 +47,6 @@ import static com.android.server.wm.proto.StackProto.TASKS;
import static com.android.server.wm.proto.StackProto.WINDOW_CONTAINER;
import android.annotation.CallSuper;
import android.app.ActivityManager.StackId;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.Region;
@@ -736,7 +738,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
outTempTaskBounds.setEmpty();
// When the home stack is resizable, should always have the same stack and task bounds
if (mStackId == HOME_STACK_ID) {
if (isActivityTypeHome()) {
final Task homeTask = findHomeTask();
if (homeTask != null && homeTask.isResizeable()) {
// Calculate the home stack bounds when in docked mode and the home stack is
@@ -1008,7 +1010,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
mAdjustImeAmount = 0f;
mAdjustDividerAmount = 0f;
updateAdjustedBounds();
mService.setResizeDimLayer(false, mStackId, 1.0f);
mService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
} else {
mImeGoingAway |= mAdjustedForIme;
}
@@ -1204,7 +1206,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
if (mAdjustedForIme && adjust && !isImeTarget) {
final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
* IME_ADJUST_DIM_AMOUNT;
mService.setResizeDimLayer(true, mStackId, alpha);
mService.setResizeDimLayer(true, getWindowingMode(), alpha);
}
}
@@ -1283,7 +1285,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
@Override
public boolean dimFullscreen() {
return StackId.isHomeOrRecentsStack(mStackId) || fillsParent();
return !isActivityTypeStandard() || fillsParent();
}
@Override
@@ -1663,7 +1665,15 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
@Override
int getOrientation() {
return (StackId.canSpecifyOrientation(mStackId))
? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
}
private boolean canSpecifyOrientation() {
final int windowingMode = getWindowingMode();
final int activityType = getActivityType();
return windowingMode == WINDOWING_MODE_FULLSCREEN
|| activityType == ACTIVITY_TYPE_HOME
|| activityType == ACTIVITY_TYPE_RECENTS
|| activityType == ACTIVITY_TYPE_ASSISTANT;
}
}

View File

@@ -21,11 +21,8 @@ import android.util.Slog;
import java.util.ArrayDeque;
import java.util.function.Consumer;
import static android.app.ActivityManager.StackId;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
@@ -187,12 +184,13 @@ class WindowLayersController {
}
}
final int stackId = w.getAppToken() != null ? w.getStackId() : INVALID_STACK_ID;
if (stackId == PINNED_STACK_ID) {
final int windowingMode = w.getWindowingMode();
if (windowingMode == WINDOWING_MODE_PINNED) {
mPinnedWindows.add(w);
} else if (stackId == DOCKED_STACK_ID) {
} else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mDockedWindows.add(w);
} else if (stackId == ASSISTANT_STACK_ID) {
}
if (w.isActivityTypeAssistant()) {
mAssistantWindows.add(w);
}
}

View File

@@ -2905,9 +2905,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
public void getStackBounds(int stackId, Rect bounds) {
public void getStackBounds(int windowingMode, int activityType, Rect bounds) {
synchronized (mWindowMap) {
final TaskStack stack = mRoot.getStackById(stackId);
final TaskStack stack = mRoot.getStack(windowingMode, activityType);
if (stack != null) {
stack.getBounds(bounds);
return;
@@ -7151,10 +7151,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
public void setResizeDimLayer(boolean visible, int targetStackId, float alpha) {
public void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
synchronized (mWindowMap) {
getDefaultDisplayContentLocked().getDockedDividerController().setResizeDimLayer(
visible, targetStackId, alpha);
visible, targetWindowingMode, alpha);
}
}

View File

@@ -3088,7 +3088,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (task == null) {
return false;
}
if (!StackId.isStackAffectedByDragResizing(getStackId())) {
if (!inSplitScreenWindowingMode()) {
return false;
}
if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) {

View File

@@ -16,9 +16,15 @@
package com.android.server.am;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static android.view.WindowManagerPolicy.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicy.NAV_BAR_RIGHT;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -26,14 +32,13 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.Display;
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
/**
@@ -46,64 +51,53 @@ import org.junit.Test;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class ActivityRecordTests extends ActivityTestsBase {
private static final int TEST_STACK_ID = 100;
private final ComponentName testActivityComponent =
ComponentName.unflattenFromString("com.foo/.BarActivity");
private final ComponentName secondaryActivityComponent =
ComponentName.unflattenFromString("com.foo/.BarActivity2");
private ActivityManagerService mService;
private ActivityStack mStack;
private TaskRecord mTask;
private ActivityRecord mActivity;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
mService = createActivityManagerService();
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask = createTask(mService.mStackSupervisor, testActivityComponent, mStack);
mActivity = createActivity(mService, testActivityComponent, mTask);
}
@Test
public void testStackCleanupOnClearingTask() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
record.setTask(null);
assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 1);
mActivity.setTask(null);
assertEquals(getActivityRemovedFromStackCount(), 1);
}
@Test
public void testStackCleanupOnActivityRemoval() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
task.removeActivity(record);
assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 1);
mTask.removeActivity(mActivity);
assertEquals(getActivityRemovedFromStackCount(), 1);
}
@Test
public void testStackCleanupOnTaskRemoval() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
service.mStackSupervisor.getStack(TEST_STACK_ID)
.removeTask(task, null /*reason*/, ActivityStack.REMOVE_TASK_MODE_MOVING);
mStack.removeTask(mTask, null /*reason*/, REMOVE_TASK_MODE_MOVING);
// Stack should be gone on task removal.
assertNull(service.mStackSupervisor.getStack(TEST_STACK_ID));
assertNull(mService.mStackSupervisor.getStack(mStack.mStackId));
}
@Test
public void testNoCleanupMovingActivityInSameStack() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord oldTask = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, oldTask);
final TaskRecord newTask = createTask(service, testActivityComponent, TEST_STACK_ID);
record.reparent(newTask, 0, null /*reason*/);
assertEquals(getActivityRemovedFromStackCount(service, TEST_STACK_ID), 0);
}
private static int getActivityRemovedFromStackCount(ActivityManagerService service,
int stackId) {
final ActivityStack stack = service.mStackSupervisor.getStack(stackId);
if (stack instanceof ActivityStackReporter) {
return ((ActivityStackReporter) stack).onActivityRemovedFromStackInvocationCount();
}
return -1;
final TaskRecord newTask =
createTask(mService.mStackSupervisor, testActivityComponent, mStack);
mActivity.reparent(newTask, 0, null /*reason*/);
assertEquals(getActivityRemovedFromStackCount(), 0);
}
@Test
@@ -126,16 +120,21 @@ public class ActivityRecordTests extends ActivityTestsBase {
private void verifyPositionWithLimitedAspectRatio(int navBarPosition, Rect taskBounds,
float aspectRatio, Rect expectedActivityBounds) {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord record = createActivity(service, testActivityComponent, task);
// Verify with nav bar on the right.
when(service.mWindowManager.getNavBarPosition()).thenReturn(navBarPosition);
task.getConfiguration().windowConfiguration.setAppBounds(taskBounds);
record.info.maxAspectRatio = aspectRatio;
record.ensureActivityConfigurationLocked(0 /* globalChanges */, false /* preserveWindow */);
assertEquals(expectedActivityBounds, record.getBounds());
when(mService.mWindowManager.getNavBarPosition()).thenReturn(navBarPosition);
mTask.getConfiguration().windowConfiguration.setAppBounds(taskBounds);
mActivity.info.maxAspectRatio = aspectRatio;
mActivity.ensureActivityConfigurationLocked(
0 /* globalChanges */, false /* preserveWindow */);
assertEquals(expectedActivityBounds, mActivity.getBounds());
}
private int getActivityRemovedFromStackCount() {
if (mStack instanceof ActivityStackReporter) {
return ((ActivityStackReporter) mStack).onActivityRemovedFromStackInvocationCount();
}
return -1;
}
@@ -156,26 +155,22 @@ public class ActivityRecordTests extends ActivityTestsBase {
private void testSupportsLaunchingResizeable(boolean taskPresent, boolean taskResizeable,
boolean activityResizeable, boolean expected) {
final ActivityManagerService service = createActivityManagerService();
service.mSupportsMultiWindow = true;
mService.mSupportsMultiWindow = true;
final TaskRecord task = taskPresent
? createTask(service, testActivityComponent, TEST_STACK_ID) : null;
? createTask(mService.mStackSupervisor, testActivityComponent, mStack) : null;
if (task != null) {
task.setResizeMode(taskResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE
: ActivityInfo.RESIZE_MODE_UNRESIZEABLE);
task.setResizeMode(taskResizeable ? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE);
}
final ActivityRecord record = createActivity(service, secondaryActivityComponent,
task);
record.info.resizeMode = activityResizeable ? ActivityInfo.RESIZE_MODE_RESIZEABLE
: ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
final ActivityRecord record = createActivity(mService, secondaryActivityComponent, task);
record.info.resizeMode = activityResizeable
? RESIZE_MODE_RESIZEABLE : RESIZE_MODE_UNRESIZEABLE;
record.canBeLaunchedOnDisplay(Display.DEFAULT_DISPLAY);
record.canBeLaunchedOnDisplay(DEFAULT_DISPLAY);
assertEquals(((TestActivityStackSupervisor) service.mStackSupervisor)
assertEquals(((TestActivityStackSupervisor) mService.mStackSupervisor)
.getLastResizeableFromCanPlaceEntityOnDisplay(), expected);
}
}

View File

@@ -16,11 +16,10 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
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_PINNED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -33,6 +32,7 @@ import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
@@ -54,6 +54,21 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
private final ComponentName testActivityComponent =
ComponentName.unflattenFromString("com.foo/.BarActivity");
private ActivityManagerService mService;
private ActivityStackSupervisor mSupervisor;
private ActivityStack mFullscreenStack;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
mService = createActivityManagerService();
mSupervisor = mService.mStackSupervisor;
mFullscreenStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
}
/**
* This test ensures that we do not try to restore a task based off an invalid task id. The
* stack supervisor is a test version so there will be no tasks present. We should expect
@@ -61,8 +76,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
*/
@Test
public void testRestoringInvalidTask() throws Exception {
final ActivityManagerService service = createActivityManagerService();
TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
TaskRecord task = mSupervisor.anyTaskForIdLocked(0 /*taskId*/,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, null);
assertNull(task);
}
@@ -73,43 +87,44 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
*/
@Test
public void testReplacingTaskInPinnedStack() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord firstTask = createTask(service, testActivityComponent,
FULLSCREEN_WORKSPACE_STACK_ID);
final ActivityRecord firstActivity = createActivity(service, testActivityComponent,
final TaskRecord firstTask = createTask(
mSupervisor, testActivityComponent, mFullscreenStack);
final ActivityRecord firstActivity = createActivity(mService, testActivityComponent,
firstTask);
// Create a new task on the full screen stack
final TaskRecord secondTask = createTask(service, testActivityComponent,
FULLSCREEN_WORKSPACE_STACK_ID);
final ActivityRecord secondActivity = createActivity(service, testActivityComponent,
final TaskRecord secondTask = createTask(
mSupervisor, testActivityComponent, mFullscreenStack);
final ActivityRecord secondActivity = createActivity(mService, testActivityComponent,
secondTask);
service.mStackSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack",
service.mStackSupervisor.getStack(FULLSCREEN_WORKSPACE_STACK_ID));
mSupervisor.setFocusStackUnchecked("testReplacingTaskInPinnedStack", mFullscreenStack);
// Ensure full screen stack has both tasks.
ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask,
secondTask);
ensureStackPlacement(mFullscreenStack, firstTask, secondTask);
// Move first activity to pinned stack.
service.mStackSupervisor.moveActivityToPinnedStackLocked(firstActivity,
new Rect() /*sourceBounds*/, 0f /*aspectRatio*/, false, "initialMove");
final Rect sourceBounds = new Rect();
mSupervisor.moveActivityToPinnedStackLocked(firstActivity, sourceBounds,
0f /*aspectRatio*/, false, "initialMove");
final ActivityDisplay display = mFullscreenStack.getDisplay();
ActivityStack pinnedStack = display.getPinnedStack();
// Ensure a task has moved over.
ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, firstTask);
ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, secondTask);
ensureStackPlacement(pinnedStack, firstTask);
ensureStackPlacement(mFullscreenStack, secondTask);
// Move second activity to pinned stack.
service.mStackSupervisor.moveActivityToPinnedStackLocked(secondActivity,
new Rect() /*sourceBounds*/, 0f /*aspectRatio*/ /*destBounds*/, false, "secondMove");
mSupervisor.moveActivityToPinnedStackLocked(secondActivity, sourceBounds,
0f /*aspectRatio*/, false, "secondMove");
// Need to get pinned stack again as a new instance might have been created.
pinnedStack = display.getPinnedStack();
// Ensure stacks have swapped tasks.
ensureStackPlacement(service.mStackSupervisor, PINNED_STACK_ID, secondTask);
ensureStackPlacement(service.mStackSupervisor, FULLSCREEN_WORKSPACE_STACK_ID, firstTask);
ensureStackPlacement(pinnedStack, secondTask);
ensureStackPlacement(mFullscreenStack, firstTask);
}
private static void ensureStackPlacement(ActivityStackSupervisor supervisor, int stackId,
TaskRecord... tasks) {
final ActivityStack stack = supervisor.getStack(stackId);
private static void ensureStackPlacement(ActivityStack stack, TaskRecord... tasks) {
final ArrayList<TaskRecord> stackTasks = stack.getAllTasks();
assertEquals(stackTasks.size(), tasks != null ? tasks.length : 0);
@@ -127,15 +142,14 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
*/
@Test
public void testStoppingActivityRemovedWhenResumed() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord firstTask = createTask(service, testActivityComponent,
FULLSCREEN_WORKSPACE_STACK_ID);
final ActivityRecord firstActivity = createActivity(service, testActivityComponent,
final TaskRecord firstTask = createTask(
mSupervisor, testActivityComponent, mFullscreenStack);
final ActivityRecord firstActivity = createActivity(mService, testActivityComponent,
firstTask);
service.mStackSupervisor.mStoppingActivities.add(firstActivity);
mSupervisor.mStoppingActivities.add(firstActivity);
firstActivity.completeResumeLocked();
assertFalse(service.mStackSupervisor.mStoppingActivities.contains(firstActivity));
assertFalse(mSupervisor.mStoppingActivities.contains(firstActivity));
}
}

View File

@@ -16,12 +16,14 @@
package com.android.server.am;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
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 android.app.ActivityManager;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.os.UserHandle;
@@ -30,6 +32,7 @@ import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.runner.RunWith;
import org.junit.Before;
import org.junit.Test;
/**
@@ -48,78 +51,80 @@ public class ActivityStackTests extends ActivityTestsBase {
private static final ComponentName testOverlayComponent =
ComponentName.unflattenFromString("com.foo/.OverlayActivity");
private ActivityManagerService mService;
private ActivityStackSupervisor mSupervisor;
private ActivityStack mStack;
private TaskRecord mTask;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
mService = createActivityManagerService();
mSupervisor = mService.mStackSupervisor;
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
mTask = createTask(mSupervisor, testActivityComponent, mStack);
}
@Test
public void testEmptyTaskCleanupOnRemove() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
assertNotNull(task.getWindowContainerController());
service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
"testEmptyTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
assertNull(task.getWindowContainerController());
assertNotNull(mTask.getWindowContainerController());
mStack.removeTask(mTask, "testEmptyTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
assertNull(mTask.getWindowContainerController());
}
@Test
public void testOccupiedTaskCleanupOnRemove() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
assertNotNull(task.getWindowContainerController());
service.mStackSupervisor.getStack(TEST_STACK_ID).removeTask(task,
"testOccupiedTaskCleanupOnRemove", ActivityStack.REMOVE_TASK_MODE_DESTROYING);
assertNotNull(task.getWindowContainerController());
final ActivityRecord r = createActivity(mService, testActivityComponent, mTask);
assertNotNull(mTask.getWindowContainerController());
mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
assertNotNull(mTask.getWindowContainerController());
}
@Test
public void testNoPauseDuringResumeTopActivity() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID);
final ActivityRecord r = createActivity(mService, testActivityComponent, mTask);
// Simulate the a resumed activity set during
// {@link ActivityStack#resumeTopActivityUncheckedLocked}.
service.mStackSupervisor.inResumeTopActivity = true;
testStack.mResumedActivity = activityRecord;
mSupervisor.inResumeTopActivity = true;
mStack.mResumedActivity = r;
final boolean waiting = testStack.goToSleepIfPossible(false);
final boolean waiting = mStack.goToSleepIfPossible(false);
// Ensure we report not being ready for sleep.
assertFalse(waiting);
// Make sure the resumed activity is untouched.
assertEquals(testStack.mResumedActivity, activityRecord);
assertEquals(mStack.mResumedActivity, r);
}
@Test
public void testStopActivityWhenActivityDestroyed() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task);
activityRecord.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID);
service.mStackSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", testStack);
testStack.stopActivityLocked(activityRecord);
final ActivityRecord r = createActivity(mService, testActivityComponent, mTask);
r.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
mSupervisor.setFocusStackUnchecked("testStopActivityWithDestroy", mStack);
mStack.stopActivityLocked(r);
// Mostly testing to make sure there is a crash in the call part, so if we get here we are
// good-to-go!
}
@Test
public void testFindTaskWithOverlay() throws Exception {
final ActivityManagerService service = createActivityManagerService();
final TaskRecord task = createTask(service, testActivityComponent, TEST_STACK_ID);
final ActivityRecord activityRecord = createActivity(service, testActivityComponent, task,
0);
final ActivityRecord r = createActivity(mService, testActivityComponent, mTask, 0);
// Overlay must be for a different user to prevent recognizing a matching top activity
final ActivityRecord taskOverlay = createActivity(service, testOverlayComponent, task,
final ActivityRecord taskOverlay = createActivity(mService, testOverlayComponent, mTask,
UserHandle.PER_USER_RANGE * 2);
taskOverlay.mTaskOverlay = true;
final ActivityStack testStack = service.mStackSupervisor.getStack(TEST_STACK_ID);
final ActivityStackSupervisor.FindTaskResult result =
new ActivityStackSupervisor.FindTaskResult();
testStack.findTaskLocked(activityRecord, result);
mStack.findTaskLocked(r, result);
assertEquals(task.getTopActivity(false /* includeOverlays */), activityRecord);
assertEquals(task.getTopActivity(true /* includeOverlays */), taskOverlay);
assertEquals(mTask.getTopActivity(false /* includeOverlays */), r);
assertEquals(mTask.getTopActivity(true /* includeOverlays */), taskOverlay);
assertNotNull(result.r);
}
}

View File

@@ -16,7 +16,7 @@
package com.android.server.am;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.doReturn;
@@ -76,16 +76,6 @@ public class ActivityTestsBase {
return service;
}
protected static ActivityStack createActivityStack(ActivityManagerService service,
int stackId, int displayId, boolean onTop) {
if (service.mStackSupervisor instanceof TestActivityStackSupervisor) {
return ((TestActivityStackSupervisor) service.mStackSupervisor)
.createTestStack(stackId, onTop);
}
return null;
}
protected static ActivityRecord createActivity(ActivityManagerService service,
ComponentName component, TaskRecord task) {
return createActivity(service, component, task, 0 /* userId */);
@@ -114,8 +104,8 @@ public class ActivityTestsBase {
return activity;
}
protected static TaskRecord createTask(ActivityManagerService service,
ComponentName component, int stackId) {
protected static TaskRecord createTask(ActivityStackSupervisor supervisor,
ComponentName component, ActivityStack stack) {
final ActivityInfo aInfo = new ActivityInfo();
aInfo.applicationInfo = new ApplicationInfo();
aInfo.applicationInfo.packageName = component.getPackageName();
@@ -123,11 +113,9 @@ public class ActivityTestsBase {
Intent intent = new Intent();
intent.setComponent(component);
final TaskRecord task = new TaskRecord(service, 0, aInfo, intent /*intent*/,
final TaskRecord task = new TaskRecord(supervisor.mService, 0, aInfo, intent /*intent*/,
null /*_taskDescription*/);
final ActivityStack stack = service.mStackSupervisor.getStack(stackId,
true /*createStaticStackIfNeeded*/, true /*onTop*/);
service.mStackSupervisor.setFocusStackUnchecked("test", stack);
supervisor.setFocusStackUnchecked("test", stack);
stack.addTask(task, true, "creating test task");
task.setStack(stack);
task.setWindowContainerController(mock(TaskWindowContainerController.class));
@@ -135,16 +123,18 @@ public class ActivityTestsBase {
return task;
}
/**
* An {@link ActivityManagerService} subclass which provides a test
* {@link ActivityStackSupervisor}.
*/
protected static class TestActivityManagerService extends ActivityManagerService {
public TestActivityManagerService(Context context) {
TestActivityManagerService(Context context) {
super(context);
mSupportsMultiWindow = true;
mSupportsMultiDisplay = true;
mSupportsSplitScreenMultiWindow = true;
mSupportsFreeformWindowManagement = true;
mSupportsPictureInPicture = true;
mWindowManager = WindowTestUtils.getWindowManagerService(context);
}
@@ -171,10 +161,15 @@ public class ActivityTestsBase {
mDisplayManager =
(DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
mWindowManager = prepareMockWindowManager();
mDisplay = new ActivityDisplay(this, DEFAULT_DISPLAY);
mDisplay = new TestActivityDisplay(this, DEFAULT_DISPLAY);
attachDisplay(mDisplay);
}
@Override
ActivityDisplay getDefaultDisplay() {
return mDisplay;
}
// TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor
// access to ActivityDisplay
@Override
@@ -218,41 +213,36 @@ public class ActivityTestsBase {
boolean preserveWindows) {
}
<T extends ActivityStack> T createTestStack(int stackId, boolean onTop) {
return (T) createStack(stackId, mDisplay, onTop);
// Always keep things awake
@Override
boolean hasAwakeDisplay() {
return true;
}
}
private static class TestActivityDisplay extends ActivityDisplay {
private final ActivityStackSupervisor mSupervisor;
TestActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
super(supervisor, displayId);
mSupervisor = supervisor;
}
@Override
ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) {
if (stackId == PINNED_STACK_ID) {
return new PinnedActivityStack(display, stackId, this, onTop) {
<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);
}
};
} else {
return new TestActivityStack(display, stackId, this, onTop);
return (T) new TestActivityStack(
this, stackId, mSupervisor, windowingMode, activityType, onTop);
}
}
@Override
protected <T extends ActivityStack> T getStack(int stackId,
boolean createStaticStackIfNeeded, boolean createOnTop) {
final T stack = super.getStack(stackId, createStaticStackIfNeeded, createOnTop);
if (stack != null || !createStaticStackIfNeeded) {
return stack;
}
return createTestStack(stackId, createOnTop);
}
// Always keep things awake
@Override
boolean hasAwakeDisplay() {
return true;
}
}
private static WindowManagerService prepareMockWindowManager() {
@@ -282,9 +272,10 @@ public class ActivityTestsBase {
extends ActivityStack<T> implements ActivityStackReporter {
private int mOnActivityRemovedFromStackCount = 0;
private T mContainerController;
TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
boolean onTop) {
super(display, stackId, supervisor, onTop);
int windowingMode, int activityType, boolean onTop) {
super(display, stackId, supervisor, windowingMode, activityType, onTop);
}
@Override
@@ -310,36 +301,4 @@ public class ActivityTestsBase {
return mContainerController;
}
}
protected static class ActivityStackBuilder {
private boolean mOnTop = true;
private int mStackId = 0;
private int mDisplayId = 1;
private final ActivityManagerService mService;
public ActivityStackBuilder(ActivityManagerService ams) {
mService = ams;
}
public ActivityStackBuilder setOnTop(boolean onTop) {
mOnTop = onTop;
return this;
}
public ActivityStackBuilder setStackId(int id) {
mStackId = id;
return this;
}
public ActivityStackBuilder setDisplayId(int id) {
mDisplayId = id;
return this;
}
public ActivityStack build() {
return createActivityStack(mService, mStackId, mDisplayId, mOnTop);
}
}
}

View File

@@ -16,7 +16,8 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -347,17 +348,20 @@ public class DisplayContentTests extends WindowTestsBase {
*/
@Test
public void testPinnedStackLocation() {
createStackControllerOnStackOnDisplay(PINNED_STACK_ID, mDisplayContent);
createStackControllerOnStackOnDisplay(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final int initialStackCount = mDisplayContent.getStackCount();
// Ensure that the pinned stack was placed at the end
assertEquals(initialStackCount - 1, mDisplayContent.getStackPosById(PINNED_STACK_ID));
assertEquals(initialStackCount - 1,
mDisplayContent.getStackPosition(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD));
// By default, this should try to create a new stack on top
createTaskStackOnDisplay(mDisplayContent);
final int afterStackCount = mDisplayContent.getStackCount();
// Make sure the stack count has increased
assertEquals(initialStackCount + 1, afterStackCount);
// Ensure that the pinned stack is still on top
assertEquals(afterStackCount - 1, mDisplayContent.getStackPosById(PINNED_STACK_ID));
assertEquals(afterStackCount - 1,
mDisplayContent.getStackPosition(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD));
}
/**

View File

@@ -29,7 +29,7 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -53,8 +53,7 @@ public class TaskStackContainersTests extends WindowTestsBase {
public void setUp() throws Exception {
super.setUp();
final Configuration overrideConfig = new Configuration();
overrideConfig.windowConfiguration.setWindowingMode(
getWindowingModeForStackId(PINNED_STACK_ID, false /* inSplitScreenMode */));
overrideConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_PINNED);
mPinnedStack = new StackWindowController(PINNED_STACK_ID, null,
mDisplayContent.getDisplayId(), true /* onTop */, new Rect(), sWm).mContainer;
mPinnedStack.onOverrideConfigurationChanged(overrideConfig);

View File

@@ -26,10 +26,10 @@ import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.DisplayInfo;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
@@ -155,7 +155,7 @@ public class WindowConfigurationTests extends WindowTestsBase {
shiftedBounds.offset(10, 10);
final Rect expectedBounds = new Rect(mParentBounds);
expectedBounds.intersect(shiftedBounds);
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, shiftedBounds,
testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, shiftedBounds,
expectedBounds);
}
@@ -163,7 +163,7 @@ public class WindowConfigurationTests extends WindowTestsBase {
@Test
public void testAppBounds_EmptyBounds() throws Exception {
final Rect emptyBounds = new Rect();
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, emptyBounds,
testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, emptyBounds,
null /*ExpectedBounds*/);
}
@@ -172,7 +172,7 @@ public class WindowConfigurationTests extends WindowTestsBase {
public void testAppBounds_FreeFormBounds() throws Exception {
final Rect freeFormBounds = new Rect(mParentBounds);
freeFormBounds.offset(10, 10);
testStackBoundsConfiguration(FREEFORM_WORKSPACE_STACK_ID, mParentBounds, freeFormBounds,
testStackBoundsConfiguration(WINDOWING_MODE_FREEFORM, mParentBounds, freeFormBounds,
freeFormBounds);
}
@@ -181,7 +181,8 @@ public class WindowConfigurationTests extends WindowTestsBase {
public void testAppBounds_ContainedBounds() throws Exception {
final Rect insetBounds = new Rect(mParentBounds);
insetBounds.inset(5, 5, 5, 5);
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, insetBounds, insetBounds);
testStackBoundsConfiguration(
WINDOWING_MODE_FULLSCREEN, mParentBounds, insetBounds, insetBounds);
}
/** Ensures that full screen free form bounds are clipped */
@@ -189,15 +190,14 @@ public class WindowConfigurationTests extends WindowTestsBase {
public void testAppBounds_FullScreenFreeFormBounds() throws Exception {
final Rect fullScreenBounds = new Rect(0, 0, mDisplayInfo.logicalWidth,
mDisplayInfo.logicalHeight);
testStackBoundsConfiguration(null /*stackId*/, mParentBounds, fullScreenBounds,
testStackBoundsConfiguration(WINDOWING_MODE_FULLSCREEN, mParentBounds, fullScreenBounds,
mParentBounds);
}
private void testStackBoundsConfiguration(Integer stackId, Rect parentBounds, Rect bounds,
private void testStackBoundsConfiguration(int windowingMode, Rect parentBounds, Rect bounds,
Rect expectedConfigBounds) {
final StackWindowController stackController = stackId != null ?
createStackControllerOnStackOnDisplay(stackId, mDisplayContent)
: createStackControllerOnDisplay(mDisplayContent);
final StackWindowController stackController = createStackControllerOnStackOnDisplay(
windowingMode, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Configuration parentConfig = mDisplayContent.getConfiguration();
parentConfig.windowConfiguration.setAppBounds(parentBounds);

View File

@@ -23,9 +23,11 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -160,12 +162,14 @@ public class WindowLayersControllerTests extends WindowTestsBase {
@Test
public void testStackLayers() throws Exception {
WindowState pinnedStackWindow = createWindowOnStack(null, PINNED_STACK_ID,
TYPE_BASE_APPLICATION, mDisplayContent, "pinnedStackWindow");
WindowState dockedStackWindow = createWindowOnStack(null, DOCKED_STACK_ID,
TYPE_BASE_APPLICATION, mDisplayContent, "dockedStackWindow");
WindowState assistantStackWindow = createWindowOnStack(null, ASSISTANT_STACK_ID,
TYPE_BASE_APPLICATION, mDisplayContent, "assistantStackWindow");
WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent, "pinnedStackWindow");
WindowState dockedStackWindow = createWindowOnStack(null,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
mDisplayContent, "dockedStackWindow");
WindowState assistantStackWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
mDisplayContent, "assistantStackWindow");
mLayersController.assignWindowLayers(mDisplayContent);

View File

@@ -16,7 +16,8 @@
package com.android.server.wm;
import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.View.VISIBLE;
@@ -167,14 +168,14 @@ class WindowTestsBase {
sWm.mAnimationHandler.runWithScissors(() -> { }, 0);
}
private WindowToken createWindowToken(DisplayContent dc, int stackId, int type) {
private WindowToken createWindowToken(
DisplayContent dc, int windowingMode, int activityType, int type) {
if (type < FIRST_APPLICATION_WINDOW || type > LAST_APPLICATION_WINDOW) {
return new WindowTestUtils.TestWindowToken(type, dc);
}
final TaskStack stack = stackId == INVALID_STACK_ID
? createTaskStackOnDisplay(dc)
: createStackControllerOnStackOnDisplay(stackId, dc).mContainer;
final TaskStack stack =
createStackControllerOnStackOnDisplay(windowingMode, activityType, dc).mContainer;
final Task task = createTaskInStack(stack, 0 /* userId */);
final WindowTestUtils.TestAppWindowToken token = new WindowTestUtils.TestAppWindowToken(dc);
task.addChild(token, 0);
@@ -187,9 +188,9 @@ class WindowTestsBase {
: createWindow(parent, type, parent.mToken, name);
}
WindowState createWindowOnStack(WindowState parent, int stackId, int type,
DisplayContent dc, String name) {
final WindowToken token = createWindowToken(dc, stackId, type);
WindowState createWindowOnStack(WindowState parent, int windowingMode, int activityType,
int type, DisplayContent dc, String name) {
final WindowToken token = createWindowToken(dc, windowingMode, activityType, type);
return createWindow(parent, type, token, name);
}
@@ -200,13 +201,15 @@ class WindowTestsBase {
}
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
final WindowToken token = createWindowToken(dc, INVALID_STACK_ID, type);
final WindowToken token = createWindowToken(
dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
return createWindow(parent, type, token, name);
}
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
boolean ownerCanAddInternalSystemWindow) {
final WindowToken token = createWindowToken(dc, INVALID_STACK_ID, type);
final WindowToken token = createWindowToken(
dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
return createWindow(parent, type, token, name, ownerCanAddInternalSystemWindow);
}
@@ -233,14 +236,16 @@ class WindowTestsBase {
}
StackWindowController createStackControllerOnDisplay(DisplayContent dc) {
final int stackId = ++sNextStackId;
return createStackControllerOnStackOnDisplay(stackId, dc);
return createStackControllerOnStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc);
}
StackWindowController createStackControllerOnStackOnDisplay(int stackId, DisplayContent dc) {
StackWindowController createStackControllerOnStackOnDisplay(
int windowingMode, int activityType, DisplayContent dc) {
final Configuration overrideConfig = new Configuration();
overrideConfig.windowConfiguration.setWindowingMode(
getWindowingModeForStackId(stackId, false /* inSplitScreenMode */));
overrideConfig.windowConfiguration.setWindowingMode(windowingMode);
overrideConfig.windowConfiguration.setActivityType(activityType);
final int stackId = ++sNextStackId;
final StackWindowController controller = new StackWindowController(stackId, null,
dc.getDisplayId(), true /* onTop */, new Rect(), sWm);
controller.onOverrideConfigurationChanged(overrideConfig);