Merge changes from topic "task_fragment_organizer" into sc-v2-dev

* changes:
  Implement WCT#create/deleteTaskFragment
  Add TaskFragmentOrganizer API
  Add WindowContainerTransaction APIs for create/deleteTaskFragment
This commit is contained in:
Chris Li
2021-06-23 04:44:23 +00:00
committed by Android (Google) Code Review
16 changed files with 1107 additions and 19 deletions

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2021 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.content.res.Configuration;
import android.os.IBinder;
import android.window.TaskFragmentAppearedInfo;
import android.window.TaskFragmentInfo;
/** @hide */
oneway interface ITaskFragmentOrganizer {
void onTaskFragmentAppeared(in TaskFragmentAppearedInfo taskFragmentAppearedInfo);
void onTaskFragmentInfoChanged(in TaskFragmentInfo taskFragmentInfo);
void onTaskFragmentVanished(in TaskFragmentInfo taskFragmentInfo);
/**
* Called when the parent leaf Task of organized TaskFragments is changed.
* When the leaf Task is changed, the organizer may want to update the TaskFragments in one
* transaction.
*
* For case like screen size change, it will trigger onTaskFragmentParentInfoChanged with new
* Task bounds, but may not trigger onTaskFragmentInfoChanged because there can be an override
* bounds.
*/
void onTaskFragmentParentInfoChanged(in IBinder fragmentToken, in Configuration parentConfig);
}

View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2021 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.window.ITaskFragmentOrganizer;
/** @hide */
interface ITaskFragmentOrganizerController {
/**
* Registers a TaskFragmentOrganizer to manage TaskFragments.
*/
void registerOrganizer(in ITaskFragmentOrganizer organizer);
/**
* Unregisters a previously registered TaskFragmentOrganizer.
*/
void unregisterOrganizer(in ITaskFragmentOrganizer organizer);
}

View File

