Merge "Add TestApi interfaces for window organizers" into rvc-dev

This commit is contained in:
Wale Ogunwale
2020-04-01 13:30:47 +00:00
committed by Android (Google) Code Review
43 changed files with 877 additions and 578 deletions

View File

@@ -5158,3 +5158,75 @@ package android.widget {
}
package android.window {
public class DisplayAreaOrganizer extends android.window.WindowOrganizer {
ctor public DisplayAreaOrganizer();
method public void onDisplayAreaAppeared(@NonNull android.window.WindowContainerToken);
method public void onDisplayAreaVanished(@NonNull android.window.WindowContainerToken);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void registerOrganizer(int);
field public static final int FEATURE_ROOT = 0; // 0x0
field public static final int FEATURE_SYSTEM_FIRST = 0; // 0x0
field public static final int FEATURE_SYSTEM_LAST = 10000; // 0x2710
field public static final int FEATURE_TASK_CONTAINER = 1; // 0x1
field public static final int FEATURE_UNDEFINED = -1; // 0xffffffff
field public static final int FEATURE_VENDOR_FIRST = 10001; // 0x2711
field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2
}
public class TaskOrganizer extends android.window.WindowOrganizer {
ctor public TaskOrganizer();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.app.ActivityManager.RunningTaskInfo createRootTask(int, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static boolean deleteRootTask(@NonNull android.window.WindowContainerToken);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.window.WindowContainerToken getImeTarget(int);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getRootTasks(int, @NonNull int[]);
method public void onBackPressedOnTaskRoot(@NonNull android.app.ActivityManager.RunningTaskInfo);
method public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo);
method public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
method public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void registerOrganizer(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void unregisterOrganizer();
}
public final class WindowContainerToken implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.view.SurfaceControl getLeash();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.window.WindowContainerToken> CREATOR;
}
public final class WindowContainerTransaction implements android.os.Parcelable {
ctor public WindowContainerTransaction();
method public int describeContents();
method @NonNull public android.window.WindowContainerTransaction reorder(@NonNull android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparent(@NonNull android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int);
method @NonNull public android.window.WindowContainerTransaction setAppBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBoundsChangeTransaction(@NonNull android.window.WindowContainerToken, @NonNull android.view.SurfaceControl.Transaction);
method @NonNull public android.window.WindowContainerTransaction setFocusable(@NonNull android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction setHidden(@NonNull android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction setScreenSizeDp(@NonNull android.window.WindowContainerToken, int, int);
method @NonNull public android.window.WindowContainerTransaction setSmallestScreenWidthDp(@NonNull android.window.WindowContainerToken, int);
method @NonNull public android.window.WindowContainerTransaction setWindowingMode(@NonNull android.window.WindowContainerToken, int);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.window.WindowContainerTransaction> CREATOR;
}
public abstract class WindowContainerTransactionCallback {
ctor public WindowContainerTransactionCallback();
method public abstract void onTransactionReady(int, @NonNull android.view.SurfaceControl.Transaction);
}
public class WindowOrganizer {
ctor public WindowOrganizer();
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void applyTransaction(@NonNull android.window.WindowContainerTransaction);
}
}

View File

@@ -73,7 +73,7 @@ import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Singleton;
import android.util.Size;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
import android.view.Surface;
import com.android.internal.app.LocalePicker;
@@ -2759,7 +2759,7 @@ public class ActivityManager {
// Index of the stack in the display's stack list, can be used for comparison of stack order
@UnsupportedAppUsage
public int position;
public IWindowContainer stackToken;
public WindowContainerToken stackToken;
/**
* The full configuration the stack is currently running in.
* @hide
@@ -2793,7 +2793,7 @@ public class ActivityManager {
dest.writeInt(userId);
dest.writeInt(visible ? 1 : 0);
dest.writeInt(position);
dest.writeStrongInterface(stackToken);
stackToken.writeToParcel(dest, 0);
if (topActivity != null) {
dest.writeInt(1);
topActivity.writeToParcel(dest, 0);
@@ -2825,7 +2825,7 @@ public class ActivityManager {
userId = source.readInt();
visible = source.readInt() > 0;
position = source.readInt();
stackToken = IWindowContainer.Stub.asInterface(source.readStrongBinder());
stackToken = WindowContainerToken.CREATOR.createFromParcel(source);
if (source.readInt() > 0) {
topActivity = ComponentName.readFromParcel(source);
}

View File

@@ -42,6 +42,9 @@ import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.window.TaskEmbedder;
import android.window.TaskOrganizerTaskEmbedder;
import android.window.VirtualDisplayTaskEmbedder;
import dalvik.system.CloseGuard;
@@ -52,11 +55,11 @@ import dalvik.system.CloseGuard;
* @hide
*/
@TestApi
public class ActivityView extends ViewGroup implements TaskEmbedder.Host {
public class ActivityView extends ViewGroup implements android.window.TaskEmbedder.Host {
private static final String TAG = "ActivityView";
private TaskEmbedder mTaskEmbedder;
private android.window.TaskEmbedder mTaskEmbedder;
private final SurfaceView mSurfaceView;
private final SurfaceCallback mSurfaceCallback;
@@ -487,7 +490,7 @@ public class ActivityView extends ViewGroup implements TaskEmbedder.Host {
/** @hide */
@Override
public void onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor) {
public void onTaskBackgroundColorChanged(android.window.TaskEmbedder ts, int bgColor) {
if (mSurfaceView != null) {
mSurfaceView.setResizeBackgroundColor(bgColor);
}

View File

@@ -28,7 +28,7 @@ import android.content.res.Configuration;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
/**
* Stores information about a particular Task.
@@ -147,7 +147,7 @@ public class TaskInfo {
* @hide
*/
@NonNull
public IWindowContainer token;
public WindowContainerToken token;
/**
* The PictureInPictureParams for the Task, if set.
@@ -222,7 +222,7 @@ public class TaskInfo {
supportsSplitScreenMultiWindow = source.readBoolean();
resizeMode = source.readInt();
configuration.readFromParcel(source);
token = IWindowContainer.Stub.asInterface(source.readStrongBinder());
token = WindowContainerToken.CREATOR.createFromParcel(source);
topActivityType = source.readInt();
pictureInPictureParams = source.readInt() != 0
? PictureInPictureParams.CREATOR.createFromParcel(source)
@@ -265,7 +265,7 @@ public class TaskInfo {
dest.writeBoolean(supportsSplitScreenMultiWindow);
dest.writeInt(resizeMode);
configuration.writeToParcel(dest, flags);
dest.writeStrongInterface(token);
token.writeToParcel(dest, flags);
dest.writeInt(topActivityType);
if (pictureInPictureParams == null) {
dest.writeInt(0);

View File

@@ -0,0 +1,91 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.os.RemoteException;
import android.util.Singleton;
/**
* Interface for WindowManager to delegate control of display areas.
* @hide
*/
@TestApi
public class DisplayAreaOrganizer extends WindowOrganizer {
public static final int FEATURE_UNDEFINED = -1;
public static final int FEATURE_SYSTEM_FIRST = 0;
// The Root display area on a display
public static final int FEATURE_ROOT = FEATURE_SYSTEM_FIRST;
// Display area hosting the task container.
public static final int FEATURE_TASK_CONTAINER = FEATURE_SYSTEM_FIRST + 1;
// Display area hosting non-activity window tokens.
public static final int FEATURE_WINDOW_TOKENS = FEATURE_SYSTEM_FIRST + 2;
public static final int FEATURE_SYSTEM_LAST = 10_000;
// Vendor specific display area definition can start with this value.
public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1;
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public void registerOrganizer(int displayAreaFeature) {
try {
getController().registerOrganizer(mInterface, displayAreaFeature);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public void onDisplayAreaAppeared(@NonNull WindowContainerToken displayArea) {}
public void onDisplayAreaVanished(@NonNull WindowContainerToken displayArea) {}
private final IDisplayAreaOrganizer mInterface = new IDisplayAreaOrganizer.Stub() {
@Override
public void onDisplayAreaAppeared(@NonNull WindowContainerToken displayArea) {
DisplayAreaOrganizer.this.onDisplayAreaAppeared(displayArea);
}
@Override
public void onDisplayAreaVanished(@NonNull WindowContainerToken displayArea) {
DisplayAreaOrganizer.this.onDisplayAreaVanished(displayArea);
}
};
private static IDisplayAreaOrganizerController getController() {
return IDisplayAreaOrganizerControllerSingleton.get();
}
private static final Singleton<IDisplayAreaOrganizerController>
IDisplayAreaOrganizerControllerSingleton =
new Singleton<IDisplayAreaOrganizerController>() {
@Override
protected IDisplayAreaOrganizerController create() {
try {
return getWindowOrganizerController()
.getDisplayAreaOrganizerController();
} catch (RemoteException e) {
return null;
}
}
};
}

View File

@@ -16,13 +16,13 @@
package android.window;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
/**
* Interface for WindowManager to delegate control of display areas.
* {@hide}
*/
oneway interface IDisplayAreaOrganizer {
void onDisplayAreaAppeared(in IWindowContainer displayArea);
void onDisplayAreaVanished(in IWindowContainer displayArea);
void onDisplayAreaAppeared(in WindowContainerToken displayArea);
void onDisplayAreaVanished(in WindowContainerToken displayArea);
}

View File

@@ -18,7 +18,7 @@ package android.window;
import android.view.SurfaceControl;
import android.app.ActivityManager;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
/**
* Interface for ActivityTaskManager/WindowManager to delegate control of tasks.

View File

@@ -18,7 +18,7 @@ package android.window;
import android.app.ActivityManager;
import android.window.ITaskOrganizer;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
/** @hide */
@@ -40,23 +40,23 @@ interface ITaskOrganizerController {
ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode);
/** Deletes a persistent root task in WM */
boolean deleteRootTask(IWindowContainer task);
boolean deleteRootTask(in WindowContainerToken task);
/** Gets direct child tasks (ordered from top-to-bottom) */
List<ActivityManager.RunningTaskInfo> getChildTasks(in IWindowContainer parent,
List<ActivityManager.RunningTaskInfo> getChildTasks(in WindowContainerToken parent,
in int[] activityTypes);
/** Gets all root tasks on a display (ordered from top-to-bottom) */
List<ActivityManager.RunningTaskInfo> getRootTasks(int displayId, in int[] activityTypes);
/** Get the root task which contains the current ime target */
IWindowContainer getImeTarget(int display);
WindowContainerToken getImeTarget(int display);
/**
* Set's the root task to launch new tasks into on a display. {@code null} means no launch root
* and thus new tasks just end up directly on the display.
*/
void setLaunchRoot(int displayId, in IWindowContainer root);
void setLaunchRoot(int displayId, in WindowContainerToken root);
/**
* Requests that the given task organizer is notified when back is pressed on the root activity

View File

@@ -23,7 +23,7 @@ import android.view.SurfaceControl;
* token.
* @hide
*/
interface IWindowContainer {
interface IWindowContainerToken {
/**
* Gets a persistent leash for this container or {@code null}.

View File

@@ -24,5 +24,5 @@ import android.view.SurfaceControl;
*/
oneway interface IWindowContainerTransactionCallback {
/** Called upon completion of WindowOrganizer#applyTransaction */
void transactionReady(int id, in SurfaceControl.Transaction t);
void onTransactionReady(int id, in SurfaceControl.Transaction t);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,19 @@
* limitations under the License.
*/
package android.app;
package android.window;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityView;
import android.app.IActivityTaskManager;
import android.app.PendingIntent;
import android.app.TaskStackListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.os.RemoteException;
import android.util.Singleton;
import java.util.List;
/**
* Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
* @hide
*/
@TestApi
public class TaskOrganizer extends WindowOrganizer {
/**
* Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
* If there was already a TaskOrganizer for this windowing mode it will be evicted
* and receive taskVanished callbacks in the process.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public void registerOrganizer(int windowingMode) {
try {
getController().registerTaskOrganizer(mInterface, windowingMode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** Unregisters a previously registered task organizer. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public void unregisterOrganizer() {
try {
getController().unregisterTaskOrganizer(mInterface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo info) {}
public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo info) {}
/** Creates a persistent root task in WM for a particular windowing-mode. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
@Nullable
public static ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) {
try {
return getController().createRootTask(displayId, windowingMode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** Deletes a persistent root task in WM */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static boolean deleteRootTask(@NonNull WindowContainerToken task) {
try {
return getController().deleteRootTask(task);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** Gets direct child tasks (ordered from top-to-bottom) */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
@Nullable
public static List<ActivityManager.RunningTaskInfo> getChildTasks(
@NonNull WindowContainerToken parent, @NonNull int[] activityTypes) {
try {
return getController().getChildTasks(parent, activityTypes);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** Gets all root tasks on a display (ordered from top-to-bottom) */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
@Nullable
public static List<ActivityManager.RunningTaskInfo> getRootTasks(
int displayId, @NonNull int[] activityTypes) {
try {
return getController().getRootTasks(displayId, activityTypes);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** Get the root task which contains the current ime target */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
@Nullable
public static WindowContainerToken getImeTarget(int display) {
try {
return getController().getImeTarget(display);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Set's the root task to launch new tasks into on a display. {@code null} means no launch
* root and thus new tasks just end up directly on the display.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void setLaunchRoot(int displayId, @NonNull WindowContainerToken root) {
try {
getController().setLaunchRoot(displayId, root);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Requests that the given task organizer is notified when back is pressed on the root activity
* of one of its controlled tasks.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
try {
getController().setInterceptBackPressedOnTaskRoot(mInterface, interceptBackPressed);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
TaskOrganizer.this.onTaskAppeared(taskInfo);
}
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
TaskOrganizer.this.onTaskVanished(taskInfo);
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
TaskOrganizer.this.onTaskInfoChanged(info);
}
@Override
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
TaskOrganizer.this.onBackPressedOnTaskRoot(info);
}
};
private static ITaskOrganizerController getController() {
return ITaskOrganizerControllerSingleton.get();
}
private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
new Singleton<ITaskOrganizerController>() {
@Override
protected ITaskOrganizerController create() {
try {
return getWindowOrganizerController().getTaskOrganizerController();
} catch (RemoteException e) {
return null;
}
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,22 +14,20 @@
* limitations under the License.
*/
package android.app;
package android.window;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityView;
import android.app.TaskStackListener;
import android.content.Context;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.IWindowContainer;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
import android.window.WindowOrganizer.TaskOrganizer;
/**
* A component which handles embedded display of tasks within another window. The embedded task can
@@ -41,9 +39,9 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
private static final String TAG = "TaskOrgTaskEmbedder";
private static final boolean DEBUG = false;
private ITaskOrganizer.Stub mTaskOrganizer;
private TaskOrganizer mTaskOrganizer;
private ActivityManager.RunningTaskInfo mTaskInfo;
private IWindowContainer mTaskToken;
private WindowContainerToken mTaskToken;
private SurfaceControl mTaskLeash;
private boolean mPendingNotifyBoundsChanged;
@@ -79,16 +77,11 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
}
// Register the task organizer
mTaskOrganizer = new TaskOrganizerImpl();
try {
// TODO(wm-shell): This currently prevents other organizers from controlling MULT_WINDOW
// windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that
// infrastructure is ready.
TaskOrganizer.registerOrganizer(mTaskOrganizer, WINDOWING_MODE_MULTI_WINDOW);
TaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskOrganizer, true);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize TaskEmbedder", e);
return false;
}
// TODO(wm-shell): This currently prevents other organizers from controlling MULT_WINDOW
// windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that
// infrastructure is ready.
mTaskOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW);
mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true);
return true;
}
@@ -100,11 +93,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
if (!isInitialized()) {
return false;
}
try {
TaskOrganizer.unregisterOrganizer(mTaskOrganizer);
} catch (RemoteException e) {
Log.e(TAG, "Failed to remove task");
}
mTaskOrganizer.unregisterOrganizer();
resetTaskInfo();
return true;
}
@@ -125,11 +114,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
}
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setHidden(mTaskToken, false /* hidden */);
try {
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.e(TAG, "Failed to unset hidden in transaction");
}
WindowOrganizer.applyTransaction(wct);
// TODO(b/151449487): Only call callback once we enable synchronization
if (mListener != null) {
mListener.onTaskVisibilityChanged(getTaskId(), true);
@@ -152,11 +137,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
}
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setHidden(mTaskToken, true /* hidden */);
try {
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.e(TAG, "Failed to set hidden in transaction");
}
WindowOrganizer.applyTransaction(wct);
// TODO(b/151449487): Only call callback once we enable synchronization
if (mListener != null) {
mListener.onTaskVisibilityChanged(getTaskId(), false);
@@ -186,12 +167,8 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setBounds(mTaskToken, screenBounds);
try {
// TODO(b/151449487): Enable synchronization
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.e(TAG, "Failed to set bounds in transaction");
}
// TODO(b/151449487): Enable synchronization
WindowOrganizer.applyTransaction(wct);
}
/**
@@ -253,8 +230,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
private class TaskStackListenerImpl extends TaskStackListener {
@Override
public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
if (!isInitialized()) {
return;
}
@@ -266,10 +242,9 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
}
}
private class TaskOrganizerImpl extends ITaskOrganizer.Stub {
private class TaskOrganizerImpl extends TaskOrganizer {
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
if (DEBUG) {
log("taskAppeared: " + taskInfo.taskId);
}
@@ -293,8 +268,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
}
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
if (DEBUG) {
log("taskVanished: " + taskInfo.taskId);
}
@@ -309,14 +283,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder {
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
// Do nothing
}
@Override
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo)
throws RemoteException {
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
if (mListener != null) {
mListener.onBackPressedOnTaskRoot(taskInfo.taskId);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package android.app;
package android.window;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
@@ -23,6 +23,11 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLI
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityView;
import android.app.TaskStackListener;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Insets;
@@ -72,7 +77,7 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
* @param singleTaskInstance whether to apply a single-task constraint to this container,
* only applicable if virtual displays are used
*/
VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
public VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
boolean singleTaskInstance) {
super(context, host);
mSingleTaskInstance = singleTaskInstance;

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
parcelable WindowContainerToken;

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.view.SurfaceControl;
import android.window.IWindowContainerToken;
/**
* Interface for a window container to communicate with the window manager. This also acts as a
* token.
* @hide
*/
@TestApi
public final class WindowContainerToken implements Parcelable {
private final IWindowContainerToken mRealToken;
/** @hide */
public WindowContainerToken(IWindowContainerToken realToken) {
mRealToken = realToken;
}
private WindowContainerToken(Parcel in) {
mRealToken = IWindowContainerToken.Stub.asInterface(in.readStrongBinder());
}
@Nullable
public SurfaceControl getLeash() {
try {
return mRealToken.getLeash();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
public IBinder asBinder() {
return mRealToken.asBinder();
}
@Override
/** @hide */
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStrongBinder(mRealToken.asBinder());
}
@NonNull
public static final Creator<WindowContainerToken> CREATOR =
new Creator<WindowContainerToken>() {
@Override
public WindowContainerToken createFromParcel(Parcel in) {
return new WindowContainerToken(in);
}
@Override
public WindowContainerToken[] newArray(int size) {
return new WindowContainerToken[size];
}
};
@Override
/** @hide */
public int describeContents() {
return 0;
}
}

View File

@@ -18,6 +18,7 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
@@ -26,7 +27,6 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.window.IWindowContainer;
import android.view.SurfaceControl;
import java.util.ArrayList;
@@ -39,7 +39,8 @@ import java.util.Map;
*
* @hide
*/
public class WindowContainerTransaction implements Parcelable {
@TestApi
public final class WindowContainerTransaction implements Parcelable {
private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>();
// Flat list because re-order operations are order-dependent
@@ -47,7 +48,7 @@ public class WindowContainerTransaction implements Parcelable {
public WindowContainerTransaction() {}
protected WindowContainerTransaction(Parcel in) {
private WindowContainerTransaction(Parcel in) {
in.readMap(mChanges, null /* loader */);
in.readList(mHierarchyOps, null /* loader */);
}
@@ -64,7 +65,9 @@ public class WindowContainerTransaction implements Parcelable {
/**
* Resize a container.
*/
public WindowContainerTransaction setBounds(IWindowContainer container, Rect bounds) {
@NonNull
public WindowContainerTransaction setBounds(
@NonNull WindowContainerToken container,@NonNull Rect bounds) {
Change chg = getOrCreateChange(container.asBinder());
chg.mConfiguration.windowConfiguration.setBounds(bounds);
chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
@@ -77,7 +80,9 @@ public class WindowContainerTransaction implements Parcelable {
* app's DisplayInfo. It is derived by subtracting the overlapping portion of the navbar from
* the full bounds.
*/
public WindowContainerTransaction setAppBounds(IWindowContainer container, Rect appBounds) {
@NonNull
public WindowContainerTransaction setAppBounds(
@NonNull WindowContainerToken container,@NonNull Rect appBounds) {
Change chg = getOrCreateChange(container.asBinder());
chg.mConfiguration.windowConfiguration.setAppBounds(appBounds);
chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
@@ -91,7 +96,9 @@ public class WindowContainerTransaction implements Parcelable {
* derived by subtracting the overlapping portions of both the statusbar and the navbar from
* the full bounds.
*/
public WindowContainerTransaction setScreenSizeDp(IWindowContainer container, int w, int h) {
@NonNull
public WindowContainerTransaction setScreenSizeDp(
@NonNull WindowContainerToken container, int w, int h) {
Change chg = getOrCreateChange(container.asBinder());
chg.mConfiguration.screenWidthDp = w;
chg.mConfiguration.screenHeightDp = h;
@@ -100,11 +107,12 @@ public class WindowContainerTransaction implements Parcelable {
}
/**
* Notify activies within the hiearchy of a container that they have entered picture-in-picture
* Notify activities within the hierarchy of a container that they have entered picture-in-picture
* mode with the given bounds.
*/
public WindowContainerTransaction scheduleFinishEnterPip(IWindowContainer container,
Rect bounds) {
@NonNull
public WindowContainerTransaction scheduleFinishEnterPip(
@NonNull WindowContainerToken container,@NonNull Rect bounds) {
Change chg = getOrCreateChange(container.asBinder());
chg.mPinnedBounds = new Rect(bounds);
chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK;
@@ -123,8 +131,9 @@ public class WindowContainerTransaction implements Parcelable {
* that you can call this, apply the WindowContainer transaction, and then later call
* dismissPip() to achieve synchronization.
*/
public WindowContainerTransaction setBoundsChangeTransaction(IWindowContainer container,
SurfaceControl.Transaction t) {
@NonNull
public WindowContainerTransaction setBoundsChangeTransaction(
@NonNull WindowContainerToken container,@NonNull SurfaceControl.Transaction t) {
Change chg = getOrCreateChange(container.asBinder());
chg.mBoundsChangeTransaction = t;
chg.mChangeMask |= Change.CHANGE_BOUNDS_TRANSACTION;
@@ -139,8 +148,9 @@ public class WindowContainerTransaction implements Parcelable {
*
* TODO(b/134365562): Can be removed once TaskOrg drives full-screen
*/
public WindowContainerTransaction setActivityWindowingMode(IWindowContainer container,
int windowingMode) {
@NonNull
public WindowContainerTransaction setActivityWindowingMode(
@NonNull WindowContainerToken container, int windowingMode) {
Change chg = getOrCreateChange(container.asBinder());
chg.mActivityWindowingMode = windowingMode;
return this;
@@ -149,8 +159,9 @@ public class WindowContainerTransaction implements Parcelable {
/**
* Sets the windowing mode of the given container.
*/
public WindowContainerTransaction setWindowingMode(IWindowContainer container,
int windowingMode) {
@NonNull
public WindowContainerTransaction setWindowingMode(
@NonNull WindowContainerToken container, int windowingMode) {
Change chg = getOrCreateChange(container.asBinder());
chg.mWindowingMode = windowingMode;
return this;
@@ -161,7 +172,9 @@ public class WindowContainerTransaction implements Parcelable {
* child can be focused; however, when {@code true}, it is still possible for children to be
* non-focusable due to WM policy.
*/
public WindowContainerTransaction setFocusable(IWindowContainer container, boolean focusable) {
@NonNull
public WindowContainerTransaction setFocusable(
@NonNull WindowContainerToken container, boolean focusable) {
Change chg = getOrCreateChange(container.asBinder());
chg.mFocusable = focusable;
chg.mChangeMask |= Change.CHANGE_FOCUSABLE;
@@ -173,7 +186,9 @@ public class WindowContainerTransaction implements Parcelable {
* visibility of the container applies, but when {@code true} the container will be forced
* to be hidden.
*/
public WindowContainerTransaction setHidden(IWindowContainer container, boolean hidden) {
@NonNull
public WindowContainerTransaction setHidden(
@NonNull WindowContainerToken container, boolean hidden) {
Change chg = getOrCreateChange(container.asBinder());
chg.mHidden = hidden;
chg.mChangeMask |= Change.CHANGE_HIDDEN;
@@ -183,8 +198,9 @@ public class WindowContainerTransaction implements Parcelable {
/**
* Set the smallestScreenWidth of a container.
*/
public WindowContainerTransaction setSmallestScreenWidthDp(IWindowContainer container,
int widthDp) {
@NonNull
public WindowContainerTransaction setSmallestScreenWidthDp(
@NonNull WindowContainerToken container, int widthDp) {
Change cfg = getOrCreateChange(container.asBinder());
cfg.mConfiguration.smallestScreenWidthDp = widthDp;
cfg.mConfigSetMask |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
@@ -198,8 +214,9 @@ public class WindowContainerTransaction implements Parcelable {
* @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
* the bottom.
*/
public WindowContainerTransaction reparent(@NonNull IWindowContainer child,
@Nullable IWindowContainer parent, boolean onTop) {
@NonNull
public WindowContainerTransaction reparent(@NonNull WindowContainerToken child,
@Nullable WindowContainerToken parent, boolean onTop) {
mHierarchyOps.add(new HierarchyOp(child.asBinder(),
parent == null ? null : parent.asBinder(), onTop));
return this;
@@ -211,36 +228,43 @@ public class WindowContainerTransaction implements Parcelable {
* @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
* the bottom.
*/
public WindowContainerTransaction reorder(@NonNull IWindowContainer child, boolean onTop) {
@NonNull
public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop) {
mHierarchyOps.add(new HierarchyOp(child.asBinder(), onTop));
return this;
}
/** @hide */
public Map<IBinder, Change> getChanges() {
return mChanges;
}
/** @hide */
public List<HierarchyOp> getHierarchyOps() {
return mHierarchyOps;
}
@Override
@NonNull
public String toString() {
return "WindowContainerTransaction { changes = " + mChanges + " hops = " + mHierarchyOps
+ " }";
}
@Override
public void writeToParcel(Parcel dest, int flags) {
/** @hide */
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeMap(mChanges);
dest.writeList(mHierarchyOps);
}
@Override
/** @hide */
public int describeContents() {
return 0;
}
@NonNull
public static final Creator<WindowContainerTransaction> CREATOR =
new Creator<WindowContainerTransaction>() {
@Override
@@ -256,7 +280,6 @@ public class WindowContainerTransaction implements Parcelable {
/**
* Holds changes on a single WindowContainer including Configuration changes.
*
* @hide
*/
public static class Change implements Parcelable {
@@ -430,6 +453,7 @@ public class WindowContainerTransaction implements Parcelable {
/**
* Holds information about a reparent/reorder operation in the hierarchy. This is separate from
* Changes because they must be executed in the same order that they are added.
* @hide
*/
public static class HierarchyOp implements Parcelable {
private final IBinder mContainer;

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.NonNull;
import android.annotation.TestApi;
import android.view.SurfaceControl;
/**
* See WindowOrganizer#applyTransaction.
* {@hide}
*/
@TestApi
public abstract class WindowContainerTransactionCallback {
public abstract void onTransactionReady(int id, @NonNull SurfaceControl.Transaction t);
/** @hide */
final IWindowContainerTransactionCallback mInterface =
new IWindowContainerTransactionCallback.Stub() {
@Override
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
WindowContainerTransactionCallback.this.onTransactionReady(id, t);
}
};
}

View File

@@ -16,29 +16,32 @@
package android.window;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.annotation.TestApi;
import android.app.ActivityTaskManager;
import android.os.RemoteException;
import android.util.Singleton;
import java.util.List;
/**
* Class for organizing specific types of windows like Tasks and DisplayAreas
* Base class for organizing specific types of windows like Tasks and DisplayAreas
*
* @hide
*/
@TestApi
public class WindowOrganizer {
/**
* Apply multiple WindowContainer operations at once.
* @param t The transaction to apply.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void applyTransaction(WindowContainerTransaction t) throws RemoteException {
getWindowOrganizerController().applyTransaction(t);
public static void applyTransaction(@NonNull WindowContainerTransaction t) {
try {
getWindowOrganizerController().applyTransaction(t);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
@@ -49,17 +52,19 @@ public class WindowOrganizer {
* WindowContainer transaction will be passed to this callback when ready.
* @return An ID for the sync operation which will later be passed to transactionReady callback.
* This lets the caller differentiate overlapping sync operations.
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static int applySyncTransaction(WindowContainerTransaction t,
IWindowContainerTransactionCallback callback) throws RemoteException {
return getWindowOrganizerController().applySyncTransaction(t, callback);
public int applySyncTransaction(@NonNull WindowContainerTransaction t,
@NonNull WindowContainerTransactionCallback callback) {
try {
return getWindowOrganizerController().applySyncTransaction(t, callback.mInterface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
private static IWindowOrganizerController getWindowOrganizerController() {
static IWindowOrganizerController getWindowOrganizerController() {
return IWindowOrganizerControllerSingleton.get();
}
@@ -74,138 +79,4 @@ public class WindowOrganizer {
}
}
};
public static class TaskOrganizer {
/**
* Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
* If there was already a TaskOrganizer for this windowing mode it will be evicted
* and receive taskVanished callbacks in the process.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void registerOrganizer(ITaskOrganizer organizer, int windowingMode)
throws RemoteException {
getController().registerTaskOrganizer(organizer, windowingMode);
}
/** Unregisters a previously registered task organizer. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void unregisterOrganizer(ITaskOrganizer organizer) throws RemoteException {
getController().unregisterTaskOrganizer(organizer);
}
/** Creates a persistent root task in WM for a particular windowing-mode. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static ActivityManager.RunningTaskInfo createRootTask(
int displayId, int windowingMode) throws RemoteException {
return getController().createRootTask(displayId, windowingMode);
}
/** Deletes a persistent root task in WM */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static boolean deleteRootTask(IWindowContainer task) throws RemoteException {
return getController().deleteRootTask(task);
}
/** Gets direct child tasks (ordered from top-to-bottom) */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static List<ActivityManager.RunningTaskInfo> getChildTasks(IWindowContainer parent,
int[] activityTypes) throws RemoteException {
return getController().getChildTasks(parent, activityTypes);
}
/** Gets all root tasks on a display (ordered from top-to-bottom) */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static List<ActivityManager.RunningTaskInfo> getRootTasks(
int displayId, int[] activityTypes) throws RemoteException {
return getController().getRootTasks(displayId, activityTypes);
}
/** Get the root task which contains the current ime target */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static IWindowContainer getImeTarget(int display) throws RemoteException {
return getController().getImeTarget(display);
}
/**
* Set's the root task to launch new tasks into on a display. {@code null} means no launch
* root and thus new tasks just end up directly on the display.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void setLaunchRoot(int displayId, IWindowContainer root)
throws RemoteException {
getController().setLaunchRoot(displayId, root);
}
/**
* Requests that the given task organizer is notified when back is pressed on the root
* activity of one of its controlled tasks.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
boolean interceptBackPressed) throws RemoteException {
getController().setInterceptBackPressedOnTaskRoot(organizer, interceptBackPressed);
}
private static ITaskOrganizerController getController() {
return ITaskOrganizerControllerSingleton.get();
}
private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
new Singleton<ITaskOrganizerController>() {
@Override
protected ITaskOrganizerController create() {
try {
return getWindowOrganizerController().getTaskOrganizerController();
} catch (RemoteException e) {
return null;
}
}
};
}
/** Class for organizing display areas. */
public static class DisplayAreaOrganizer {
public static final int FEATURE_UNDEFINED = -1;
public static final int FEATURE_SYSTEM_FIRST = 0;
// The Root display area on a display
public static final int FEATURE_ROOT = FEATURE_SYSTEM_FIRST;
// Display area hosting the task container.
public static final int FEATURE_TASK_CONTAINER = FEATURE_SYSTEM_FIRST + 1;
// Display area hosting non-activity window tokens.
public static final int FEATURE_WINDOW_TOKENS = FEATURE_SYSTEM_FIRST + 2;
public static final int FEATURE_SYSTEM_LAST = 10_000;
// Vendor specific display area definition can start with this value.
public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1;
/** @hide */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
public static void registerOrganizer(
IDisplayAreaOrganizer organizer, int displayAreaFeature) throws RemoteException {
getController().registerOrganizer(organizer, displayAreaFeature);
}
/** @hide */
private static IDisplayAreaOrganizerController getController() {
return IDisplayAreaOrganizerControllerSingleton.get();
}
private static final Singleton<IDisplayAreaOrganizerController>
IDisplayAreaOrganizerControllerSingleton =
new Singleton<IDisplayAreaOrganizerController>() {
@Override
protected IDisplayAreaOrganizerController create() {
try {
return getWindowOrganizerController()
.getDisplayAreaOrganizerController();
} catch (RemoteException e) {
return null;
}
}
};
}
}

View File

@@ -23,8 +23,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.app.TaskEmbedder;
import android.app.TaskOrganizerTaskEmbedder;
import android.window.TaskEmbedder;
import android.window.TaskOrganizerTaskEmbedder;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;

View File

@@ -41,8 +41,8 @@ import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.IWindowContainer;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -60,7 +60,7 @@ import java.util.function.Consumer;
/**
* Manages PiP tasks such as resize and offset.
*
* This class listens on {@link ITaskOrganizer} callbacks for windowing mode change
* This class listens on {@link TaskOrganizer} callbacks for windowing mode change
* both to and from PiP and issues corresponding animation if applicable.
* Normally, we apply series of {@link SurfaceControl.Transaction} when the animator is running
* and files a final {@link WindowContainerTransaction} at the end of the transition.
@@ -68,7 +68,7 @@ import java.util.function.Consumer;
* This class is also responsible for general resize/offset PiP operations within SysUI component,
* see also {@link com.android.systemui.pip.phone.PipMotionHelper}.
*/
public class PipTaskOrganizer extends ITaskOrganizer.Stub {
public class PipTaskOrganizer extends TaskOrganizer {
private static final String TAG = PipTaskOrganizer.class.getSimpleName();
private static final int MSG_RESIZE_IMMEDIATE = 1;
@@ -182,7 +182,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
};
private ActivityManager.RunningTaskInfo mTaskInfo;
private IWindowContainer mToken;
private WindowContainerToken mToken;
private SurfaceControl mLeash;
private boolean mInPip;
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
@@ -234,13 +234,9 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
* @param animationDurationMs duration in millisecond for the exiting PiP transition
*/
public void dismissPip(int animationDurationMs) {
try {
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.e(TAG, "Failed to apply container transaction", e);
}
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
WindowOrganizer.applyTransaction(wct);
final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs,
@@ -258,11 +254,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
mTaskInfo = info;
mToken = mTaskInfo.token;
mInPip = true;
try {
mLeash = mToken.getLeash();
} catch (RemoteException e) {
throw new RuntimeException("Unable to get leash", e);
}
mLeash = mToken.getLeash();
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
mBoundsToRestore.put(mToken.asBinder(), currentBounds);
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
@@ -290,8 +283,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
*/
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
IWindowContainer token = info.token;
Objects.requireNonNull(token, "Requires valid IWindowContainer");
WindowContainerToken token = info.token;
Objects.requireNonNull(token, "Requires valid WindowContainerToken");
if (token.asBinder() != mToken.asBinder()) {
Log.wtf(TAG, "Unrecognized token: " + token);
return;
@@ -502,30 +495,26 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
+ "directly");
}
mLastReportedBounds.set(destinationBounds);
try {
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect taskBounds;
if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
// If we are animating to fullscreen, then we need to reset the override bounds
// on the task to ensure that the task "matches" the parent's bounds, this applies
// also to the final windowing mode, which should be reset to undefined rather than
// fullscreen.
taskBounds = null;
wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
} else {
taskBounds = destinationBounds;
}
if (direction == TRANSITION_DIRECTION_TO_PIP) {
wct.scheduleFinishEnterPip(mToken, taskBounds);
} else {
wct.setBounds(mToken, taskBounds);
}
wct.setBoundsChangeTransaction(mToken, tx);
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.e(TAG, "Failed to apply container transaction", e);
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect taskBounds;
if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
// If we are animating to fullscreen, then we need to reset the override bounds
// on the task to ensure that the task "matches" the parent's bounds, this applies
// also to the final windowing mode, which should be reset to undefined rather than
// fullscreen.
taskBounds = null;
wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
} else {
taskBounds = destinationBounds;
}
if (direction == TRANSITION_DIRECTION_TO_PIP) {
wct.scheduleFinishEnterPip(mToken, taskBounds);
} else {
wct.setBounds(mToken, taskBounds);
}
wct.setBoundsChangeTransaction(mToken, tx);
WindowOrganizer.applyTransaction(wct);
}
private void animateResizePip(Rect currentBounds, Rect destinationBounds,

View File

@@ -18,7 +18,6 @@ package com.android.systemui.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.window.WindowOrganizer.TaskOrganizer;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
@@ -234,7 +233,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
mPipBoundsHandler.onDisplayInfoChanged(displayInfo);
try {
TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
if (stackInfo != null) {

View File

@@ -19,7 +19,6 @@ package com.android.systemui.pip.tv;
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.window.WindowOrganizer.TaskOrganizer;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackInfo;
@@ -294,7 +293,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
try {
WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
} catch (RemoteException | UnsupportedOperationException e) {
Log.e(TAG, "Failed to register pinned stack listener", e);
}

View File

@@ -20,7 +20,6 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowOrganizer.TaskOrganizer;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -33,11 +32,12 @@ import android.os.Handler;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Slog;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
import android.window.IWindowContainer;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -181,14 +181,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
private boolean mPausedTargetAdjusted = false;
private boolean getSecondaryHasFocus(int displayId) {
try {
IWindowContainer imeSplit = TaskOrganizer.getImeTarget(displayId);
return imeSplit != null
&& (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
} catch (RemoteException e) {
Slog.w(TAG, "Failed to get IME target", e);
}
return false;
WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId);
return imeSplit != null
&& (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
}
private void updateDimTargets() {
@@ -270,10 +265,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
wct.setScreenSizeDp(mSplits.mSecondary.token,
SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
}
try {
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
}
WindowOrganizer.applyTransaction(wct);
// Update all the adjusted-for-ime states
if (!mPaused) {
@@ -506,12 +499,8 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
final WindowContainerTransaction tct = new WindowContainerTransaction();
mSplitLayout.resizeSplits(midPos, tct);
try {
WindowOrganizer.applyTransaction(tct);
} catch (RemoteException e) {
}
} else if (mRotateSplitLayout != null
&& mSplitLayout.mDisplayLayout.rotation()
WindowOrganizer.applyTransaction(tct);
} else if (mSplitLayout.mDisplayLayout.rotation()
== mRotateSplitLayout.mDisplayLayout.rotation()) {
mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
@@ -653,7 +642,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
}
}
updateTouchable();
WindowManagerProxy.applyContainerTransaction(wct);
WindowOrganizer.applyTransaction(wct);
}
void setAdjustedForIme(boolean adjustedForIme) {

View File

@@ -22,7 +22,6 @@ 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_SPLIT_SCREEN_SECONDARY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowOrganizer.TaskOrganizer;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.WindowConfiguration;
@@ -32,11 +31,11 @@ import android.util.Log;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.ITaskOrganizer;
import android.window.TaskOrganizer;
import java.util.ArrayList;
class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
class SplitScreenTaskOrganizer extends TaskOrganizer {
private static final String TAG = "SplitScreenTaskOrganizer";
private static final boolean DEBUG = Divider.DEBUG;
@@ -56,8 +55,8 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
}
void init(SurfaceSession session) throws RemoteException {
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
try {
mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -65,9 +64,9 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
mPrimarySurface = mPrimary.token.getLeash();
mSecondarySurface = mSecondary.token.getLeash();
} catch (RemoteException e) {
} catch (Exception e) {
// teardown to prevent callbacks
TaskOrganizer.unregisterOrganizer(this);
unregisterOrganizer();
throw e;
}
mSplitScreenSupported = true;
@@ -98,14 +97,6 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
mDivider.mTransactionPool.release(t);
}
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo) {
}
@Override
public void onTaskVanished(RunningTaskInfo taskInfo) {
}
@Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
if (taskInfo.displayId != DEFAULT_DISPLAY) {

View File

@@ -20,7 +20,6 @@ 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.view.Display.DEFAULT_DISPLAY;
import static android.window.WindowOrganizer.TaskOrganizer;
import android.annotation.NonNull;
import android.app.ActivityManager;
@@ -30,7 +29,8 @@ import android.os.RemoteException;
import android.util.Log;
import android.view.Display;
import android.view.WindowManagerGlobal;
import android.window.IWindowContainer;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
@@ -112,27 +112,21 @@ public class WindowManagerProxy {
static void applyResizeSplits(int position, SplitDisplayLayout splitLayout) {
WindowContainerTransaction t = new WindowContainerTransaction();
splitLayout.resizeSplits(position, t);
try {
WindowOrganizer.applyTransaction(t);
} catch (RemoteException e) {
}
WindowOrganizer.applyTransaction(t);
}
private static boolean getHomeAndRecentsTasks(List<IWindowContainer> out,
IWindowContainer parent) {
private static boolean getHomeAndRecentsTasks(List<WindowContainerToken> out,
WindowContainerToken parent) {
boolean resizable = false;
try {
List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
: TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
for (int i = 0, n = rootTasks.size(); i < n; ++i) {
final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
out.add(ti.token);
if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
resizable = ti.isResizable();
}
List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
: TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
for (int i = 0, n = rootTasks.size(); i < n; ++i) {
final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
out.add(ti.token);
if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
resizable = ti.isResizable();
}
} catch (RemoteException e) {
}
return resizable;
}
@@ -142,11 +136,11 @@ public class WindowManagerProxy {
* split is minimized. This actually "sticks out" of the secondary split area, but when in
* minimized mode, the secondary split gets a 'negative' crop to expose it.
*/
static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent,
static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent,
@NonNull WindowContainerTransaction wct) {
// Resize the home/recents stacks to the larger minimized-state size
final Rect homeBounds;
final ArrayList<IWindowContainer> homeStacks = new ArrayList<>();
final ArrayList<WindowContainerToken> homeStacks = new ArrayList<>();
boolean isHomeResizable = getHomeAndRecentsTasks(homeStacks, parent);
if (isHomeResizable) {
homeBounds = layout.calcMinimizedHomeStackBounds();
@@ -170,36 +164,31 @@ public class WindowManagerProxy {
* @return whether the home stack is resizable
*/
static boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) {
try {
// Set launchtile first so that any stack created after
// getAllStackInfos and before reparent (even if unlikely) are placed
// correctly.
TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
List<ActivityManager.RunningTaskInfo> rootTasks =
TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
WindowContainerTransaction wct = new WindowContainerTransaction();
if (rootTasks.isEmpty()) {
return false;
}
tiles.mHomeAndRecentsSurfaces.clear();
for (int i = rootTasks.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
if (isHomeOrRecentTask(rootTask)) {
tiles.mHomeAndRecentsSurfaces.add(rootTask.token.getLeash());
}
if (rootTask.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_FULLSCREEN) {
continue;
}
wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */);
}
boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
WindowOrganizer.applyTransaction(wct);
return isHomeResizable;
} catch (RemoteException e) {
Log.w(TAG, "Error moving fullscreen tasks to secondary split: " + e);
// Set launchtile first so that any stack created after
// getAllStackInfos and before reparent (even if unlikely) are placed
// correctly.
TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
List<ActivityManager.RunningTaskInfo> rootTasks =
TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
WindowContainerTransaction wct = new WindowContainerTransaction();
if (rootTasks.isEmpty()) {
return false;
}
return false;
tiles.mHomeAndRecentsSurfaces.clear();
for (int i = rootTasks.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
if (isHomeOrRecentTask(rootTask)) {
tiles.mHomeAndRecentsSurfaces.add(rootTask.token.getLeash());
}
if (rootTask.configuration.windowConfiguration.getWindowingMode()
!= WINDOWING_MODE_FULLSCREEN) {
continue;
}
wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */);
}
boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
WindowOrganizer.applyTransaction(wct);
return isHomeResizable;
}
private static boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) {
@@ -214,82 +203,70 @@ public class WindowManagerProxy {
* fullscreen. {@code false} resolves the other way.
*/
static void applyDismissSplit(SplitScreenTaskOrganizer tiles, boolean dismissOrMaximize) {
try {
// Set launch root first so that any task created after getChildContainers and
// before reparent (pretty unlikely) are put into fullscreen.
TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
tiles.mHomeAndRecentsSurfaces.clear();
// TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
// plus specific APIs to clean this up.
List<ActivityManager.RunningTaskInfo> primaryChildren =
TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
List<ActivityManager.RunningTaskInfo> secondaryChildren =
TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
// In some cases (eg. non-resizable is launched), system-server will leave split-screen.
// as a result, the above will not capture any tasks; yet, we need to clean-up the
// home task bounds.
List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
&& freeHomeAndRecents.isEmpty()) {
return;
// Set launch root first so that any task created after getChildContainers and
// before reparent (pretty unlikely) are put into fullscreen.
TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
tiles.mHomeAndRecentsSurfaces.clear();
// TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
// plus specific APIs to clean this up.
List<ActivityManager.RunningTaskInfo> primaryChildren =
TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
List<ActivityManager.RunningTaskInfo> secondaryChildren =
TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
// In some cases (eg. non-resizable is launched), system-server will leave split-screen.
// as a result, the above will not capture any tasks; yet, we need to clean-up the
// home task bounds.
List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
&& freeHomeAndRecents.isEmpty()) {
return;
}
WindowContainerTransaction wct = new WindowContainerTransaction();
if (dismissOrMaximize) {
// Dismissing, so move all primary split tasks first
for (int i = primaryChildren.size() - 1; i >= 0; --i) {
wct.reparent(primaryChildren.get(i).token, null /* parent */,
true /* onTop */);
}
WindowContainerTransaction wct = new WindowContainerTransaction();
if (dismissOrMaximize) {
// Dismissing, so move all primary split tasks first
for (int i = primaryChildren.size() - 1; i >= 0; --i) {
wct.reparent(primaryChildren.get(i).token, null /* parent */,
true /* onTop */);
// Don't need to worry about home tasks because they are already in the "proper"
// order within the secondary split.
for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
wct.reparent(ti.token, null /* parent */, true /* onTop */);
if (isHomeOrRecentTask(ti)) {
wct.setBounds(ti.token, null);
}
// Don't need to worry about home tasks because they are already in the "proper"
// order within the secondary split.
for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
}
} else {
// Maximize, so move non-home secondary split first
for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
if (isHomeOrRecentTask(secondaryChildren.get(i))) {
continue;
}
wct.reparent(secondaryChildren.get(i).token, null /* parent */,
true /* onTop */);
}
// Find and place home tasks in-between. This simulates the fact that there was
// nothing behind the primary split's tasks.
for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
if (isHomeOrRecentTask(ti)) {
wct.reparent(ti.token, null /* parent */, true /* onTop */);
if (isHomeOrRecentTask(ti)) {
wct.setBounds(ti.token, null);
}
}
} else {
// Maximize, so move non-home secondary split first
for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
if (isHomeOrRecentTask(secondaryChildren.get(i))) {
continue;
}
wct.reparent(secondaryChildren.get(i).token, null /* parent */,
true /* onTop */);
}
// Find and place home tasks in-between. This simulates the fact that there was
// nothing behind the primary split's tasks.
for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
if (isHomeOrRecentTask(ti)) {
wct.reparent(ti.token, null /* parent */, true /* onTop */);
// reset bounds too
wct.setBounds(ti.token, null);
}
}
for (int i = primaryChildren.size() - 1; i >= 0; --i) {
wct.reparent(primaryChildren.get(i).token, null /* parent */,
true /* onTop */);
// reset bounds too
wct.setBounds(ti.token, null);
}
}
for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
wct.setBounds(freeHomeAndRecents.get(i).token, null);
for (int i = primaryChildren.size() - 1; i >= 0; --i) {
wct.reparent(primaryChildren.get(i).token, null /* parent */,
true /* onTop */);
}
// Reset focusable to true
wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.w(TAG, "Failed to remove stack: " + e);
}
}
static void applyContainerTransaction(WindowContainerTransaction wct) {
try {
WindowOrganizer.applyTransaction(wct);
} catch (RemoteException e) {
Log.w(TAG, "Error setting focusability: " + e);
for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
wct.setBounds(freeHomeAndRecents.get(i).token, null);
}
// Reset focusable to true
wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
WindowOrganizer.applyTransaction(wct);
}
}

View File

@@ -2802,7 +2802,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
false /* includingParents */);
}
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(task.getStack().mRemoteToken, primarySplitTask.mRemoteToken, toTop);
wct.reparent(task.getStack().mRemoteToken.toWindowContainerToken(),
primarySplitTask.mRemoteToken.toWindowContainerToken(), toTop);
mWindowOrganizerController.applyTransaction(wct);
}
@@ -4291,7 +4292,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
tempDockedTaskInsetBounds != null ? tempDockedTaskInsetBounds
: (tempDockedTaskBounds != null ? tempDockedTaskBounds
: dockedBounds);
wct.setBounds(primary.mRemoteToken, primaryRect);
wct.setBounds(primary.mRemoteToken.toWindowContainerToken(), primaryRect);
Rect otherRect = tempOtherTaskInsetBounds != null ? tempOtherTaskInsetBounds
: tempOtherTaskBounds;
if (otherRect == null) {
@@ -4303,7 +4304,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
otherRect.top = primaryRect.bottom + 6;
}
}
wct.setBounds(secondary.mRemoteToken, otherRect);
wct.setBounds(secondary.mRemoteToken.toWindowContainerToken(), otherRect);
mWindowOrganizerController.applyTransaction(wct);
}
} finally {

View File

@@ -16,10 +16,6 @@
package com.android.server.wm;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.window.ITaskOrganizer;
import android.view.SurfaceControl;
import java.util.HashMap;
@@ -50,7 +46,7 @@ class BLASTSyncEngine {
private static final String TAG = "BLASTSyncEngine";
interface TransactionReadyListener {
void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction);
void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction);
};
// Holds state associated with a single synchronous set of operations.
@@ -63,12 +59,12 @@ class BLASTSyncEngine {
private void tryFinish() {
if (mRemainingTransactions == 0 && mReady) {
mListener.transactionReady(mSyncId, mMergedTransaction);
mListener.onTransactionReady(mSyncId, mMergedTransaction);
mPendingSyncs.remove(mSyncId);
}
}
public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
mRemainingTransactions--;
mMergedTransaction.merge(mergedTransaction);
tryFinish();

View File

@@ -21,9 +21,9 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_UNDEFINED;
import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
import static com.android.internal.util.Preconditions.checkState;
import static com.android.server.wm.DisplayAreaProto.NAME;

View File

@@ -94,7 +94,7 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl
void onDisplayAreaAppeared(IDisplayAreaOrganizer organizer, DisplayArea da) {
try {
organizer.onDisplayAreaAppeared(da.mRemoteToken);
organizer.onDisplayAreaAppeared(da.mRemoteToken.toWindowContainerToken());
} catch (RemoteException e) {
// Oh well...
}
@@ -102,7 +102,7 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl
void onDisplayAreaVanished(IDisplayAreaOrganizer organizer, DisplayArea da) {
try {
organizer.onDisplayAreaVanished(da.mRemoteToken);
organizer.onDisplayAreaVanished(da.mRemoteToken.toWindowContainerToken());
} catch (RemoteException e) {
// Oh well...
}

View File

@@ -87,8 +87,8 @@ class DisplayAreaPolicyBuilder {
*
* Must be unique among the features added to a {@link DisplayAreaPolicyBuilder}.
*
* @see android.window.WindowOrganizer.DisplayAreaOrganizer#FEATURE_SYSTEM_FIRST
* @see android.window.WindowOrganizer.DisplayAreaOrganizer#FEATURE_VENDOR_FIRST
* @see android.window.DisplayAreaOrganizer#FEATURE_SYSTEM_FIRST
* @see android.window.DisplayAreaOrganizer#FEATURE_VENDOR_FIRST
*/
public int getId() {
return mId;

View File

@@ -2346,7 +2346,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
stack.getBounds(info.bounds);
info.displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId() : INVALID_DISPLAY;
info.stackId = stack.mTaskId;
info.stackToken = stack.mRemoteToken;
info.stackToken = stack.mRemoteToken.toWindowContainerToken();
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.

View File

@@ -478,7 +478,7 @@ class Task extends WindowContainer<WindowContainer> {
/**
* The TaskOrganizer which is delegated presentation of this task. If set the Task will
* emit an IWindowContainer (allowing access to it's SurfaceControl leash) to the organizers
* emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
* taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
*/
ITaskOrganizer mTaskOrganizer;
@@ -3435,7 +3435,7 @@ class Task extends WindowContainer<WindowContainer> {
info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
info.configuration.setTo(getConfiguration());
info.token = mRemoteToken;
info.token = mRemoteToken.toWindowContainerToken();
//TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
// order changes.

View File

@@ -31,7 +31,7 @@ import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
import static android.window.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
@@ -1183,7 +1183,8 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> {
for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
final Task root = mTmpTasks.get(i);
for (int j = 0; j < root.getChildCount(); j++) {
wct.reparent(root.getChildAt(j).mRemoteToken, null, true /* toTop */);
wct.reparent(root.getChildAt(j).mRemoteToken.toWindowContainerToken(),
null, true /* toTop */);
}
}
mAtmService.mWindowOrganizerController.applyTransaction(wct);

View File

@@ -36,7 +36,7 @@ import android.util.Slog;
import android.util.SparseArray;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
import com.android.internal.util.ArrayUtils;
@@ -290,7 +290,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
@Override
public boolean deleteRootTask(IWindowContainer token) {
public boolean deleteRootTask(WindowContainerToken token) {
enforceStackPermission("deleteRootTask()");
final long origId = Binder.clearCallingIdentity();
try {
@@ -367,7 +367,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
@Override
public IWindowContainer getImeTarget(int displayId) {
public WindowContainerToken getImeTarget(int displayId) {
enforceStackPermission("getImeTarget()");
final long origId = Binder.clearCallingIdentity();
try {
@@ -382,7 +382,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
if (task == null) {
return null;
}
return task.getRootTask().mRemoteToken;
return task.getRootTask().mRemoteToken.toWindowContainerToken();
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -390,7 +390,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
@Override
public void setLaunchRoot(int displayId, @Nullable IWindowContainer token) {
public void setLaunchRoot(int displayId, @Nullable WindowContainerToken token) {
enforceStackPermission("setLaunchRoot()");
final long origId = Binder.clearCallingIdentity();
try {
@@ -422,7 +422,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
}
@Override
public List<RunningTaskInfo> getChildTasks(IWindowContainer parent,
public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent,
@Nullable int[] activityTypes) {
enforceStackPermission("getChildTasks()");
final long ident = Binder.clearCallingIdentity();

View File

@@ -76,7 +76,8 @@ import android.view.SurfaceControl.Builder;
import android.view.SurfaceSession;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.window.IWindowContainer;
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
@@ -2449,8 +2450,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return RemoteToken.fromBinder(binder).getContainer();
}
static class RemoteToken extends IWindowContainer.Stub {
static class RemoteToken extends IWindowContainerToken.Stub {
final WeakReference<WindowContainer> mWeakRef;
private WindowContainerToken mWindowContainerToken;
RemoteToken(WindowContainer container) {
mWeakRef = new WeakReference<>(container);
@@ -2476,6 +2479,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return sc;
}
WindowContainerToken toWindowContainerToken() {
if (mWindowContainerToken == null) {
mWindowContainerToken = new WindowContainerToken(this);
}
return mWindowContainerToken;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
@@ -2489,11 +2499,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
@Override
public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
mergedTransaction.merge(mBLASTSyncTransaction);
mUsingBLASTSyncTransaction = false;
mWaitingListener.transactionReady(mWaitingSyncId, mergedTransaction);
mWaitingListener.onTransactionReady(mWaitingSyncId, mergedTransaction);
mWaitingListener = null;
mWaitingSyncId = -1;

View File

@@ -340,12 +340,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
@Override
public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
final IWindowContainerTransactionCallback callback =
mTransactionCallbacksByPendingSyncId.get(mSyncId);
try {
callback.transactionReady(mSyncId, mergedTransaction);
callback.onTransactionReady(mSyncId, mergedTransaction);
} catch (RemoteException e) {
}

View File

@@ -5723,7 +5723,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (mLocalSyncId >= 0) {
mBLASTSyncEngine.setReady(mLocalSyncId);
} else {
mWaitingListener.transactionReady(mWaitingSyncId, mBLASTSyncTransaction);
mWaitingListener.onTransactionReady(mWaitingSyncId, mBLASTSyncTransaction);
}
mUsingBLASTSyncTransaction = false;

View File

@@ -83,7 +83,7 @@ import android.platform.test.annotations.Presubmit;
import android.service.voice.IVoiceInteractionSession;
import android.view.Gravity;
import android.window.ITaskOrganizer;
import android.window.IWindowContainer;
import android.window.WindowContainerToken;
import androidx.test.filters.SmallTest;
@@ -1014,10 +1014,10 @@ public class ActivityStarterTests extends ActivityTestsBase {
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mService.mTaskOrganizerController.registerTaskOrganizer(this,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
IWindowContainer primary = mService.mTaskOrganizerController.createRootTask(
WindowContainerToken primary = mService.mTaskOrganizerController.createRootTask(
displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token;
mPrimary = WindowContainer.fromBinder(primary.asBinder()).asTask();
IWindowContainer secondary = mService.mTaskOrganizerController.createRootTask(
WindowContainerToken secondary = mService.mTaskOrganizerController.createRootTask(
displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token;
mSecondary = WindowContainer.fromBinder(secondary.asBinder()).asTask();
}
@@ -1037,7 +1037,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
== WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mInSplit = true;
mService.mTaskOrganizerController.setLaunchRoot(mDisplayId,
mSecondary.mRemoteToken);
mSecondary.mRemoteToken.toWindowContainerToken());
// move everything to secondary because test expects this but usually sysui
// does it.
DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);

View File

@@ -26,6 +26,8 @@ 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.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -282,7 +284,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
final Task task = stack.getTopMostTask();
WindowContainerTransaction t = new WindowContainerTransaction();
Rect newBounds = new Rect(10, 10, 100, 100);
t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertEquals(newBounds, task.getBounds());
}
@@ -295,7 +297,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
StackInfo info =
mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
WindowContainerTransaction t = new WindowContainerTransaction();
assertEquals(stack.mRemoteToken, info.stackToken);
assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.stackToken);
Rect newBounds = new Rect(10, 10, 100, 100);
t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
@@ -308,7 +310,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
final WindowContainerTransaction t = new WindowContainerTransaction();
t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
t.setWindowingMode(stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode());
@@ -320,8 +322,9 @@ public class TaskOrganizerTests extends WindowTestsBase {
final ActivityStack stack = record.getStack();
final WindowContainerTransaction t = new WindowContainerTransaction();
t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED);
t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
t.setWindowingMode(stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_PINNED);
t.setActivityWindowingMode(
stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
@@ -336,10 +339,10 @@ public class TaskOrganizerTests extends WindowTestsBase {
final Task task = stack.getTopMostTask();
WindowContainerTransaction t = new WindowContainerTransaction();
assertTrue(task.isFocusable());
t.setFocusable(stack.mRemoteToken, false);
t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), false);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertFalse(task.isFocusable());
t.setFocusable(stack.mRemoteToken, true);
t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), true);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertTrue(task.isFocusable());
}
@@ -351,10 +354,10 @@ public class TaskOrganizerTests extends WindowTestsBase {
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
WindowContainerTransaction t = new WindowContainerTransaction();
assertTrue(stack.shouldBeVisible(null));
t.setHidden(stack.mRemoteToken, true);
t.setHidden(stack.mRemoteToken.toWindowContainerToken(), true);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertFalse(stack.shouldBeVisible(null));
t.setHidden(stack.mRemoteToken, false);
t.setHidden(stack.mRemoteToken.toWindowContainerToken(), false);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertTrue(stack.shouldBeVisible(null));
}
@@ -366,19 +369,19 @@ public class TaskOrganizerTests extends WindowTestsBase {
.setWindowingMode(WINDOWING_MODE_FREEFORM).build();
final Task task = stack.getTopMostTask();
WindowContainerTransaction t = new WindowContainerTransaction();
t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
final int origScreenWDp = task.getConfiguration().screenHeightDp;
final int origScreenHDp = task.getConfiguration().screenHeightDp;
t = new WindowContainerTransaction();
// verify that setting config overrides on parent restricts children.
t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp);
t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200));
t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), origScreenWDp, origScreenHDp);
t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 150, 200));
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
t = new WindowContainerTransaction();
t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED,
Configuration.SCREEN_HEIGHT_DP_UNDEFINED);
t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED,
SCREEN_HEIGHT_DP_UNDEFINED);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
}
@@ -435,7 +438,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertEquals(info1.configuration.windowConfiguration.getWindowingMode(),
stack.getWindowingMode());
@@ -455,7 +458,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
assertEquals(newSize, stack.getBounds());
wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, null, true /* onTop */);
wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
infos = getTasksCreatedByOrganizer(mDisplayContent);
@@ -495,7 +498,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertTrue(called[0]);
assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
@@ -505,7 +508,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
final ActivityStack stack2 = createTaskStackOnDisplay(
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
wct = new WindowContainerTransaction();
wct.reparent(stack2.mRemoteToken, info1.token, true /* onTop */);
wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertTrue(called[0]);
assertEquals(ACTIVITY_TYPE_HOME, lastReportedTiles.get(0).topActivityType);
@@ -519,8 +522,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
lastReportedTiles.clear();
called[0] = false;
wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, null, true /* onTop */);
wct.reparent(stack2.mRemoteToken, null, true /* onTop */);
wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertTrue(called[0]);
assertEquals(ACTIVITY_TYPE_UNDEFINED, lastReportedTiles.get(0).topActivityType);
@@ -569,8 +572,8 @@ public class TaskOrganizerTests extends WindowTestsBase {
lastReportedTiles.clear();
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */);
wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info2.token, true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertFalse(lastReportedTiles.isEmpty());
assertEquals(ACTIVITY_TYPE_STANDARD,
@@ -580,7 +583,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
lastReportedTiles.clear();
wct = new WindowContainerTransaction();
wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */);
wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, false /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertFalse(lastReportedTiles.isEmpty());
// Standard should still be on top of tile 1, so no change there
@@ -605,7 +608,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
lastReportedTiles.clear();
wct = new WindowContainerTransaction();
wct.reorder(stack2.mRemoteToken, true /* onTop */);
wct.reorder(stack2.mRemoteToken.toWindowContainerToken(), true /* onTop */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
// Home should now be on top. No change occurs in second tile, so not reported
assertEquals(1, lastReportedTiles.size());
@@ -641,7 +644,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
bse.setReady(id);
// Since this task has no windows the sync is trivial and completes immediately.
verify(transactionListener)
.transactionReady(anyInt(), any());
.onTransactionReady(anyInt(), any());
}
@Test
@@ -691,10 +694,10 @@ public class TaskOrganizerTests extends WindowTestsBase {
bse.setReady(id);
// Since we have a window we have to wait for it to draw to finish sync.
verify(transactionListener, never())
.transactionReady(anyInt(), any());
.onTransactionReady(anyInt(), any());
w.finishDrawing(null);
verify(transactionListener)
.transactionReady(anyInt(), any());
.onTransactionReady(anyInt(), any());
}
@Test
@@ -716,7 +719,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
// Since the window was invisible, the Task had no visible leaves and the sync should
// complete as soon as we call setReady.
verify(transactionListener)
.transactionReady(anyInt(), any());
.onTransactionReady(anyInt(), any());
}
@Test
@@ -742,13 +745,13 @@ public class TaskOrganizerTests extends WindowTestsBase {
// Since we have a child window we still shouldn't be done.
verify(transactionListener, never())
.transactionReady(anyInt(), any());
.onTransactionReady(anyInt(), any());
reset(transactionListener);
child.finishDrawing(null);
// Ah finally! Done
verify(transactionListener)
.transactionReady(anyInt(), any());
.onTransactionReady(anyInt(), any());
}
class StubOrganizer extends ITaskOrganizer.Stub {

View File

@@ -17,10 +17,9 @@
package com.android.test.taskembed;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.window.WindowOrganizer.TaskOrganizer;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Activity;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
@@ -35,10 +34,12 @@ import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.window.ITaskOrganizer;
import android.window.IWindowContainerTransactionCallback;
import android.window.TaskOrganizer;
import android.window.WindowContainerTransaction;
import android.widget.LinearLayout;
import android.window.WindowContainerTransactionCallback;
import android.window.WindowOrganizer;
public class TaskOrganizerMultiWindowTest extends Activity {
@@ -97,7 +98,7 @@ public class TaskOrganizerMultiWindowTest extends Activity {
class ResizingTaskView extends TaskView {
final Intent mIntent;
boolean launched = false;
ResizingTaskView(Context c, ITaskOrganizer o, int windowingMode, Intent i) {
ResizingTaskView(Context c, TaskOrganizer o, int windowingMode, Intent i) {
super(c, o, windowingMode);
mIntent = i;
}
@@ -116,7 +117,7 @@ public class TaskOrganizerMultiWindowTest extends Activity {
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setBounds(mWc, new Rect(0, 0, width, height));
try {
WindowOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
mOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
} catch (Exception e) {
// Oh well
}
@@ -127,14 +128,13 @@ public class TaskOrganizerMultiWindowTest extends Activity {
TaskView mTaskView2;
boolean gotFirstTask = false;
class Organizer extends ITaskOrganizer.Stub {
class Organizer extends TaskOrganizer {
private int receivedTransactions = 0;
SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
IWindowContainerTransactionCallback mTransactionCallback =
new IWindowContainerTransactionCallback() {
WindowContainerTransactionCallback mTransactionCallback =
new WindowContainerTransactionCallback() {
@Override
public void transactionReady(int id, SurfaceControl.Transaction t)
throws RemoteException {
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
mergedTransaction.merge(t);
receivedTransactions++;
if (receivedTransactions == 2) {
@@ -142,11 +142,6 @@ public class TaskOrganizerMultiWindowTest extends Activity {
receivedTransactions = 0;
}
}
@Override
public IBinder asBinder() {
return null;
}
};
@Override
@@ -158,14 +153,6 @@ public class TaskOrganizerMultiWindowTest extends Activity {
mTaskView2.reparentTask(ti.token);
}
}
public void onTaskVanished(ActivityManager.RunningTaskInfo ti) {
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
}
@Override
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
}
}
Organizer mOrganizer = new Organizer();
@@ -174,10 +161,7 @@ public class TaskOrganizerMultiWindowTest extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_MULTI_WINDOW);
} catch (Exception e) {
}
mOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW);
mTaskView1 = new ResizingTaskView(this, mOrganizer, WINDOWING_MODE_MULTI_WINDOW,
makeSettingsIntent());

View File

@@ -17,7 +17,6 @@
package com.android.test.taskembed;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.window.WindowOrganizer.TaskOrganizer;
import android.app.ActivityManager;
import android.app.Service;
@@ -25,11 +24,10 @@ import android.content.Intent;
import android.graphics.Rect;
import android.os.IBinder;
import android.view.ViewGroup;
import android.window.TaskOrganizer;
import android.window.WindowContainerTransaction;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.window.ITaskOrganizer;
import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer;
public class TaskOrganizerPipTest extends Service {
static final int PIP_WIDTH = 640;
@@ -37,23 +35,13 @@ public class TaskOrganizerPipTest extends Service {
TaskView mTaskView;
class Organizer extends ITaskOrganizer.Stub {
class Organizer extends TaskOrganizer {
public void onTaskAppeared(ActivityManager.RunningTaskInfo ti) {
mTaskView.reparentTask(ti.token);
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.scheduleFinishEnterPip(ti.token, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT));
try {
WindowOrganizer.applyTransaction(wct);
} catch (Exception e) {
}
}
public void onTaskVanished(ActivityManager.RunningTaskInfo ti) {
}
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
}
@Override
public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
applyTransaction(wct);
}
}
@@ -68,10 +56,7 @@ public class TaskOrganizerPipTest extends Service {
public void onCreate() {
super.onCreate();
try {
TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_PINNED);
} catch (Exception e) {
}
mOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
final WindowManager.LayoutParams wlp = new WindowManager.LayoutParams();
wlp.setTitle("TaskOrganizerPipTest");

View File

@@ -18,7 +18,8 @@ package com.android.test.taskembed;
import android.app.ActivityTaskManager;
import android.content.Context;
import android.window.IWindowContainer;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@@ -29,14 +30,14 @@ import android.window.ITaskOrganizer;
* after it's Surface is ready.
*/
class TaskView extends SurfaceView implements SurfaceHolder.Callback {
final ITaskOrganizer mTaskOrganizer;
final TaskOrganizer mTaskOrganizer;
final int mWindowingMode;
IWindowContainer mWc;
WindowContainerToken mWc;
boolean mSurfaceCreated = false;
boolean mNeedsReparent;
TaskView(Context c, ITaskOrganizer o, int windowingMode) {
TaskView(Context c, TaskOrganizer o, int windowingMode) {
super(c);
getHolder().addCallback(this);
setZOrderOnTop(true);
@@ -62,7 +63,7 @@ class TaskView extends SurfaceView implements SurfaceHolder.Callback {
public void surfaceDestroyed(SurfaceHolder holder) {
}
void reparentTask(IWindowContainer wc) {
void reparentTask(WindowContainerToken wc) {
mWc = wc;
if (mSurfaceCreated == false) {
mNeedsReparent = true;