/*
* 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 static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
import android.annotation.CallSuper;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
/**
* Interface for WindowManager to delegate control of {@code TaskFragment}.
* @hide
*/
@TestApi
public class TaskFragmentOrganizer extends WindowOrganizer {
/**
* Key to the {@link Throwable} in {@link TaskFragmentTransaction.Change#getErrorBundle()}.
*/
public static final String KEY_ERROR_CALLBACK_THROWABLE = "fragment_throwable";
/**
* Key to the {@link TaskFragmentInfo} in
* {@link TaskFragmentTransaction.Change#getErrorBundle()}.
*/
public static final String KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO = "task_fragment_info";
/**
* Key to the {@link TaskFragmentOperation.OperationType} in
* {@link TaskFragmentTransaction.Change#getErrorBundle()}.
*/
public static final String KEY_ERROR_CALLBACK_OP_TYPE = "operation_type";
/**
* No change set.
*/
@WindowManager.TransitionType
@TaskFragmentTransitionType
public static final int TASK_FRAGMENT_TRANSIT_NONE = TRANSIT_NONE;
/**
* A window that didn't exist before has been created and made visible.
*/
@WindowManager.TransitionType
@TaskFragmentTransitionType
public static final int TASK_FRAGMENT_TRANSIT_OPEN = TRANSIT_OPEN;
/**
* A window that was visible no-longer exists (was finished or destroyed).
*/
@WindowManager.TransitionType
@TaskFragmentTransitionType
public static final int TASK_FRAGMENT_TRANSIT_CLOSE = TRANSIT_CLOSE;
/**
* A window is visible before and after but changes in some way (eg. it resizes or changes
* windowing-mode).
*/
@WindowManager.TransitionType
@TaskFragmentTransitionType
public static final int TASK_FRAGMENT_TRANSIT_CHANGE = TRANSIT_CHANGE;
/**
* Introduced a sub set of {@link WindowManager.TransitionType} for the types that are used for
* TaskFragment transition.
*
* Doing this instead of exposing {@link WindowManager.TransitionType} because we want to keep
* the Shell transition API hidden until it comes fully stable.
* @hide
*/
@IntDef(prefix = { "TASK_FRAGMENT_TRANSIT_" }, value = {
TASK_FRAGMENT_TRANSIT_NONE,
TASK_FRAGMENT_TRANSIT_OPEN,
TASK_FRAGMENT_TRANSIT_CLOSE,
TASK_FRAGMENT_TRANSIT_CHANGE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TaskFragmentTransitionType {}
/**
* Creates a {@link Bundle} with an exception, operation type and TaskFragmentInfo (if any)
* that can be passed to {@link ITaskFragmentOrganizer#onTaskFragmentError}.
* @hide
*/
public static @NonNull Bundle putErrorInfoInBundle(@NonNull Throwable exception,
@Nullable TaskFragmentInfo info, @TaskFragmentOperation.OperationType int opType) {
final Bundle errorBundle = new Bundle();
errorBundle.putSerializable(KEY_ERROR_CALLBACK_THROWABLE, exception);
if (info != null) {
errorBundle.putParcelable(KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO, info);
}
errorBundle.putInt(KEY_ERROR_CALLBACK_OP_TYPE, opType);
return errorBundle;
}
/**
* 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();
}
}
/**
* Registers remote animations per transition type for the organizer. It will override the
* animations if the transition only contains windows that belong to the organized
* TaskFragments, and at least one of the transition window is embedded (not filling the Task).
* @hide
*/
@CallSuper
public void registerRemoteAnimations(@NonNull RemoteAnimationDefinition definition) {
try {
getController().registerRemoteAnimations(mInterface, definition);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Unregisters remote animations per transition type for the organizer.
* @hide
*/
@CallSuper
public void unregisterRemoteAnimations() {
try {
getController().unregisterRemoteAnimations(mInterface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Notifies the server that the organizer has finished handling the given transaction. The
* server should apply the given {@link WindowContainerTransaction} for the necessary changes.
*
* @param transactionToken {@link TaskFragmentTransaction#getTransactionToken()} from
* {@link #onTransactionReady(TaskFragmentTransaction)}
* @param wct {@link WindowContainerTransaction} that the server should apply for
* update of the transaction.
* @param transitionType {@link TaskFragmentTransitionType} if it needs to start a
* transition.
* @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
* transition, which will be queued until the sync engine is
* free if there is any other active sync. If {@code false},
* the {@code wct} will be directly applied to the active sync.
* @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
* for permission enforcement.
*/
public void onTransactionHandled(@NonNull IBinder transactionToken,
@NonNull WindowContainerTransaction wct,
@TaskFragmentTransitionType int transitionType, boolean shouldApplyIndependently) {
wct.setTaskFragmentOrganizer(mInterface);
try {
getController().onTransactionHandled(transactionToken, wct, transitionType,
shouldApplyIndependently);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Must use {@link #applyTransaction(WindowContainerTransaction, int, boolean)} instead.
* @see #applyTransaction(WindowContainerTransaction, int, boolean)
*/
@Override
public void applyTransaction(@NonNull WindowContainerTransaction wct) {
throw new RuntimeException("Not allowed!");
}
/**
* Requests the server to apply the given {@link WindowContainerTransaction}.
*
* @param wct {@link WindowContainerTransaction} to apply.
* @param transitionType {@link TaskFragmentTransitionType} if it needs to start a
* transition.
* @param shouldApplyIndependently If {@code true}, the {@code wct} will request a new
* transition, which will be queued until the sync engine is
* free if there is any other active sync. If {@code false},
* the {@code wct} will be directly applied to the active sync.
* @see com.android.server.wm.WindowOrganizerController#enforceTaskFragmentOrganizerPermission
* for permission enforcement.
*/
public void applyTransaction(@NonNull WindowContainerTransaction wct,
@TaskFragmentTransitionType int transitionType, boolean shouldApplyIndependently) {
if (wct.isEmpty()) {
return;
}
wct.setTaskFragmentOrganizer(mInterface);
try {
getController().applyTransaction(wct, transitionType, shouldApplyIndependently);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Called when the transaction is ready so that the organizer can update the TaskFragments based
* on the changes in transaction.
*/
public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
// Notify the server to finish the transaction.
onTransactionHandled(transaction.getTransactionToken(), new WindowContainerTransaction(),
TASK_FRAGMENT_TRANSIT_NONE, false /* shouldApplyIndependently */);
}
private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
@Override
public void onTransactionReady(@NonNull TaskFragmentTransaction transaction) {
mExecutor.execute(() -> TaskFragmentOrganizer.this.onTransactionReady(transaction));
}
};
private final TaskFragmentOrganizerToken mToken = new TaskFragmentOrganizerToken(mInterface);
@NonNull
public TaskFragmentOrganizerToken getOrganizerToken() {
return mToken;
}
private ITaskFragmentOrganizerController getController() {
try {
return getWindowOrganizerController().getTaskFragmentOrganizerController();
} catch (RemoteException e) {
return null;
}
}
/**
* Checks if an activity organized by a {@link android.window.TaskFragmentOrganizer} and
* only occupies a portion of Task bounds.
* @hide
*/
public boolean isActivityEmbedded(@NonNull IBinder activityToken) {
try {
return getController().isActivityEmbedded(activityToken);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
这是TaskFragmentOrganizer.java文件,按照如上修改后报错如下:
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:20: 错误: 方法不会覆盖或实现超类型的方法
@Override
^
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:25: 错误: 方法不会覆盖或实现超类型的方法
@Override
^
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:30: 错误: 方法不会覆盖或实现超类型的方法
@Override
^
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:45: 错误: 找不到符号
TaskFragment taskFragment1 = mOrganizer.createTaskFragment(
^
符号: 方法 createTaskFragment(WindowContainerTransaction,<空值>,IBinder,<空值>)
位置: 类型为TaskFragmentOrganizer的变量 mOrganizer
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:50: 错误: 找不到符号
TaskFragment taskFragment2 = mOrganizer.createTaskFragment(
^
符号: 方法 createTaskFragment(WindowContainerTransaction,<空值>,IBinder,<空值>)
位置: 类型为TaskFragmentOrganizer的变量 mOrganizer
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:61: 错误: 找不到符号
Rect bounds1 = new Rect(0, 0, displayWidth / 2, displayHeight);
^
符号: 类 Rect
位置: 类 SplitScreenHelper
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:61: 错误: 找不到符号
Rect bounds1 = new Rect(0, 0, displayWidth / 2, displayHeight);
^
符号: 类 Rect
位置: 类 SplitScreenHelper
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:65: 错误: 找不到符号
Rect bounds2 = new Rect(displayWidth / 2, 0, displayWidth, displayHeight);
^
符号: 类 Rect
位置: 类 SplitScreenHelper
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:65: 错误: 找不到符号
Rect bounds2 = new Rect(displayWidth / 2, 0, displayWidth, displayHeight);
^
符号: 类 Rect
位置: 类 SplitScreenHelper
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:70: 错误: 找不到符号
options1.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
^
符号: 变量 WindowConfiguration
位置: 类 SplitScreenHelper
out_system/soong/.intermediates/frameworks/base/services/core/services.core.unboosted/android_common/javac/shard36/srcjars/frameworks/base/services/core/java/com/android/server/wm/SplitScreenHelper.java:76: 错误: 找不到符号
options2.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
^
符号: 变量 WindowConfiguration
位置: 类 SplitScreenHelper