@@ -20,6 +20,7 @@ import android.view.SurfaceControl;
import android.os.IBinder;
import android.window.IDisplayAreaOrganizerController;
import android.window.ITaskFragmentOrganizerController;
import android.window.ITaskOrganizerController;
import android.window.ITransitionPlayer;
import android.window.IWindowContainerTransactionCallback;
@@ -77,6 +78,9 @@ interface IWindowOrganizerController {
/** @return An interface enabling the management of display area organizers. */
IDisplayAreaOrganizerController getDisplayAreaOrganizerController();
/** @return An interface enabling the management of task fragment organizers. */
ITaskFragmentOrganizerController getTaskFragmentOrganizerController();
/**
* Registers a transition player with Core. There is only one of these at a time and calling
* this will replace the existing one if set.

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2021 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;
/**
* Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
* @hide
*/
parcelable TaskFragmentAppearedInfo;

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2021 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.os.Parcel;
import android.os.Parcelable;
import android.view.SurfaceControl;
/**
* Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
* @hide
*/
public final class TaskFragmentAppearedInfo implements Parcelable {
@NonNull
private final TaskFragmentInfo mTaskFragmentInfo;
@NonNull
private final SurfaceControl mLeash;
public TaskFragmentAppearedInfo(
@NonNull TaskFragmentInfo taskFragmentInfo, @NonNull SurfaceControl leash) {
mTaskFragmentInfo = taskFragmentInfo;
mLeash = leash;
}
public TaskFragmentInfo getTaskFragmentInfo() {
return mTaskFragmentInfo;
}
public SurfaceControl getLeash() {
return mLeash;
}
private TaskFragmentAppearedInfo(Parcel in) {
mTaskFragmentInfo = in.readTypedObject(TaskFragmentInfo.CREATOR);
mLeash = in.readTypedObject(SurfaceControl.CREATOR);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(mTaskFragmentInfo, flags);
dest.writeTypedObject(mLeash, flags);
}
@NonNull
public static final Creator<TaskFragmentAppearedInfo> CREATOR =
new Creator<TaskFragmentAppearedInfo>() {
@Override
public TaskFragmentAppearedInfo createFromParcel(Parcel in) {
return new TaskFragmentAppearedInfo(in);
}
@Override
public TaskFragmentAppearedInfo[] newArray(int size) {
return new TaskFragmentAppearedInfo[size];
}
};
@Override
public String toString() {
return "TaskFragmentAppearedInfo{"
+ " taskFragmentInfo=" + mTaskFragmentInfo
+ "}";
}
@Override
public int describeContents() {
return 0;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2021 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;
/**
* Data object for options to create TaskFragment with.
* @hide
*/
parcelable TaskFragmentCreationParams;

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2021 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.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Data object for options to create TaskFragment with.
* @hide
*/
public final class TaskFragmentCreationParams implements Parcelable {
/** The organizer that will organize this TaskFragment. */
@NonNull
private final ITaskFragmentOrganizer mOrganizer;
/**
* Unique token assigned from the client organizer to identify the {@link TaskFragmentInfo} when
* a new TaskFragment is created with this option.
*/
@NonNull
private final IBinder mFragmentToken;
/**
* Activity token used to identify the leaf Task to create the TaskFragment in. It has to belong
* to the same app as the root Activity of the target Task.
*/
@NonNull
private final IBinder mOwnerToken;
/** The initial bounds of the TaskFragment. Fill parent if empty. */
@NonNull
private final Rect mInitialBounds = new Rect();
private TaskFragmentCreationParams(
@NonNull ITaskFragmentOrganizer organizer, @NonNull IBinder fragmentToken,
@NonNull IBinder ownerToken, @NonNull Rect initialBounds) {
mOrganizer = organizer;
mFragmentToken = fragmentToken;
mOwnerToken = ownerToken;
mInitialBounds.set(initialBounds);
}
public ITaskFragmentOrganizer getOrganizer() {
return mOrganizer;
}
public IBinder getFragmentToken() {
return mFragmentToken;
}
public IBinder getOwnerToken() {
return mOwnerToken;
}
public Rect getInitialBounds() {
return mInitialBounds;
}
private TaskFragmentCreationParams(Parcel in) {
mOrganizer = ITaskFragmentOrganizer.Stub.asInterface(in.readStrongBinder());
mFragmentToken = in.readStrongBinder();
mOwnerToken = in.readStrongBinder();
mInitialBounds.readFromParcel(in);
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStrongInterface(mOrganizer);
dest.writeStrongBinder(mFragmentToken);
dest.writeStrongBinder(mOwnerToken);
mInitialBounds.writeToParcel(dest, flags);
}
@NonNull
public static final Creator<TaskFragmentCreationParams> CREATOR =
new Creator<TaskFragmentCreationParams>() {
@Override
public TaskFragmentCreationParams createFromParcel(Parcel in) {
return new TaskFragmentCreationParams(in);
}
@Override
public TaskFragmentCreationParams[] newArray(int size) {
return new TaskFragmentCreationParams[size];
}
};
@Override
public String toString() {
return "TaskFragmentCreationParams{"
+ " organizer=" + mOrganizer
+ " fragmentToken=" + mFragmentToken
+ " ownerToken=" + mOwnerToken
+ " initialBounds=" + mInitialBounds
+ "}";
}
@Override
public int describeContents() {
return 0;
}
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2021 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;
/**
* Stores information about a particular TaskFragment.
* @hide
*/
parcelable TaskFragmentInfo;

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2021 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.content.ComponentName;
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Stores information about a particular TaskFragment.
* @hide
*/
public final class TaskFragmentInfo implements Parcelable {
/**
* Client assigned unique token in {@link TaskFragmentCreationParams#fragmentToken} to create
* this TaskFragment with.
*/
@NonNull
private final IBinder mFragmentToken;
/**
* The component name of the initial root activity of this TaskFragment, which will be used
* to configure the relationships for TaskFragments.
*/
@NonNull
private final ComponentName mInitialComponentName;
@NonNull
private final WindowContainerToken mToken;
@NonNull
private final Configuration mConfiguration = new Configuration();
/** Whether the TaskFragment contains any child Activity. */
private final boolean mIsEmpty;
/** Whether this TaskFragment is visible on the window hierarchy. */
private final boolean mIsVisible;
public TaskFragmentInfo(
@NonNull IBinder fragmentToken, @NonNull ComponentName initialComponentName,
@NonNull WindowContainerToken token, @NonNull Configuration configuration,
boolean isEmpty, boolean isVisible) {
if (fragmentToken == null || initialComponentName == null) {
throw new IllegalArgumentException("Invalid TaskFragmentInfo.");
}
mFragmentToken = fragmentToken;
mInitialComponentName = initialComponentName;
mToken = token;
mConfiguration.setTo(configuration);
mIsEmpty = isEmpty;
mIsVisible = isVisible;
}
public IBinder getFragmentToken() {
return mFragmentToken;
}
public ComponentName getInitialComponentName() {
return mInitialComponentName;
}
public WindowContainerToken getToken() {
return mToken;
}
public Configuration getConfiguration() {
return mConfiguration;
}
public boolean isEmpty() {
return mIsEmpty;
}
public boolean isVisible() {
return mIsVisible;
}
private TaskFragmentInfo(Parcel in) {
mFragmentToken = in.readStrongBinder();
mInitialComponentName = in.readTypedObject(ComponentName.CREATOR);
mToken = in.readTypedObject(WindowContainerToken.CREATOR);
mConfiguration.readFromParcel(in);
mIsEmpty = in.readBoolean();
mIsVisible = in.readBoolean();
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStrongBinder(mFragmentToken);
dest.writeTypedObject(mInitialComponentName, flags);
dest.writeTypedObject(mToken, flags);
mConfiguration.writeToParcel(dest, flags);
dest.writeBoolean(mIsEmpty);
dest.writeBoolean(mIsVisible);
}
@NonNull
public static final Creator<TaskFragmentInfo> CREATOR =
new Creator<TaskFragmentInfo>() {
@Override
public TaskFragmentInfo createFromParcel(Parcel in) {
return new TaskFragmentInfo(in);
}
@Override
public TaskFragmentInfo[] newArray(int size) {
return new TaskFragmentInfo[size];
}
};
@Override
public String toString() {
return "TaskFragmentInfo{"
+ " fragmentToken=" + mFragmentToken
+ " initialComponentName=" + mInitialComponentName
+ " token=" + mToken
+ " isEmpty=" + mIsEmpty
+ " isVisible=" + mIsVisible
+ "}";
}
@Override
public int describeContents() {
return 0;
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2021 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.CallSuper;
import android.annotation.NonNull;
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.RemoteException;
import java.util.concurrent.Executor;
/**
* Interface for WindowManager to delegate control of {@link com.android.server.wm.TaskFragment}.
* @hide
*/
public class TaskFragmentOrganizer extends WindowOrganizer {
/**
* Callbacks from WM Core are posted on this executor.
*/
private final Executor mExecutor;
public TaskFragmentOrganizer(@NonNull Executor executor) {
mExecutor = executor;
}
/**
* Gets the executor to run callbacks on.
*/
@NonNull
public Executor getExecutor() {
return mExecutor;
}
/**
* Registers a TaskFragmentOrganizer to manage TaskFragments.
*/
@CallSuper
public void registerOrganizer() {
try {
getController().registerOrganizer(mInterface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Unregisters a previously registered TaskFragmentOrganizer.
*/
@CallSuper
public void unregisterOrganizer() {
try {
getController().unregisterOrganizer(mInterface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** Called when a TaskFragment is created and organized by this organizer. */
public void onTaskFragmentAppeared(
@NonNull TaskFragmentAppearedInfo taskFragmentAppearedInfo) {}
/** Called when the status of an organized TaskFragment is changed. */
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {}
/** Called when an organized TaskFragment is removed. */
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {}
/**
* Called when the parent leaf Task of organized TaskFragments is changed.
* When the leaf Task is changed, the organizer may want to update the TaskFragments in one
* transaction.
*
* For case like screen size change, it will trigger onTaskFragmentParentInfoChanged with new
* Task bounds, but may not trigger onTaskFragmentInfoChanged because there can be an override
* bounds.
*/
public void onTaskFragmentParentInfoChanged(
@NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {}
private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
@Override
public void onTaskFragmentAppeared(@NonNull TaskFragmentAppearedInfo taskFragmentInfo) {
mExecutor.execute(
() -> TaskFragmentOrganizer.this.onTaskFragmentAppeared(taskFragmentInfo));
}
@Override
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {
mExecutor.execute(
() -> TaskFragmentOrganizer.this.onTaskFragmentInfoChanged(taskFragmentInfo));
}
@Override
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
mExecutor.execute(
() -> TaskFragmentOrganizer.this.onTaskFragmentVanished(taskFragmentInfo));
}
@Override
public void onTaskFragmentParentInfoChanged(
@NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {
mExecutor.execute(
() -> TaskFragmentOrganizer.this.onTaskFragmentParentInfoChanged(
fragmentToken, parentConfig));
}
};
private ITaskFragmentOrganizerController getController() {
try {
return getWindowOrganizerController().getTaskFragmentOrganizerController();
} catch (RemoteException e) {
return null;
}
}
}

View File

@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -325,7 +326,8 @@ public final class WindowContainerTransaction implements Parcelable {
/**
* Sets to containers adjacent to each other. Containers below two visible adjacent roots will
* be made invisible. This currently only applies to Task containers created by organizer.
* be made invisible. This currently only applies to TaskFragment containers created by
* organizer.
* @param root1 the first root.
* @param root2 the second root.
*/
@@ -377,6 +379,102 @@ public final class WindowContainerTransaction implements Parcelable {
return this;
}
/**
* Creates a new TaskFragment with the given options.
* @param taskFragmentOptions the options used to create the TaskFragment.
* @hide
*/
@NonNull
public WindowContainerTransaction createTaskFragment(
@NonNull TaskFragmentCreationParams taskFragmentOptions) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT)
.setTaskFragmentCreationOptions(taskFragmentOptions)
.build();
mHierarchyOps.add(hierarchyOp);
return this;
}
/**
* Deletes an existing TaskFragment. Any remaining activities below it will be destroyed.
* @param taskFragment the TaskFragment to be removed.
* @hide
*/
@NonNull
public WindowContainerTransaction deleteTaskFragment(
@NonNull WindowContainerToken taskFragment) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT)
.setContainer(taskFragment.asBinder())
.build();
mHierarchyOps.add(hierarchyOp);
return this;
}
/**
* Starts an activity in the TaskFragment.
* @param fragmentToken client assigned unique token to create TaskFragment with specified in
* {@link TaskFragmentCreationParams#fragmentToken}.
* @param activityIntent intent to start the activity.
* @param activityOptions ActivityOptions to start the activity with.
* @see android.content.Context#startActivity(Intent, Bundle).
* @hide
*/
@NonNull
public WindowContainerTransaction startActivityInTaskFragment(
@NonNull IBinder fragmentToken, @NonNull Intent activityIntent,
@Nullable Bundle activityOptions) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(
HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT)
.setContainer(fragmentToken)
.setActivityIntent(activityIntent)
.setLaunchOptions(activityOptions)
.build();
mHierarchyOps.add(hierarchyOp);
return this;
}
/**
* Moves an activity into the TaskFragment.
* @param fragmentToken client assigned unique token to create TaskFragment with specified in
* {@link TaskFragmentCreationParams#fragmentToken}.
* @param activityToken activity to be reparented.
* @hide
*/
@NonNull
public WindowContainerTransaction reparentActivityToTaskFragment(
@NonNull IBinder fragmentToken, @NonNull IBinder activityToken) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(
HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT)
.setReparentContainer(fragmentToken)
.setContainer(activityToken)
.build();
mHierarchyOps.add(hierarchyOp);
return this;
}
/**
* Reparents all children of one TaskFragment to another.
* @param oldParent children of this TaskFragment will be reparented.
* @param newParent the new parent TaskFragment to move the children to. If {@code null}, the
* children will be moved to the leaf Task.
* @hide
*/
@NonNull
public WindowContainerTransaction reparentChildren(
@NonNull WindowContainerToken oldParent,
@Nullable WindowContainerToken newParent) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_CHILDREN)
.setContainer(oldParent.asBinder())
.setReparentContainer(newParent.asBinder())
.build();
mHierarchyOps.add(hierarchyOp);
return this;
}
/**
* Merges another WCT into this one.
* @param transfer When true, this will transfer everything from other potentially leaving
@@ -705,6 +803,11 @@ public final class WindowContainerTransaction implements Parcelable {
public static final int HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS = 4;
public static final int HIERARCHY_OP_TYPE_LAUNCH_TASK = 5;
public static final int HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT = 6;
public static final int HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT = 7;
public static final int HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT = 8;
public static final int HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT = 9;
public static final int HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT = 10;
public static final int HIERARCHY_OP_TYPE_REPARENT_CHILDREN = 11;
// The following key(s) are for use with mLaunchOptions:
// When launching a task (eg. from recents), this is the taskId to be launched.
@@ -732,6 +835,13 @@ public final class WindowContainerTransaction implements Parcelable {
@Nullable
private Bundle mLaunchOptions;
@Nullable
private Intent mActivityIntent;
// Used as options for WindowContainerTransaction#createTaskFragment().
@Nullable
private TaskFragmentCreationParams mTaskFragmentCreationOptions;
public static HierarchyOp createForReparent(
@NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) {
return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT)
@@ -808,6 +918,8 @@ public final class WindowContainerTransaction implements Parcelable {
mWindowingModes = copy.mWindowingModes;
mActivityTypes = copy.mActivityTypes;
mLaunchOptions = copy.mLaunchOptions;
mActivityIntent = copy.mActivityIntent;
mTaskFragmentCreationOptions = copy.mTaskFragmentCreationOptions;
}
protected HierarchyOp(Parcel in) {
@@ -818,6 +930,8 @@ public final class WindowContainerTransaction implements Parcelable {
mWindowingModes = in.createIntArray();
mActivityTypes = in.createIntArray();
mLaunchOptions = in.readBundle();
mActivityIntent = in.readTypedObject(Intent.CREATOR);
mTaskFragmentCreationOptions = in.readTypedObject(TaskFragmentCreationParams.CREATOR);
}
public int getType() {
@@ -860,6 +974,16 @@ public final class WindowContainerTransaction implements Parcelable {
return mLaunchOptions;
}
@Nullable
public Intent getActivityIntent() {
return mActivityIntent;
}
@Nullable
public TaskFragmentCreationParams getTaskFragmentCreationOptions() {
return mTaskFragmentCreationOptions;
}
@Override
public String toString() {
switch (mType) {
@@ -884,6 +1008,19 @@ public final class WindowContainerTransaction implements Parcelable {
case HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT:
return "{SetAdjacentFlagRoot: container=" + mContainer + " clearRoot=" + mToTop
+ "}";
case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT:
return "{CreateTaskFragment: options=" + mTaskFragmentCreationOptions + "}";
case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT:
return "{DeleteTaskFragment: taskFragment=" + mContainer + "}";
case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT:
return "{StartActivityInTaskFragment: fragmentToken=" + mContainer + " intent="
+ mActivityIntent + " options=" + mLaunchOptions + "}";
case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT:
return "{ReparentActivityToTaskFragment: fragmentToken=" + mReparent
+ " activity=" + mContainer + "}";
case HIERARCHY_OP_TYPE_REPARENT_CHILDREN:
return "{ReparentChildren: oldParent=" + mContainer + " newParent=" + mReparent
+ "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop + " mWindowingMode=" + mWindowingModes
@@ -900,6 +1037,8 @@ public final class WindowContainerTransaction implements Parcelable {
dest.writeIntArray(mWindowingModes);
dest.writeIntArray(mActivityTypes);
dest.writeBundle(mLaunchOptions);
dest.writeTypedObject(mActivityIntent, flags);
dest.writeTypedObject(mTaskFragmentCreationOptions, flags);
}
@Override
@@ -940,6 +1079,12 @@ public final class WindowContainerTransaction implements Parcelable {
@Nullable
private Bundle mLaunchOptions;
@Nullable
private Intent mActivityIntent;
@Nullable
private TaskFragmentCreationParams mTaskFragmentCreationOptions;
Builder(int type) {
mType = type;
}
@@ -974,6 +1119,17 @@ public final class WindowContainerTransaction implements Parcelable {
return this;
}
Builder setActivityIntent(@Nullable Intent activityIntent) {
mActivityIntent = activityIntent;
return this;
}
Builder setTaskFragmentCreationOptions(
@Nullable TaskFragmentCreationParams taskFragmentCreationOptions) {
mTaskFragmentCreationOptions = taskFragmentCreationOptions;
return this;
}
HierarchyOp build() {
final HierarchyOp hierarchyOp = new HierarchyOp(mType);
hierarchyOp.mContainer = mContainer;
@@ -986,6 +1142,8 @@ public final class WindowContainerTransaction implements Parcelable {
: null;
hierarchyOp.mToTop = mToTop;
hierarchyOp.mLaunchOptions = mLaunchOptions;
hierarchyOp.mActivityIntent = mActivityIntent;
hierarchyOp.mTaskFragmentCreationOptions = mTaskFragmentCreationOptions;
return hierarchyOp;
}

View File

@@ -721,6 +721,12 @@
"group": "WM_DEBUG_IME",
"at": "com\/android\/server\/wm\/WindowState.java"
},
"-1311436264": {
"message": "Unregister task fragment organizer=%s uid=%d pid=%d",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
},
"-1305966693": {
"message": "Sending position change to %s, onTop: %b",
"level": "VERBOSE",
@@ -1219,6 +1225,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"-706481945": {
"message": "TaskFragment parent info changed name=%s parentTaskId=%d",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
},
"-705939410": {
"message": "Waiting for pause to complete...",
"level": "VERBOSE",
@@ -1381,6 +1393,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowAnimator.java"
},
"-542756093": {
"message": "TaskFragment vanished name=%s",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
},
"-532081937": {
"message": " Commit activity becoming invisible: %s",
"level": "VERBOSE",
@@ -2743,6 +2761,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/TaskFragment.java"
},
"1022095595": {
"message": "TaskFragment info changed name=%s",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
},
"1023413388": {
"message": "Finish waiting for pause of: %s",
"level": "VERBOSE",
@@ -2929,6 +2953,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"1284122013": {
"message": "TaskFragment appeared name=%s",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
},
"1288731814": {
"message": "WindowState.hideLw: setting mFocusMayChange true",
"level": "INFO",
@@ -3223,6 +3253,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
"1653025361": {
"message": "Register task fragment organizer=%s uid=%d pid=%d",
"level": "VERBOSE",
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
},
"1653210583": {
"message": "Removing app %s delayed=%b animation=%s animating=%b",
"level": "VERBOSE",

View File

@@ -602,18 +602,6 @@ class Task extends TaskFragment {
*/
private boolean mForceNotOrganized;
/**
* This task was created by the task organizer which has the following implementations.
* <ul>
* <lis>The task won't be removed when it is empty. Removal has to be an explicit request
* from the task organizer.</li>
* <li>Unlike other non-root tasks, it's direct children are visible to the task
* organizer for ordering purposes.</li>
* </ul>
*/
@VisibleForTesting
boolean mCreatedByOrganizer;
// Tracking cookie for the creation of this task.
IBinder mLaunchCookie;
@@ -641,7 +629,7 @@ class Task extends TaskFragment {
IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear,
boolean _removeWithTaskOrganizer) {
super(atmService);
super(atmService, _createdByOrganizer);
mTaskId = _taskId;
mUserId = _userId;
@@ -693,7 +681,6 @@ class Task extends TaskFragment {
mHandler = new ActivityTaskHandler(mTaskSupervisor.mLooper);
mCurrentUser = mAtmService.mAmInternal.getCurrentUserId();
mCreatedByOrganizer = _createdByOrganizer;
mLaunchCookie = _launchCookie;
mDeferTaskAppear = _deferTaskAppear;
mRemoveWithTaskOrganizer = _removeWithTaskOrganizer;

View File

@@ -74,13 +74,17 @@ import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.NewIntentItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.ComponentName;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.window.ITaskFragmentOrganizer;
import android.window.TaskFragmentInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
@@ -181,6 +185,38 @@ class TaskFragment extends WindowContainer<WindowContainer> {
@Nullable
private ActivityRecord mResumedActivity = null;
/**
* This TaskFragment was created by an organizer which has the following implementations.
* <ul>
* <li>The TaskFragment won't be removed when it is empty. Removal has to be an explicit
* request from the organizer.</li>
* <li>If this fragment is a Task object then unlike other non-root tasks, it's direct
* children are visible to the organizer for ordering purposes.</li>
* <li>A TaskFragment can be created by {@link android.window.TaskFragmentOrganizer}, and
* a Task can be created by {@link android.window.TaskOrganizer}.</li>
* </ul>
*/
@VisibleForTesting
boolean mCreatedByOrganizer;
/** Organizer that organizing this TaskFragment. */
// TODO(b/190433129) set the value when creating TaskFragment from WCT.
@Nullable
private ITaskFragmentOrganizer mTaskFragmentOrganizer;
/** Client assigned unique token for this TaskFragment if this is created by an organizer. */
// TODO(b/190433129) set the value when creating TaskFragment from WCT.
@Nullable
private IBinder mFragmentToken;
/**
* The component name of the root activity that initiated this TaskFragment, which will be used
* to configure the relationships for TaskFragments.
*/
// TODO(b/190433129) set the value when creating TaskFragment from WCT.
@Nullable
private ComponentName mInitialComponentName;
private final Rect mTmpInsets = new Rect();
private final Rect mTmpBounds = new Rect();
private final Rect mTmpFullBounds = new Rect();
@@ -229,12 +265,13 @@ class TaskFragment extends WindowContainer<WindowContainer> {
}
}
TaskFragment(ActivityTaskManagerService atmService) {
TaskFragment(ActivityTaskManagerService atmService, boolean createdByOrganizer) {
super(atmService.mWindowManager);
mAtmService = atmService;
mTaskSupervisor = atmService.mTaskSupervisor;
mRootWindowContainer = mAtmService.mRootWindowContainer;
mCreatedByOrganizer = createdByOrganizer;
}
void setAdjacentTaskFragment(TaskFragment taskFragment) {
@@ -1900,6 +1937,25 @@ class TaskFragment extends WindowContainer<WindowContainer> {
return getTopChild().getActivityType();
}
/**
* Returns a {@link TaskFragmentInfo} with information from this TaskFragment. Should not be
* called from {@link Task}.
*/
TaskFragmentInfo getTaskFragmentInfo() {
return new TaskFragmentInfo(
mFragmentToken,
mInitialComponentName,
mRemoteToken.toWindowContainerToken(),
getConfiguration(),
getChildCount() == 0,
isVisible());
}
@Nullable
IBinder getFragmentToken() {
return mFragmentToken;
}
boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header) {
boolean printed = false;

View File

@@ -0,0 +1,170 @@
/*
* Copyright (C) 2021 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 com.android.server.wm;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.view.SurfaceControl;
import android.window.ITaskFragmentOrganizer;
import android.window.ITaskFragmentOrganizerController;
import android.window.TaskFragmentAppearedInfo;
import com.android.internal.protolog.common.ProtoLog;
import java.util.Map;
import java.util.Set;
/**
* Stores and manages the client {@link android.window.TaskFragmentOrganizer}.
*/
public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerController.Stub {
private static final String TAG = "TaskFragmentOrganizerController";
private final ActivityTaskManagerService mAtmService;
private final WindowManagerGlobalLock mGlobalLock;
private final Set<ITaskFragmentOrganizer> mOrganizers = new ArraySet<>();
private final Map<ITaskFragmentOrganizer, DeathRecipient> mDeathRecipients = new ArrayMap<>();
private class DeathRecipient implements IBinder.DeathRecipient {
final ITaskFragmentOrganizer mOrganizer;
DeathRecipient(ITaskFragmentOrganizer organizer) {
mOrganizer = organizer;
}
@Override
public void binderDied() {
removeOrganizer(mOrganizer);
}
}
TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
mAtmService = atm;
mGlobalLock = atm.mGlobalLock;
}
@Override
public void registerOrganizer(ITaskFragmentOrganizer organizer) {
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"Register task fragment organizer=%s uid=%d pid=%d",
organizer.asBinder(), uid, pid);
if (mOrganizers.contains(organizer)) {
throw new IllegalStateException(
"Replacing existing organizer currently unsupported");
}
final DeathRecipient dr = new DeathRecipient(organizer);
try {
organizer.asBinder().linkToDeath(dr, 0);
} catch (RemoteException e) {
// Oh well...
}
mOrganizers.add(organizer);
mDeathRecipients.put(organizer, dr);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
@Override
public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
final int pid = Binder.getCallingPid();
final long uid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"Unregister task fragment organizer=%s uid=%d pid=%d",
organizer.asBinder(), uid, pid);
if (!mOrganizers.contains(organizer)) {
throw new IllegalStateException(
"The task fragment organizer hasn't been registered.");
}
final DeathRecipient dr = mDeathRecipients.get(organizer);
organizer.asBinder().unlinkToDeath(dr, 0);
removeOrganizer(organizer);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
try {
final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
"TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
organizer.onTaskFragmentAppeared(
new TaskFragmentAppearedInfo(tf.getTaskFragmentInfo(), outSurfaceControl));
} catch (RemoteException e) {
// Oh well...
}
}
void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s", tf.getName());
try {
organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
} catch (RemoteException e) {
// Oh well...
}
}
void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
try {
organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
} catch (RemoteException e) {
// Oh well...
}
}
void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
final Task parent = tf.getParent().asTask();
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
"TaskFragment parent info changed name=%s parentTaskId=%d",
tf.getName(), parent.mTaskId);
try {
organizer.onTaskFragmentParentInfoChanged(
tf.getFragmentToken(), parent.getConfiguration());
} catch (RemoteException e) {
// Oh well...
}
}
private void removeOrganizer(ITaskFragmentOrganizer organizer) {
synchronized (mGlobalLock) {
mOrganizers.remove(organizer);
mDeathRecipients.remove(organizer);
}
// TODO(b/190432728) move child activities of organized TaskFragment to leaf Task
}
}

View File

@@ -17,12 +17,17 @@
package com.android.server.wm;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_CHILDREN;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
import static com.android.server.wm.ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED;
@@ -34,6 +39,7 @@ import static com.android.server.wm.WindowContainer.POSITION_TOP;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -46,10 +52,12 @@ import android.util.ArraySet;
import android.util.Slog;
import android.view.SurfaceControl;
import android.window.IDisplayAreaOrganizerController;
import android.window.ITaskFragmentOrganizerController;
import android.window.ITaskOrganizerController;
import android.window.ITransitionPlayer;
import android.window.IWindowContainerTransactionCallback;
import android.window.IWindowOrganizerController;
import android.window.TaskFragmentCreationParams;
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
@@ -95,6 +103,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
final TaskOrganizerController mTaskOrganizerController;
final DisplayAreaOrganizerController mDisplayAreaOrganizerController;
final TaskFragmentOrganizerController mTaskFragmentOrganizerController;
final TransitionController mTransitionController;
@@ -103,6 +112,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
mGlobalLock = atm.mGlobalLock;
mTaskOrganizerController = new TaskOrganizerController(mService);
mDisplayAreaOrganizerController = new DisplayAreaOrganizerController(mService);
mTaskFragmentOrganizerController = new TaskFragmentOrganizerController(atm);
mTransitionController = new TransitionController(atm);
}
@@ -501,13 +511,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return effects;
}
final WindowContainer wc;
final IBinder fragmentToken;
switch (type) {
case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT:
effects |= reparentChildrenTasksHierarchyOp(hop, transition, syncId);
break;
case HIERARCHY_OP_TYPE_REORDER:
case HIERARCHY_OP_TYPE_REPARENT:
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
wc = WindowContainer.fromBinder(hop.getContainer());
if (wc == null || !wc.isAttached()) {
Slog.e(TAG, "Attempt to operate on detached container: " + wc);
break;
@@ -543,6 +555,40 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
launchOpts.remove(WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
mService.startActivityFromRecents(taskId, launchOpts);
break;
case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT:
final TaskFragmentCreationParams taskFragmentCreationOptions =
hop.getTaskFragmentCreationOptions();
// TODO(b/190433129) add actual implementation on WM Core
break;
case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT:
wc = WindowContainer.fromBinder(hop.getContainer());
if (wc == null || !wc.isAttached()) {
Slog.e(TAG, "Attempt to operate on detached container: " + wc);
break;
}
final TaskFragment taskFragment = wc.asTaskFragment();
if (taskFragment == null || taskFragment.asTask() != null) {
throw new IllegalArgumentException(
"Can only delete organized TaskFragment, but not Task.");
}
// TODO(b/190433129) add actual implementation on WM Core
break;
case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT:
fragmentToken = hop.getContainer();
final Intent activityIntent = hop.getActivityIntent();
final Bundle activityOptions = hop.getLaunchOptions();
// TODO(b/190433129) add actual implementation on WM Core
break;
case HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT:
fragmentToken = hop.getNewParent();
final ActivityRecord activity = ActivityRecord.forTokenLocked(hop.getContainer());
// TODO(b/190433129) add actual implementation on WM Core
break;
case HIERARCHY_OP_TYPE_REPARENT_CHILDREN:
final WindowContainer oldParent = WindowContainer.fromBinder(hop.getContainer());
final WindowContainer newParent = WindowContainer.fromBinder(hop.getNewParent());
// TODO(b/190433129) add actual implementation on WM Core
break;
}
return effects;
}
@@ -704,8 +750,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
private int setAdjacentRootsHierarchyOp(WindowContainerTransaction.HierarchyOp hop) {
final Task root1 = WindowContainer.fromBinder(hop.getContainer()).asTask();
final Task root2 = WindowContainer.fromBinder(hop.getAdjacentRoot()).asTask();
final TaskFragment root1 = WindowContainer.fromBinder(hop.getContainer()).asTaskFragment();
final TaskFragment root2 =
WindowContainer.fromBinder(hop.getAdjacentRoot()).asTaskFragment();
if (!root1.mCreatedByOrganizer || !root2.mCreatedByOrganizer) {
throw new IllegalArgumentException("setAdjacentRootsHierarchyOp: Not created by"
+ " organizer root1=" + root1 + " root2=" + root2);
@@ -747,6 +794,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return mDisplayAreaOrganizerController;
}
@Override
public ITaskFragmentOrganizerController getTaskFragmentOrganizerController() {
return mTaskFragmentOrganizerController;
}
@VisibleForTesting
int startSyncWithOrganizer(IWindowContainerTransactionCallback callback) {
int id = mService.mWindowManager.mSyncEngine.startSyncSet(this);