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:
40
core/java/android/window/ITaskFragmentOrganizer.aidl
Normal file
40
core/java/android/window/ITaskFragmentOrganizer.aidl
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
23
core/java/android/window/TaskFragmentAppearedInfo.aidl
Normal file
23
core/java/android/window/TaskFragmentAppearedInfo.aidl
Normal 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;
|
||||
86
core/java/android/window/TaskFragmentAppearedInfo.java
Normal file
86
core/java/android/window/TaskFragmentAppearedInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
23
core/java/android/window/TaskFragmentCreationParams.aidl
Normal file
23
core/java/android/window/TaskFragmentCreationParams.aidl
Normal 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;
|
||||
121
core/java/android/window/TaskFragmentCreationParams.java
Normal file
121
core/java/android/window/TaskFragmentCreationParams.java
Normal 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;
|
||||
}
|
||||
}
|
||||
23
core/java/android/window/TaskFragmentInfo.aidl
Normal file
23
core/java/android/window/TaskFragmentInfo.aidl
Normal 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;
|
||||
145
core/java/android/window/TaskFragmentInfo.java
Normal file
145
core/java/android/window/TaskFragmentInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
131
core/java/android/window/TaskFragmentOrganizer.java
Normal file
131
core/java/android/window/TaskFragmentOrganizer.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user