Merge "Introduce WindowOrganizer" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
e5cfca4454
@@ -30,7 +30,6 @@ import android.os.IBinder;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.util.Singleton;
|
import android.util.Singleton;
|
||||||
import android.window.ITaskOrganizerController;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -159,24 +158,6 @@ public class ActivityTaskManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @hide */
|
|
||||||
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
|
||||||
public static ITaskOrganizerController getTaskOrganizerController() {
|
|
||||||
return ITaskOrganizerControllerSingleton.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
|
|
||||||
new Singleton<ITaskOrganizerController>() {
|
|
||||||
@Override
|
|
||||||
protected ITaskOrganizerController create() {
|
|
||||||
try {
|
|
||||||
return getService().getTaskOrganizerController();
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the windowing mode for a specific task. Only works on tasks of type
|
* Sets the windowing mode for a specific task. Only works on tasks of type
|
||||||
* {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}
|
* {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import android.app.IProcessObserver;
|
|||||||
import android.app.IRequestFinishCallback;
|
import android.app.IRequestFinishCallback;
|
||||||
import android.app.IServiceConnection;
|
import android.app.IServiceConnection;
|
||||||
import android.app.IStopUserCallback;
|
import android.app.IStopUserCallback;
|
||||||
import android.window.ITaskOrganizerController;
|
|
||||||
import android.app.ITaskStackListener;
|
import android.app.ITaskStackListener;
|
||||||
import android.app.IUiAutomationConnection;
|
import android.app.IUiAutomationConnection;
|
||||||
import android.app.IUidObserver;
|
import android.app.IUidObserver;
|
||||||
@@ -69,9 +68,9 @@ import android.os.StrictMode;
|
|||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
import android.service.voice.IVoiceInteractionSession;
|
import android.service.voice.IVoiceInteractionSession;
|
||||||
import android.view.IRecentsAnimationRunner;
|
import android.view.IRecentsAnimationRunner;
|
||||||
import android.window.ITaskOrganizer;
|
|
||||||
import android.view.RemoteAnimationDefinition;
|
import android.view.RemoteAnimationDefinition;
|
||||||
import android.view.RemoteAnimationAdapter;
|
import android.view.RemoteAnimationAdapter;
|
||||||
|
import android.window.IWindowOrganizerController;
|
||||||
import com.android.internal.app.IVoiceInteractor;
|
import com.android.internal.app.IVoiceInteractor;
|
||||||
import com.android.internal.os.IResultReceiver;
|
import com.android.internal.os.IResultReceiver;
|
||||||
import com.android.internal.policy.IKeyguardDismissCallback;
|
import com.android.internal.policy.IKeyguardDismissCallback;
|
||||||
@@ -340,10 +339,8 @@ interface IActivityTaskManager {
|
|||||||
in Rect tempDockedTaskInsetBounds,
|
in Rect tempDockedTaskInsetBounds,
|
||||||
in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds);
|
in Rect tempOtherTaskBounds, in Rect tempOtherTaskInsetBounds);
|
||||||
|
|
||||||
/**
|
/** Returns an interface enabling the management of window organizers. */
|
||||||
* Returns an interface enabling the management of task organizers.
|
IWindowOrganizerController getWindowOrganizerController();
|
||||||
*/
|
|
||||||
ITaskOrganizerController getTaskOrganizerController();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether we are currently in an interactive split screen resize operation where we
|
* Sets whether we are currently in an interactive split screen resize operation where we
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
/* //device/java/android/android/view/ITaskOrganizer.aidl
|
/*
|
||||||
**
|
* Copyright (C) 2019 The Android Open Source Project
|
||||||
** Copyright 2019, The Android Open Source Project
|
*
|
||||||
**
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
||||||
** you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
||||||
** You may obtain a copy of the License at
|
*
|
||||||
**
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
** http://www.apache.org/licenses/LICENSE-2.0
|
*
|
||||||
**
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
** Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
||||||
** See the License for the specific language governing permissions and
|
* limitations under the License.
|
||||||
** limitations under the License.
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
package android.window;
|
package android.window;
|
||||||
|
|
||||||
@@ -29,12 +28,6 @@ oneway interface ITaskOrganizer {
|
|||||||
void taskAppeared(in ActivityManager.RunningTaskInfo taskInfo);
|
void taskAppeared(in ActivityManager.RunningTaskInfo taskInfo);
|
||||||
void taskVanished(in ActivityManager.RunningTaskInfo taskInfo);
|
void taskVanished(in ActivityManager.RunningTaskInfo taskInfo);
|
||||||
|
|
||||||
/**
|
|
||||||
* Called upon completion of
|
|
||||||
* ActivityTaskManagerService#applyTaskOrganizerTransaction
|
|
||||||
*/
|
|
||||||
void transactionReady(int id, in SurfaceControl.Transaction t);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will fire when core attributes of a Task's info change. Relevant properties include the
|
* Will fire when core attributes of a Task's info change. Relevant properties include the
|
||||||
* {@link WindowConfiguration.ActivityType} and whether it is resizable.
|
* {@link WindowConfiguration.ActivityType} and whether it is resizable.
|
||||||
|
|||||||
@@ -36,20 +36,6 @@ interface ITaskOrganizerController {
|
|||||||
*/
|
*/
|
||||||
void unregisterTaskOrganizer(ITaskOrganizer organizer);
|
void unregisterTaskOrganizer(ITaskOrganizer organizer);
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply multiple WindowContainer operations at once.
|
|
||||||
* @param organizer If non-null this transaction will use the synchronization
|
|
||||||
* scheme described in BLASTSyncEngine.java. The SurfaceControl transaction
|
|
||||||
* containing the effects of this WindowContainer transaction will be passed
|
|
||||||
* to the organizers Transaction ready callback. If null the transaction
|
|
||||||
* will apply with non particular synchronization constraints (other than
|
|
||||||
* it will all apply at once).
|
|
||||||
* @return If organizer was non-null returns an ID for the sync operation which will
|
|
||||||
* later be passed to transactionReady. This lets TaskOrganizer implementations
|
|
||||||
* differentiate overlapping sync operations.
|
|
||||||
*/
|
|
||||||
int applyContainerTransaction(in WindowContainerTransaction t, ITaskOrganizer organizer);
|
|
||||||
|
|
||||||
/** Creates a persistent root task in WM for a particular windowing-mode. */
|
/** Creates a persistent root task in WM for a particular windowing-mode. */
|
||||||
ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode);
|
ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.window;
|
||||||
|
|
||||||
|
import android.view.SurfaceControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See WindowOrganizer#applyTransaction.
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
oneway interface IWindowContainerTransactionCallback {
|
||||||
|
/** Called upon completion of WindowOrganizer#applyTransaction */
|
||||||
|
void transactionReady(int id, in SurfaceControl.Transaction t);
|
||||||
|
}
|
||||||
46
core/java/android/window/IWindowOrganizerController.aidl
Normal file
46
core/java/android/window/IWindowOrganizerController.aidl
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2020, The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.window;
|
||||||
|
|
||||||
|
import android.window.ITaskOrganizerController;
|
||||||
|
import android.window.IWindowContainerTransactionCallback;
|
||||||
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
interface IWindowOrganizerController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply multiple WindowContainer operations at once.
|
||||||
|
* @param t The transaction to apply.
|
||||||
|
*/
|
||||||
|
void applyTransaction(in WindowContainerTransaction t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply multiple WindowContainer operations at once.
|
||||||
|
* @param t The transaction to apply.
|
||||||
|
* @param callback This transaction will use the synchronization scheme described in
|
||||||
|
* BLASTSyncEngine.java. The SurfaceControl transaction containing the effects of this
|
||||||
|
* WindowContainer transaction will be passed to this callback when ready.
|
||||||
|
* @return An ID for the sync operation which will later be passed to transactionReady callback.
|
||||||
|
* This lets the caller differentiate overlapping sync operations.
|
||||||
|
*/
|
||||||
|
int applySyncTransaction(in WindowContainerTransaction t,
|
||||||
|
in IWindowContainerTransactionCallback callback);
|
||||||
|
|
||||||
|
/** @return An interface enabling the management of task organizers. */
|
||||||
|
ITaskOrganizerController getTaskOrganizerController();
|
||||||
|
}
|
||||||
157
core/java/android/window/WindowOrganizer.java
Normal file
157
core/java/android/window/WindowOrganizer.java
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.window;
|
||||||
|
|
||||||
|
import android.annotation.RequiresPermission;
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.app.ActivityTaskManager;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Singleton;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for organizing specific types of windows like Tasks and DisplayAreas
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class WindowOrganizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply multiple WindowContainer operations at once.
|
||||||
|
* @param t The transaction to apply.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static void applyTransaction(WindowContainerTransaction t) throws RemoteException {
|
||||||
|
getWindowOrganizerController().applyTransaction(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply multiple WindowContainer operations at once.
|
||||||
|
* @param t The transaction to apply.
|
||||||
|
* @param callback This transaction will use the synchronization scheme described in
|
||||||
|
* BLASTSyncEngine.java. The SurfaceControl transaction containing the effects of this
|
||||||
|
* WindowContainer transaction will be passed to this callback when ready.
|
||||||
|
* @return An ID for the sync operation which will later be passed to transactionReady callback.
|
||||||
|
* This lets the caller differentiate overlapping sync operations.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static int applySyncTransaction(WindowContainerTransaction t,
|
||||||
|
IWindowContainerTransactionCallback callback) throws RemoteException {
|
||||||
|
return getWindowOrganizerController().applySyncTransaction(t, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
private static IWindowOrganizerController getWindowOrganizerController() {
|
||||||
|
return IWindowOrganizerControllerSingleton.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Singleton<IWindowOrganizerController> IWindowOrganizerControllerSingleton =
|
||||||
|
new Singleton<IWindowOrganizerController>() {
|
||||||
|
@Override
|
||||||
|
protected IWindowOrganizerController create() {
|
||||||
|
try {
|
||||||
|
return ActivityTaskManager.getService().getWindowOrganizerController();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static class TaskOrganizer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
|
||||||
|
* If there was already a TaskOrganizer for this windowing mode it will be evicted
|
||||||
|
* and receive taskVanished callbacks in the process.
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static void registerOrganizer(ITaskOrganizer organizer, int windowingMode)
|
||||||
|
throws RemoteException {
|
||||||
|
getController().registerTaskOrganizer(organizer, windowingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unregisters a previously registered task organizer. */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static void unregisterOrganizer(ITaskOrganizer organizer) throws RemoteException {
|
||||||
|
getController().unregisterTaskOrganizer(organizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a persistent root task in WM for a particular windowing-mode. */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static ActivityManager.RunningTaskInfo createRootTask(
|
||||||
|
int displayId, int windowingMode) throws RemoteException {
|
||||||
|
return getController().createRootTask(displayId, windowingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Deletes a persistent root task in WM */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static boolean deleteRootTask(IWindowContainer task) throws RemoteException {
|
||||||
|
return getController().deleteRootTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets direct child tasks (ordered from top-to-bottom) */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static List<ActivityManager.RunningTaskInfo> getChildTasks(IWindowContainer parent,
|
||||||
|
int[] activityTypes) throws RemoteException {
|
||||||
|
return getController().getChildTasks(parent, activityTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets all root tasks on a display (ordered from top-to-bottom) */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static List<ActivityManager.RunningTaskInfo> getRootTasks(
|
||||||
|
int displayId, int[] activityTypes) throws RemoteException {
|
||||||
|
return getController().getRootTasks(displayId, activityTypes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the root task which contains the current ime target */
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static IWindowContainer getImeTarget(int display) throws RemoteException {
|
||||||
|
return getController().getImeTarget(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set's the root task to launch new tasks into on a display. {@code null} means no launch
|
||||||
|
* root and thus new tasks just end up directly on the display.
|
||||||
|
*/
|
||||||
|
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
|
||||||
|
public static void setLaunchRoot(int displayId, IWindowContainer root)
|
||||||
|
throws RemoteException {
|
||||||
|
getController().setLaunchRoot(displayId, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ITaskOrganizerController getController() {
|
||||||
|
return ITaskOrganizerControllerSingleton.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
|
||||||
|
new Singleton<ITaskOrganizerController>() {
|
||||||
|
@Override
|
||||||
|
protected ITaskOrganizerController create() {
|
||||||
|
try {
|
||||||
|
return getWindowOrganizerController().getTaskOrganizerController();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,6 +42,7 @@ import android.window.ITaskOrganizer;
|
|||||||
import android.window.IWindowContainer;
|
import android.window.IWindowContainer;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
import com.android.internal.os.SomeArgs;
|
import com.android.internal.os.SomeArgs;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -76,7 +77,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
|
|
||||||
private final Handler mMainHandler;
|
private final Handler mMainHandler;
|
||||||
private final Handler mUpdateHandler;
|
private final Handler mUpdateHandler;
|
||||||
private final ITaskOrganizerController mTaskOrganizerController;
|
|
||||||
private final PipBoundsHandler mPipBoundsHandler;
|
private final PipBoundsHandler mPipBoundsHandler;
|
||||||
private final PipAnimationController mPipAnimationController;
|
private final PipAnimationController mPipAnimationController;
|
||||||
private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
|
private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
|
||||||
@@ -188,7 +188,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper) {
|
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper) {
|
||||||
mMainHandler = new Handler(Looper.getMainLooper());
|
mMainHandler = new Handler(Looper.getMainLooper());
|
||||||
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
|
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
|
||||||
mTaskOrganizerController = ActivityTaskManager.getTaskOrganizerController();
|
|
||||||
mPipBoundsHandler = boundsHandler;
|
mPipBoundsHandler = boundsHandler;
|
||||||
mEnterExitAnimationDuration = context.getResources()
|
mEnterExitAnimationDuration = context.getResources()
|
||||||
.getInteger(R.integer.config_pipResizeAnimationDuration);
|
.getInteger(R.integer.config_pipResizeAnimationDuration);
|
||||||
@@ -264,10 +263,6 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
mInPip = false;
|
mInPip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
||||||
final PictureInPictureParams newParams = info.pictureInPictureParams;
|
final PictureInPictureParams newParams = info.pictureInPictureParams;
|
||||||
@@ -450,7 +445,7 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
wct.setBounds(mToken, taskBounds);
|
wct.setBounds(mToken, taskBounds);
|
||||||
}
|
}
|
||||||
wct.setBoundsChangeTransaction(mToken, tx);
|
wct.setBoundsChangeTransaction(mToken, tx);
|
||||||
mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */);
|
WindowOrganizer.applyTransaction(wct);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Failed to apply container transaction", e);
|
Log.e(TAG, "Failed to apply container transaction", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui.pip.phone;
|
|||||||
|
|
||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityTaskManager;
|
import android.app.ActivityTaskManager;
|
||||||
@@ -35,6 +36,7 @@ import android.util.Pair;
|
|||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
import android.view.IPinnedStackController;
|
import android.view.IPinnedStackController;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.UiOffloadThread;
|
import com.android.systemui.UiOffloadThread;
|
||||||
@@ -248,8 +250,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
|||||||
mPipBoundsHandler.onDisplayInfoChanged(displayInfo);
|
mPipBoundsHandler.onDisplayInfoChanged(displayInfo);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(
|
TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
|
||||||
mPipTaskOrganizer, WINDOWING_MODE_PINNED);
|
|
||||||
ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
|
ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
|
||||||
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
|
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
|
||||||
if (stackInfo != null) {
|
if (stackInfo != null) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.systemui.pip.tv;
|
|||||||
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
|
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
|
||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.app.ActivityManager.StackInfo;
|
import android.app.ActivityManager.StackInfo;
|
||||||
@@ -44,6 +45,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
import com.android.systemui.Dependency;
|
import com.android.systemui.Dependency;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
@@ -293,8 +295,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
|
WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
|
||||||
ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(
|
TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
|
||||||
mPipTaskOrganizer, WINDOWING_MODE_PINNED);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Failed to register pinned stack listener", e);
|
Log.e(TAG, "Failed to register pinned stack listener", e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
|||||||
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
|
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
|
||||||
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
|
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.app.ActivityTaskManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -38,6 +38,7 @@ import android.view.SurfaceControl;
|
|||||||
import android.view.SurfaceSession;
|
import android.view.SurfaceSession;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@@ -177,8 +178,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
|
|||||||
|
|
||||||
private boolean getSecondaryHasFocus(int displayId) {
|
private boolean getSecondaryHasFocus(int displayId) {
|
||||||
try {
|
try {
|
||||||
IWindowContainer imeSplit = ActivityTaskManager.getTaskOrganizerController()
|
IWindowContainer imeSplit = TaskOrganizer.getImeTarget(displayId);
|
||||||
.getImeTarget(displayId);
|
|
||||||
return imeSplit != null
|
return imeSplit != null
|
||||||
&& (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
|
&& (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -267,8 +267,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
|
|||||||
SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
|
SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController()
|
WindowOrganizer.applyTransaction(wct);
|
||||||
.applyContainerTransaction(wct, null /* organizer */);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,13 +473,12 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
|
|||||||
mImeController.addPositionProcessor(mImePositionProcessor);
|
mImeController.addPositionProcessor(mImePositionProcessor);
|
||||||
mDisplayController.addDisplayChangingController(mRotationController);
|
mDisplayController.addDisplayChangingController(mRotationController);
|
||||||
try {
|
try {
|
||||||
mSplits.init(ActivityTaskManager.getTaskOrganizerController(), mSurfaceSession);
|
mSplits.init(mSurfaceSession);
|
||||||
// Set starting tile bounds based on middle target
|
// Set starting tile bounds based on middle target
|
||||||
final WindowContainerTransaction tct = new WindowContainerTransaction();
|
final WindowContainerTransaction tct = new WindowContainerTransaction();
|
||||||
int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
|
int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
|
||||||
mSplitLayout.resizeSplits(midPos, tct);
|
mSplitLayout.resizeSplits(midPos, tct);
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(tct,
|
WindowOrganizer.applyTransaction(tct);
|
||||||
null /* organizer */);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Slog.e(TAG, "Failed to register docked stack listener", e);
|
Slog.e(TAG, "Failed to register docked stack listener", e);
|
||||||
}
|
}
|
||||||
@@ -499,8 +497,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
|
|||||||
final WindowContainerTransaction tct = new WindowContainerTransaction();
|
final WindowContainerTransaction tct = new WindowContainerTransaction();
|
||||||
mSplitLayout.resizeSplits(midPos, tct);
|
mSplitLayout.resizeSplits(midPos, tct);
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(tct,
|
WindowOrganizer.applyTransaction(tct);
|
||||||
null /* organizer */);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
} else if (mRotateSplitLayout != null
|
} else if (mRotateSplitLayout != null
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.window.ITaskOrganizerController;
|
|
||||||
import android.app.WindowConfiguration;
|
import android.app.WindowConfiguration;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -49,13 +49,12 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
mDivider = divider;
|
mDivider = divider;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init(ITaskOrganizerController organizerController, SurfaceSession session)
|
void init(SurfaceSession session) throws RemoteException {
|
||||||
throws RemoteException {
|
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
||||||
organizerController.registerTaskOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
||||||
organizerController.registerTaskOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
|
||||||
mPrimary = organizerController.createRootTask(Display.DEFAULT_DISPLAY,
|
|
||||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
|
||||||
mSecondary = organizerController.createRootTask(Display.DEFAULT_DISPLAY,
|
mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
|
||||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
||||||
mPrimarySurface = mPrimary.token.getLeash();
|
mPrimarySurface = mPrimary.token.getLeash();
|
||||||
mSecondarySurface = mSecondary.token.getLeash();
|
mSecondarySurface = mSecondary.token.getLeash();
|
||||||
@@ -90,10 +89,6 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
|
|||||||
public void taskVanished(RunningTaskInfo taskInfo) {
|
public void taskVanished(RunningTaskInfo taskInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
if (taskInfo.displayId != DEFAULT_DISPLAY) {
|
if (taskInfo.displayId != DEFAULT_DISPLAY) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
|||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
@@ -31,6 +32,7 @@ import android.view.Display;
|
|||||||
import android.window.IWindowContainer;
|
import android.window.IWindowContainer;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
import android.view.WindowManagerGlobal;
|
import android.view.WindowManagerGlobal;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
@@ -111,8 +113,7 @@ public class WindowManagerProxy {
|
|||||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||||
splitLayout.resizeSplits(position, t);
|
splitLayout.resizeSplits(position, t);
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(t,
|
WindowOrganizer.applyTransaction(t);
|
||||||
null /* organizer */);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,10 +123,8 @@ public class WindowManagerProxy {
|
|||||||
boolean resizable = false;
|
boolean resizable = false;
|
||||||
try {
|
try {
|
||||||
List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
|
List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
|
||||||
? ActivityTaskManager.getTaskOrganizerController().getRootTasks(
|
? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
|
||||||
Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
|
: TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
|
||||||
: ActivityTaskManager.getTaskOrganizerController().getChildTasks(parent,
|
|
||||||
HOME_AND_RECENTS);
|
|
||||||
for (int i = 0, n = rootTasks.size(); i < n; ++i) {
|
for (int i = 0, n = rootTasks.size(); i < n; ++i) {
|
||||||
final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
|
final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
|
||||||
out.add(ti.token);
|
out.add(ti.token);
|
||||||
@@ -174,11 +173,9 @@ public class WindowManagerProxy {
|
|||||||
// Set launchtile first so that any stack created after
|
// Set launchtile first so that any stack created after
|
||||||
// getAllStackInfos and before reparent (even if unlikely) are placed
|
// getAllStackInfos and before reparent (even if unlikely) are placed
|
||||||
// correctly.
|
// correctly.
|
||||||
ActivityTaskManager.getTaskOrganizerController().setLaunchRoot(
|
TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
|
||||||
DEFAULT_DISPLAY, tiles.mSecondary.token);
|
|
||||||
List<ActivityManager.RunningTaskInfo> rootTasks =
|
List<ActivityManager.RunningTaskInfo> rootTasks =
|
||||||
ActivityTaskManager.getTaskOrganizerController().getRootTasks(DEFAULT_DISPLAY,
|
TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
|
||||||
null /* activityTypes */);
|
|
||||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
if (rootTasks.isEmpty()) {
|
if (rootTasks.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
@@ -192,8 +189,7 @@ public class WindowManagerProxy {
|
|||||||
true /* onTop */);
|
true /* onTop */);
|
||||||
}
|
}
|
||||||
boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
|
boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
|
||||||
ActivityTaskManager.getTaskOrganizerController()
|
WindowOrganizer.applyTransaction(wct);
|
||||||
.applyContainerTransaction(wct, null /* organizer */);
|
|
||||||
return isHomeResizable;
|
return isHomeResizable;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "Error moving fullscreen tasks to secondary split: " + e);
|
Log.w(TAG, "Error moving fullscreen tasks to secondary split: " + e);
|
||||||
@@ -216,22 +212,18 @@ public class WindowManagerProxy {
|
|||||||
try {
|
try {
|
||||||
// Set launch root first so that any task created after getChildContainers and
|
// Set launch root first so that any task created after getChildContainers and
|
||||||
// before reparent (pretty unlikely) are put into fullscreen.
|
// before reparent (pretty unlikely) are put into fullscreen.
|
||||||
ActivityTaskManager.getTaskOrganizerController().setLaunchRoot(Display.DEFAULT_DISPLAY,
|
TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
|
||||||
null);
|
|
||||||
// TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
|
// TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
|
||||||
// plus specific APIs to clean this up.
|
// plus specific APIs to clean this up.
|
||||||
List<ActivityManager.RunningTaskInfo> primaryChildren =
|
List<ActivityManager.RunningTaskInfo> primaryChildren =
|
||||||
ActivityTaskManager.getTaskOrganizerController().getChildTasks(
|
TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
|
||||||
tiles.mPrimary.token, null /* activityTypes */);
|
|
||||||
List<ActivityManager.RunningTaskInfo> secondaryChildren =
|
List<ActivityManager.RunningTaskInfo> secondaryChildren =
|
||||||
ActivityTaskManager.getTaskOrganizerController().getChildTasks(
|
TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
|
||||||
tiles.mSecondary.token, null /* activityTypes */);
|
|
||||||
// In some cases (eg. non-resizable is launched), system-server will leave split-screen.
|
// In some cases (eg. non-resizable is launched), system-server will leave split-screen.
|
||||||
// as a result, the above will not capture any tasks; yet, we need to clean-up the
|
// as a result, the above will not capture any tasks; yet, we need to clean-up the
|
||||||
// home task bounds.
|
// home task bounds.
|
||||||
List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
|
List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
|
||||||
ActivityTaskManager.getTaskOrganizerController().getRootTasks(
|
TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
|
||||||
Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
|
|
||||||
if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
|
if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
|
||||||
&& freeHomeAndRecents.isEmpty()) {
|
&& freeHomeAndRecents.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
@@ -281,8 +273,7 @@ public class WindowManagerProxy {
|
|||||||
}
|
}
|
||||||
// Reset focusable to true
|
// Reset focusable to true
|
||||||
wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
|
wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct,
|
WindowOrganizer.applyTransaction(wct);
|
||||||
null /* organizer */);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "Failed to remove stack: " + e);
|
Log.w(TAG, "Failed to remove stack: " + e);
|
||||||
}
|
}
|
||||||
@@ -290,8 +281,7 @@ public class WindowManagerProxy {
|
|||||||
|
|
||||||
static void applyContainerTransaction(WindowContainerTransaction wct) {
|
static void applyContainerTransaction(WindowContainerTransaction wct) {
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct,
|
WindowOrganizer.applyTransaction(wct);
|
||||||
null /* organizer */);
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.w(TAG, "Error setting focusability: " + e);
|
Log.w(TAG, "Error setting focusability: " + e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ import android.util.proto.ProtoOutputStream;
|
|||||||
import android.view.IRecentsAnimationRunner;
|
import android.view.IRecentsAnimationRunner;
|
||||||
import android.view.RemoteAnimationAdapter;
|
import android.view.RemoteAnimationAdapter;
|
||||||
import android.view.RemoteAnimationDefinition;
|
import android.view.RemoteAnimationDefinition;
|
||||||
|
import android.window.IWindowOrganizerController;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
|
||||||
@@ -663,10 +664,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
|
|
||||||
private FontScaleSettingObserver mFontScaleSettingObserver;
|
private FontScaleSettingObserver mFontScaleSettingObserver;
|
||||||
|
|
||||||
/**
|
WindowOrganizerController mWindowOrganizerController;
|
||||||
* Stores the registration and state of TaskOrganizers in use.
|
TaskOrganizerController mTaskOrganizerController;
|
||||||
*/
|
|
||||||
TaskOrganizerController mTaskOrganizerController = new TaskOrganizerController(this);
|
|
||||||
|
|
||||||
private int mDeviceOwnerUid = Process.INVALID_UID;
|
private int mDeviceOwnerUid = Process.INVALID_UID;
|
||||||
|
|
||||||
@@ -724,6 +723,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
mLifecycleManager = new ClientLifecycleManager();
|
mLifecycleManager = new ClientLifecycleManager();
|
||||||
mInternal = new LocalService();
|
mInternal = new LocalService();
|
||||||
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED);
|
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED);
|
||||||
|
mWindowOrganizerController = new WindowOrganizerController(this);
|
||||||
|
mTaskOrganizerController = mWindowOrganizerController.mTaskOrganizerController;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSystemReady() {
|
public void onSystemReady() {
|
||||||
@@ -2772,7 +2773,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
}
|
}
|
||||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
wct.reparent(stack.mRemoteToken, tile.mRemoteToken, toTop);
|
wct.reparent(stack.mRemoteToken, tile.mRemoteToken, toTop);
|
||||||
mTaskOrganizerController.applyContainerTransaction(wct, null);
|
mWindowOrganizerController.applyTransaction(wct);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -4311,7 +4312,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
wct.setBounds(secondary.mRemoteToken, otherRect);
|
wct.setBounds(secondary.mRemoteToken, otherRect);
|
||||||
mTaskOrganizerController.applyContainerTransaction(wct, null /* organizer */);
|
mWindowOrganizerController.applyTransaction(wct);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
@@ -4332,10 +4333,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ITaskOrganizerController getTaskOrganizerController() {
|
public IWindowOrganizerController getWindowOrganizerController() {
|
||||||
mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
|
mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS,
|
||||||
"getTaskOrganizerController()");
|
"getWindowOrganizerController()");
|
||||||
return mTaskOrganizerController;
|
return mWindowOrganizerController;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -531,8 +531,7 @@ public class DisplayRotation {
|
|||||||
try {
|
try {
|
||||||
mDisplayContent.sendNewConfiguration();
|
mDisplayContent.sendNewConfiguration();
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
mService.mAtmService.mTaskOrganizerController.applyContainerTransaction(t,
|
mService.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
null /* organizer */);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
mService.mAtmService.continueWindowLayout();
|
mService.mAtmService.continueWindowLayout();
|
||||||
|
|||||||
@@ -22,59 +22,34 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
|||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||||
|
|
||||||
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
|
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
|
||||||
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
|
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
|
||||||
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
|
|
||||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.app.WindowConfiguration;
|
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.ArraySet;
|
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.SurfaceControl;
|
|
||||||
import android.window.ITaskOrganizerController;
|
import android.window.ITaskOrganizerController;
|
||||||
import android.window.ITaskOrganizer;
|
import android.window.ITaskOrganizer;
|
||||||
import android.window.IWindowContainer;
|
import android.window.IWindowContainer;
|
||||||
import android.window.WindowContainerTransaction;
|
|
||||||
|
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.function.pooled.PooledConsumer;
|
|
||||||
import com.android.internal.util.function.pooled.PooledLambda;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the TaskOrganizers associated with a given windowing mode and
|
* Stores the TaskOrganizers associated with a given windowing mode and
|
||||||
* their associated state.
|
* their associated state.
|
||||||
*/
|
*/
|
||||||
class TaskOrganizerController extends ITaskOrganizerController.Stub
|
class TaskOrganizerController extends ITaskOrganizerController.Stub {
|
||||||
implements BLASTSyncEngine.TransactionReadyListener {
|
|
||||||
private static final String TAG = "TaskOrganizerController";
|
private static final String TAG = "TaskOrganizerController";
|
||||||
|
|
||||||
/** Flag indicating that an applied transaction may have effected lifecycle */
|
|
||||||
private static final int TRANSACT_EFFECTS_CLIENT_CONFIG = 1;
|
|
||||||
private static final int TRANSACT_EFFECTS_LIFECYCLE = 1 << 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Masks specifying which configurations task-organizers can control. Incoming transactions
|
|
||||||
* will be filtered to only include these.
|
|
||||||
*/
|
|
||||||
private static final int CONTROLLABLE_CONFIGS = ActivityInfo.CONFIG_WINDOW_CONFIGURATION
|
|
||||||
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE;
|
|
||||||
private static final int CONTROLLABLE_WINDOW_CONFIGS = WindowConfiguration.WINDOW_CONFIG_BOUNDS
|
|
||||||
| WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
|
|
||||||
/**
|
/**
|
||||||
* Masks specifying which configurations are important to report back to an organizer when
|
* Masks specifying which configurations are important to report back to an organizer when
|
||||||
* changed.
|
* changed.
|
||||||
@@ -181,13 +156,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub
|
|||||||
final HashMap<Integer, TaskOrganizerState> mTaskOrganizersForWindowingMode = new HashMap();
|
final HashMap<Integer, TaskOrganizerState> mTaskOrganizersForWindowingMode = new HashMap();
|
||||||
final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap();
|
final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap();
|
||||||
|
|
||||||
final HashMap<Integer, ITaskOrganizer> mTaskOrganizersByPendingSyncId = new HashMap();
|
|
||||||
|
|
||||||
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
|
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
|
||||||
private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
|
private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
|
||||||
|
|
||||||
private final BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
|
|
||||||
|
|
||||||
final ActivityTaskManagerService mService;
|
final ActivityTaskManagerService mService;
|
||||||
|
|
||||||
RunningTaskInfo mTmpTaskInfo;
|
RunningTaskInfo mTmpTaskInfo;
|
||||||
@@ -498,253 +469,4 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub
|
|||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sanitizeAndApplyChange(WindowContainer container,
|
|
||||||
WindowContainerTransaction.Change change) {
|
|
||||||
if (!(container instanceof Task)) {
|
|
||||||
throw new RuntimeException("Invalid token in task transaction");
|
|
||||||
}
|
|
||||||
final Task task = (Task) container;
|
|
||||||
// The "client"-facing API should prevent bad changes; however, just in case, sanitize
|
|
||||||
// masks here.
|
|
||||||
final int configMask = change.getConfigSetMask() & CONTROLLABLE_CONFIGS;
|
|
||||||
final int windowMask = change.getWindowSetMask() & CONTROLLABLE_WINDOW_CONFIGS;
|
|
||||||
int effects = 0;
|
|
||||||
if (configMask != 0) {
|
|
||||||
Configuration c = new Configuration(container.getRequestedOverrideConfiguration());
|
|
||||||
c.setTo(change.getConfiguration(), configMask, windowMask);
|
|
||||||
container.onRequestedOverrideConfigurationChanged(c);
|
|
||||||
// TODO(b/145675353): remove the following once we could apply new bounds to the
|
|
||||||
// pinned stack together with its children.
|
|
||||||
resizePinnedStackIfNeeded(container, configMask, windowMask, c);
|
|
||||||
effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
|
|
||||||
}
|
|
||||||
if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_FOCUSABLE) != 0) {
|
|
||||||
if (container.setFocusable(change.getFocusable())) {
|
|
||||||
effects |= TRANSACT_EFFECTS_LIFECYCLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) {
|
|
||||||
if (task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, change.getHidden())) {
|
|
||||||
effects |= TRANSACT_EFFECTS_LIFECYCLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return effects;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
|
|
||||||
WindowContainerTransaction.HierarchyOp hop) {
|
|
||||||
if (!(container instanceof Task)) {
|
|
||||||
throw new IllegalArgumentException("Invalid container in hierarchy op");
|
|
||||||
}
|
|
||||||
if (container.getDisplayContent() == null) {
|
|
||||||
Slog.w(TAG, "Container is no longer attached: " + container);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (hop.isReparent()) {
|
|
||||||
// special case for tiles since they are "virtual" parents
|
|
||||||
if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
|
|
||||||
ActivityStack as = (ActivityStack) container;
|
|
||||||
TaskTile newParent = hop.getNewParent() == null ? null
|
|
||||||
: (TaskTile) WindowContainer.fromBinder(hop.getNewParent());
|
|
||||||
if (as.getTile() != newParent) {
|
|
||||||
if (as.getTile() != null) {
|
|
||||||
as.getTile().removeChild(as);
|
|
||||||
}
|
|
||||||
if (newParent != null) {
|
|
||||||
if (!as.affectedBySplitScreenResize()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
newParent.addChild(as, POSITION_TOP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (hop.getToTop()) {
|
|
||||||
as.getDisplay().positionStackAtTop(as, false /* includingParents */);
|
|
||||||
} else {
|
|
||||||
as.getDisplay().positionStackAtBottom(as);
|
|
||||||
}
|
|
||||||
} else if (container instanceof Task) {
|
|
||||||
throw new RuntimeException("Reparenting leaf Tasks is not supported now.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Ugh, of course ActivityStack has its own special reorder logic...
|
|
||||||
if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
|
|
||||||
ActivityStack as = (ActivityStack) container;
|
|
||||||
if (hop.getToTop()) {
|
|
||||||
as.getDisplay().positionStackAtTop(as, false /* includingParents */);
|
|
||||||
} else {
|
|
||||||
as.getDisplay().positionStackAtBottom(as);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
container.getParent().positionChildAt(
|
|
||||||
hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
|
|
||||||
container, false /* includingParents */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TRANSACT_EFFECTS_LIFECYCLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask,
|
|
||||||
int windowMask, Configuration config) {
|
|
||||||
if ((container instanceof ActivityStack)
|
|
||||||
&& ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0)
|
|
||||||
&& ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) {
|
|
||||||
final ActivityStack stack = (ActivityStack) container;
|
|
||||||
if (stack.inPinnedWindowingMode()) {
|
|
||||||
stack.resize(config.windowConfiguration.getBounds(),
|
|
||||||
null /* configBounds */, PRESERVE_WINDOWS, true /* deferResume */);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int applyWindowContainerChange(WindowContainer wc,
|
|
||||||
WindowContainerTransaction.Change c) {
|
|
||||||
int effects = sanitizeAndApplyChange(wc, c);
|
|
||||||
|
|
||||||
final Task tr = wc.asTask();
|
|
||||||
|
|
||||||
final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
|
|
||||||
if (t != null) {
|
|
||||||
tr.setMainWindowSizeChangeTransaction(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect enterPipBounds = c.getEnterPipBounds();
|
|
||||||
if (enterPipBounds != null) {
|
|
||||||
mService.mStackSupervisor.updatePictureInPictureMode(tr,
|
|
||||||
enterPipBounds, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
final int windowingMode = c.getWindowingMode();
|
|
||||||
if (windowingMode > -1) {
|
|
||||||
tr.setWindowingMode(windowingMode);
|
|
||||||
}
|
|
||||||
final int childWindowingMode = c.getActivityWindowingMode();
|
|
||||||
if (childWindowingMode > -1) {
|
|
||||||
tr.setActivityWindowingMode(childWindowingMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return effects;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int applyContainerTransaction(WindowContainerTransaction t, ITaskOrganizer organizer) {
|
|
||||||
enforceStackPermission("applyContainerTransaction()");
|
|
||||||
int syncId = -1;
|
|
||||||
if (t == null) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Null transaction passed to applyContainerTransaction");
|
|
||||||
}
|
|
||||||
long ident = Binder.clearCallingIdentity();
|
|
||||||
try {
|
|
||||||
synchronized (mGlobalLock) {
|
|
||||||
int effects = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If organizer is non-null we are looking to synchronize this transaction
|
|
||||||
* by collecting all the results in to a SurfaceFlinger transaction and
|
|
||||||
* then delivering that to the given organizers transaction ready callback.
|
|
||||||
* See {@link BLASTSyncEngine} for the details of the operation. But at
|
|
||||||
* a high level we create a sync operation with a given ID and an associated
|
|
||||||
* organizer. Then we notify each WindowContainer in this WindowContainer
|
|
||||||
* transaction that it is participating in a sync operation with that
|
|
||||||
* ID. Once everything is notified we tell the BLASTSyncEngine
|
|
||||||
* "setSyncReady" which means that we have added everything
|
|
||||||
* to the set. At any point after this, all the WindowContainers
|
|
||||||
* will eventually finish applying their changes and notify the
|
|
||||||
* BLASTSyncEngine which will deliver the Transaction to the organizer.
|
|
||||||
*/
|
|
||||||
if (organizer != null) {
|
|
||||||
syncId = startSyncWithOrganizer(organizer);
|
|
||||||
}
|
|
||||||
mService.deferWindowLayout();
|
|
||||||
try {
|
|
||||||
ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
|
|
||||||
Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
|
|
||||||
t.getChanges().entrySet().iterator();
|
|
||||||
while (entries.hasNext()) {
|
|
||||||
final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
|
|
||||||
entries.next();
|
|
||||||
final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
|
|
||||||
int containerEffect = applyWindowContainerChange(wc, entry.getValue());
|
|
||||||
effects |= containerEffect;
|
|
||||||
|
|
||||||
// Lifecycle changes will trigger ensureConfig for everything.
|
|
||||||
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
|
|
||||||
&& (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
|
|
||||||
haveConfigChanges.add(wc);
|
|
||||||
}
|
|
||||||
if (syncId >= 0) {
|
|
||||||
mBLASTSyncEngine.addToSyncSet(syncId, wc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Hierarchy changes
|
|
||||||
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
|
|
||||||
for (int i = 0, n = hops.size(); i < n; ++i) {
|
|
||||||
final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
|
|
||||||
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
|
|
||||||
effects |= sanitizeAndApplyHierarchyOp(wc, hop);
|
|
||||||
}
|
|
||||||
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
|
|
||||||
// Already calls ensureActivityConfig
|
|
||||||
mService.mRootWindowContainer.ensureActivitiesVisible(
|
|
||||||
null, 0, PRESERVE_WINDOWS);
|
|
||||||
} else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
|
|
||||||
final PooledConsumer f = PooledLambda.obtainConsumer(
|
|
||||||
ActivityRecord::ensureActivityConfiguration,
|
|
||||||
PooledLambda.__(ActivityRecord.class), 0,
|
|
||||||
false /* preserveWindow */);
|
|
||||||
try {
|
|
||||||
for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
|
|
||||||
final WindowContainer wc = haveConfigChanges.valueAt(i);
|
|
||||||
final Task task = wc.asTask();
|
|
||||||
final TaskTile tile = task != null ? task.asTile() : null;
|
|
||||||
if (tile != null) {
|
|
||||||
// Special case for tile. Can't override normal forAllActivities
|
|
||||||
// because it generates duplicate calls and messes up existing
|
|
||||||
// code-paths.
|
|
||||||
tile.forAllTileActivities(f);
|
|
||||||
} else {
|
|
||||||
wc.forAllActivities(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
f.recycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
mService.continueWindowLayout();
|
|
||||||
if (syncId >= 0) {
|
|
||||||
setSyncReady(syncId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Binder.restoreCallingIdentity(ident);
|
|
||||||
}
|
|
||||||
return syncId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction sc) {
|
|
||||||
final ITaskOrganizer organizer = mTaskOrganizersByPendingSyncId.get(id);
|
|
||||||
if (organizer == null) {
|
|
||||||
Slog.e(TAG, "Got transaction complete for unexpected ID");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
organizer.transactionReady(id, sc);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
mTaskOrganizersByPendingSyncId.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int startSyncWithOrganizer(ITaskOrganizer organizer) {
|
|
||||||
int id = mBLASTSyncEngine.startSyncSet(this);
|
|
||||||
mTaskOrganizersByPendingSyncId.put(id, organizer);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSyncReady(int id) {
|
|
||||||
mBLASTSyncEngine.setReady(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,347 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
|
||||||
|
|
||||||
|
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
|
||||||
|
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
|
||||||
|
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
|
||||||
|
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||||
|
|
||||||
|
import android.app.WindowConfiguration;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
import android.util.Slog;
|
||||||
|
import android.view.SurfaceControl;
|
||||||
|
import android.window.ITaskOrganizerController;
|
||||||
|
import android.window.IWindowContainerTransactionCallback;
|
||||||
|
import android.window.IWindowOrganizerController;
|
||||||
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
|
import com.android.internal.util.function.pooled.PooledConsumer;
|
||||||
|
import com.android.internal.util.function.pooled.PooledLambda;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server side implementation for the interface for organizing windows
|
||||||
|
* @see android.window.WindowOrganizer
|
||||||
|
*/
|
||||||
|
class WindowOrganizerController extends IWindowOrganizerController.Stub
|
||||||
|
implements BLASTSyncEngine.TransactionReadyListener {
|
||||||
|
|
||||||
|
private static final String TAG = "WindowOrganizerController";
|
||||||
|
|
||||||
|
/** Flag indicating that an applied transaction may have effected lifecycle */
|
||||||
|
private static final int TRANSACT_EFFECTS_CLIENT_CONFIG = 1;
|
||||||
|
private static final int TRANSACT_EFFECTS_LIFECYCLE = 1 << 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Masks specifying which configurations task-organizers can control. Incoming transactions
|
||||||
|
* will be filtered to only include these.
|
||||||
|
*/
|
||||||
|
static final int CONTROLLABLE_CONFIGS = ActivityInfo.CONFIG_WINDOW_CONFIGURATION
|
||||||
|
| ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_SIZE;
|
||||||
|
static final int CONTROLLABLE_WINDOW_CONFIGS = WindowConfiguration.WINDOW_CONFIG_BOUNDS
|
||||||
|
| WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
|
||||||
|
|
||||||
|
private final ActivityTaskManagerService mService;
|
||||||
|
private final WindowManagerGlobalLock mGlobalLock;
|
||||||
|
|
||||||
|
private final BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
|
||||||
|
private final HashMap<Integer, IWindowContainerTransactionCallback>
|
||||||
|
mTransactionCallbacksByPendingSyncId = new HashMap();
|
||||||
|
|
||||||
|
final TaskOrganizerController mTaskOrganizerController;
|
||||||
|
|
||||||
|
WindowOrganizerController(ActivityTaskManagerService atm) {
|
||||||
|
mService = atm;
|
||||||
|
mGlobalLock = atm.mGlobalLock;
|
||||||
|
mTaskOrganizerController = new TaskOrganizerController(mService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyTransaction(WindowContainerTransaction t) {
|
||||||
|
applySyncTransaction(t, null /*callback*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int applySyncTransaction(WindowContainerTransaction t,
|
||||||
|
IWindowContainerTransactionCallback callback) {
|
||||||
|
enforceStackPermission("applySyncTransaction()");
|
||||||
|
int syncId = -1;
|
||||||
|
if (t == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Null transaction passed to applySyncTransaction");
|
||||||
|
}
|
||||||
|
long ident = Binder.clearCallingIdentity();
|
||||||
|
try {
|
||||||
|
synchronized (mGlobalLock) {
|
||||||
|
int effects = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If callback is non-null we are looking to synchronize this transaction by
|
||||||
|
* collecting all the results in to a SurfaceFlinger transaction and then delivering
|
||||||
|
* that to the given transaction ready callback. See {@link BLASTSyncEngine} for the
|
||||||
|
* details of the operation. But at a high level we create a sync operation with a
|
||||||
|
* given ID and an associated callback. Then we notify each WindowContainer in this
|
||||||
|
* WindowContainer transaction that it is participating in a sync operation with
|
||||||
|
* that ID. Once everything is notified we tell the BLASTSyncEngine "setSyncReady"
|
||||||
|
* which means that we have added everything to the set. At any point after this,
|
||||||
|
* all the WindowContainers will eventually finish applying their changes and notify
|
||||||
|
* the BLASTSyncEngine which will deliver the Transaction to the callback.
|
||||||
|
*/
|
||||||
|
if (callback != null) {
|
||||||
|
syncId = startSyncWithOrganizer(callback);
|
||||||
|
}
|
||||||
|
mService.deferWindowLayout();
|
||||||
|
try {
|
||||||
|
ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
|
||||||
|
Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
|
||||||
|
t.getChanges().entrySet().iterator();
|
||||||
|
while (entries.hasNext()) {
|
||||||
|
final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
|
||||||
|
entries.next();
|
||||||
|
final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
|
||||||
|
int containerEffect = applyWindowContainerChange(wc, entry.getValue());
|
||||||
|
effects |= containerEffect;
|
||||||
|
|
||||||
|
// Lifecycle changes will trigger ensureConfig for everything.
|
||||||
|
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
|
||||||
|
&& (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
|
||||||
|
haveConfigChanges.add(wc);
|
||||||
|
}
|
||||||
|
if (syncId >= 0) {
|
||||||
|
mBLASTSyncEngine.addToSyncSet(syncId, wc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Hierarchy changes
|
||||||
|
final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
|
||||||
|
for (int i = 0, n = hops.size(); i < n; ++i) {
|
||||||
|
final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
|
||||||
|
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
|
||||||
|
effects |= sanitizeAndApplyHierarchyOp(wc, hop);
|
||||||
|
}
|
||||||
|
if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
|
||||||
|
// Already calls ensureActivityConfig
|
||||||
|
mService.mRootWindowContainer.ensureActivitiesVisible(
|
||||||
|
null, 0, PRESERVE_WINDOWS);
|
||||||
|
} else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
|
||||||
|
final PooledConsumer f = PooledLambda.obtainConsumer(
|
||||||
|
ActivityRecord::ensureActivityConfiguration,
|
||||||
|
PooledLambda.__(ActivityRecord.class), 0,
|
||||||
|
false /* preserveWindow */);
|
||||||
|
try {
|
||||||
|
for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
|
||||||
|
final WindowContainer wc = haveConfigChanges.valueAt(i);
|
||||||
|
final Task task = wc.asTask();
|
||||||
|
final TaskTile tile = task != null ? task.asTile() : null;
|
||||||
|
if (tile != null) {
|
||||||
|
// Special case for tile. Can't override normal forAllActivities
|
||||||
|
// because it generates duplicate calls and messes up existing
|
||||||
|
// code-paths.
|
||||||
|
tile.forAllTileActivities(f);
|
||||||
|
} else {
|
||||||
|
wc.forAllActivities(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
f.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
mService.continueWindowLayout();
|
||||||
|
if (syncId >= 0) {
|
||||||
|
setSyncReady(syncId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
|
}
|
||||||
|
return syncId;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int sanitizeAndApplyChange(WindowContainer container,
|
||||||
|
WindowContainerTransaction.Change change) {
|
||||||
|
if (!(container instanceof Task)) {
|
||||||
|
throw new RuntimeException("Invalid token in task transaction");
|
||||||
|
}
|
||||||
|
final Task task = (Task) container;
|
||||||
|
// The "client"-facing API should prevent bad changes; however, just in case, sanitize
|
||||||
|
// masks here.
|
||||||
|
final int configMask = change.getConfigSetMask() & CONTROLLABLE_CONFIGS;
|
||||||
|
final int windowMask = change.getWindowSetMask() & CONTROLLABLE_WINDOW_CONFIGS;
|
||||||
|
int effects = 0;
|
||||||
|
if (configMask != 0) {
|
||||||
|
Configuration c = new Configuration(container.getRequestedOverrideConfiguration());
|
||||||
|
c.setTo(change.getConfiguration(), configMask, windowMask);
|
||||||
|
container.onRequestedOverrideConfigurationChanged(c);
|
||||||
|
// TODO(b/145675353): remove the following once we could apply new bounds to the
|
||||||
|
// pinned stack together with its children.
|
||||||
|
resizePinnedStackIfNeeded(container, configMask, windowMask, c);
|
||||||
|
effects |= TRANSACT_EFFECTS_CLIENT_CONFIG;
|
||||||
|
}
|
||||||
|
if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_FOCUSABLE) != 0) {
|
||||||
|
if (container.setFocusable(change.getFocusable())) {
|
||||||
|
effects |= TRANSACT_EFFECTS_LIFECYCLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) {
|
||||||
|
if (task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, change.getHidden())) {
|
||||||
|
effects |= TRANSACT_EFFECTS_LIFECYCLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int sanitizeAndApplyHierarchyOp(WindowContainer container,
|
||||||
|
WindowContainerTransaction.HierarchyOp hop) {
|
||||||
|
if (!(container instanceof Task)) {
|
||||||
|
throw new IllegalArgumentException("Invalid container in hierarchy op");
|
||||||
|
}
|
||||||
|
if (container.getDisplayContent() == null) {
|
||||||
|
Slog.w(TAG, "Container is no longer attached: " + container);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (hop.isReparent()) {
|
||||||
|
// special case for tiles since they are "virtual" parents
|
||||||
|
if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
|
||||||
|
ActivityStack as = (ActivityStack) container;
|
||||||
|
TaskTile newParent = hop.getNewParent() == null ? null
|
||||||
|
: (TaskTile) WindowContainer.fromBinder(hop.getNewParent());
|
||||||
|
if (as.getTile() != newParent) {
|
||||||
|
if (as.getTile() != null) {
|
||||||
|
as.getTile().removeChild(as);
|
||||||
|
}
|
||||||
|
if (newParent != null) {
|
||||||
|
if (!as.affectedBySplitScreenResize()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
newParent.addChild(as, POSITION_TOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hop.getToTop()) {
|
||||||
|
as.getDisplay().positionStackAtTop(as, false /* includingParents */);
|
||||||
|
} else {
|
||||||
|
as.getDisplay().positionStackAtBottom(as);
|
||||||
|
}
|
||||||
|
} else if (container instanceof Task) {
|
||||||
|
throw new RuntimeException("Reparenting leaf Tasks is not supported now.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Ugh, of course ActivityStack has its own special reorder logic...
|
||||||
|
if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
|
||||||
|
ActivityStack as = (ActivityStack) container;
|
||||||
|
if (hop.getToTop()) {
|
||||||
|
as.getDisplay().positionStackAtTop(as, false /* includingParents */);
|
||||||
|
} else {
|
||||||
|
as.getDisplay().positionStackAtBottom(as);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
container.getParent().positionChildAt(
|
||||||
|
hop.getToTop() ? POSITION_TOP : POSITION_BOTTOM,
|
||||||
|
container, false /* includingParents */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRANSACT_EFFECTS_LIFECYCLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int applyWindowContainerChange(WindowContainer wc,
|
||||||
|
WindowContainerTransaction.Change c) {
|
||||||
|
int effects = sanitizeAndApplyChange(wc, c);
|
||||||
|
|
||||||
|
final Task tr = wc.asTask();
|
||||||
|
|
||||||
|
final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
|
||||||
|
if (t != null) {
|
||||||
|
tr.setMainWindowSizeChangeTransaction(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect enterPipBounds = c.getEnterPipBounds();
|
||||||
|
if (enterPipBounds != null) {
|
||||||
|
mService.mStackSupervisor.updatePictureInPictureMode(tr,
|
||||||
|
enterPipBounds, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int windowingMode = c.getWindowingMode();
|
||||||
|
if (windowingMode > -1) {
|
||||||
|
tr.setWindowingMode(windowingMode);
|
||||||
|
}
|
||||||
|
final int childWindowingMode = c.getActivityWindowingMode();
|
||||||
|
if (childWindowingMode > -1) {
|
||||||
|
tr.setActivityWindowingMode(childWindowingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return effects;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask,
|
||||||
|
int windowMask, Configuration config) {
|
||||||
|
if ((container instanceof ActivityStack)
|
||||||
|
&& ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0)
|
||||||
|
&& ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) {
|
||||||
|
final ActivityStack stack = (ActivityStack) container;
|
||||||
|
if (stack.inPinnedWindowingMode()) {
|
||||||
|
stack.resize(config.windowConfiguration.getBounds(),
|
||||||
|
null /* configBounds */, PRESERVE_WINDOWS, true /* deferResume */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ITaskOrganizerController getTaskOrganizerController() {
|
||||||
|
enforceStackPermission("getTaskOrganizerController()");
|
||||||
|
return mTaskOrganizerController;
|
||||||
|
}
|
||||||
|
|
||||||
|
int startSyncWithOrganizer(IWindowContainerTransactionCallback callback) {
|
||||||
|
int id = mBLASTSyncEngine.startSyncSet(this);
|
||||||
|
mTransactionCallbacksByPendingSyncId.put(id, callback);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSyncReady(int id) {
|
||||||
|
mBLASTSyncEngine.setReady(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
|
||||||
|
final IWindowContainerTransactionCallback callback =
|
||||||
|
mTransactionCallbacksByPendingSyncId.get(mSyncId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
callback.transactionReady(mSyncId, mergedTransaction);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
mTransactionCallbacksByPendingSyncId.remove(mSyncId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enforceStackPermission(String func) {
|
||||||
|
mService.mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, func);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1026,9 +1026,6 @@ public class ActivityStarterTests extends ActivityTestsBase {
|
|||||||
public void taskVanished(ActivityManager.RunningTaskInfo info) {
|
public void taskVanished(ActivityManager.RunningTaskInfo info) {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) {
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
||||||
if (mInSplit) {
|
if (mInSplit) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||||
Rect newBounds = new Rect(10, 10, 100, 100);
|
Rect newBounds = new Rect(10, 10, 100, 100);
|
||||||
t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
|
t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertEquals(newBounds, task.getBounds());
|
assertEquals(newBounds, task.getBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
assertEquals(stack.mRemoteToken, info.stackToken);
|
assertEquals(stack.mRemoteToken, info.stackToken);
|
||||||
Rect newBounds = new Rect(10, 10, 100, 100);
|
Rect newBounds = new Rect(10, 10, 100, 100);
|
||||||
t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
|
t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertEquals(newBounds, stack.getBounds());
|
assertEquals(newBounds, stack.getBounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
final WindowContainerTransaction t = new WindowContainerTransaction();
|
final WindowContainerTransaction t = new WindowContainerTransaction();
|
||||||
|
|
||||||
t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
|
t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
|
|
||||||
assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode());
|
assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode());
|
||||||
}
|
}
|
||||||
@@ -270,7 +270,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
|
|
||||||
t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED);
|
t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED);
|
||||||
t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
|
t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
|
|
||||||
assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
|
assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
|
||||||
assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode());
|
assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode());
|
||||||
@@ -285,10 +285,10 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||||
assertTrue(task.isFocusable());
|
assertTrue(task.isFocusable());
|
||||||
t.setFocusable(stack.mRemoteToken, false);
|
t.setFocusable(stack.mRemoteToken, false);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertFalse(task.isFocusable());
|
assertFalse(task.isFocusable());
|
||||||
t.setFocusable(stack.mRemoteToken, true);
|
t.setFocusable(stack.mRemoteToken, true);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertTrue(task.isFocusable());
|
assertTrue(task.isFocusable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,10 +300,10 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||||
assertTrue(stack.shouldBeVisible(null));
|
assertTrue(stack.shouldBeVisible(null));
|
||||||
t.setHidden(stack.mRemoteToken, true);
|
t.setHidden(stack.mRemoteToken, true);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertFalse(stack.shouldBeVisible(null));
|
assertFalse(stack.shouldBeVisible(null));
|
||||||
t.setHidden(stack.mRemoteToken, false);
|
t.setHidden(stack.mRemoteToken, false);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertTrue(stack.shouldBeVisible(null));
|
assertTrue(stack.shouldBeVisible(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,19 +315,19 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
final Task task = stack.getTopMostTask();
|
final Task task = stack.getTopMostTask();
|
||||||
WindowContainerTransaction t = new WindowContainerTransaction();
|
WindowContainerTransaction t = new WindowContainerTransaction();
|
||||||
t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
|
t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
final int origScreenWDp = task.getConfiguration().screenHeightDp;
|
final int origScreenWDp = task.getConfiguration().screenHeightDp;
|
||||||
final int origScreenHDp = task.getConfiguration().screenHeightDp;
|
final int origScreenHDp = task.getConfiguration().screenHeightDp;
|
||||||
t = new WindowContainerTransaction();
|
t = new WindowContainerTransaction();
|
||||||
// verify that setting config overrides on parent restricts children.
|
// verify that setting config overrides on parent restricts children.
|
||||||
t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp);
|
t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp);
|
||||||
t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200));
|
t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200));
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
|
assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
|
||||||
t = new WindowContainerTransaction();
|
t = new WindowContainerTransaction();
|
||||||
t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED,
|
t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED,
|
||||||
Configuration.SCREEN_HEIGHT_DP_UNDEFINED);
|
Configuration.SCREEN_HEIGHT_DP_UNDEFINED);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
|
||||||
assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
|
assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,9 +401,6 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
@Override
|
@Override
|
||||||
public void taskVanished(RunningTaskInfo container) { }
|
public void taskVanished(RunningTaskInfo container) { }
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) { }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
|
public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
|
||||||
lastReportedTiles.add(info);
|
lastReportedTiles.add(info);
|
||||||
@@ -455,9 +452,6 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
@Override
|
@Override
|
||||||
public void taskVanished(RunningTaskInfo container) { }
|
public void taskVanished(RunningTaskInfo container) { }
|
||||||
|
|
||||||
@Override
|
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) { }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo info) {
|
public void onTaskInfoChanged(RunningTaskInfo info) {
|
||||||
lastReportedTiles.put(info.token.asBinder(), info);
|
lastReportedTiles.put(info.token.asBinder(), info);
|
||||||
@@ -487,8 +481,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
|
wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
|
||||||
wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */);
|
wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct,
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
|
||||||
null /* organizer */);
|
|
||||||
assertFalse(lastReportedTiles.isEmpty());
|
assertFalse(lastReportedTiles.isEmpty());
|
||||||
assertEquals(ACTIVITY_TYPE_STANDARD,
|
assertEquals(ACTIVITY_TYPE_STANDARD,
|
||||||
lastReportedTiles.get(info1.token.asBinder()).topActivityType);
|
lastReportedTiles.get(info1.token.asBinder()).topActivityType);
|
||||||
@@ -498,8 +491,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
lastReportedTiles.clear();
|
lastReportedTiles.clear();
|
||||||
wct = new WindowContainerTransaction();
|
wct = new WindowContainerTransaction();
|
||||||
wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */);
|
wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct,
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
|
||||||
null /* organizer */);
|
|
||||||
assertFalse(lastReportedTiles.isEmpty());
|
assertFalse(lastReportedTiles.isEmpty());
|
||||||
// Standard should still be on top of tile 1, so no change there
|
// Standard should still be on top of tile 1, so no change there
|
||||||
assertFalse(lastReportedTiles.containsKey(info1.token.asBinder()));
|
assertFalse(lastReportedTiles.containsKey(info1.token.asBinder()));
|
||||||
@@ -524,8 +516,7 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
lastReportedTiles.clear();
|
lastReportedTiles.clear();
|
||||||
wct = new WindowContainerTransaction();
|
wct = new WindowContainerTransaction();
|
||||||
wct.reorder(stack2.mRemoteToken, true /* onTop */);
|
wct.reorder(stack2.mRemoteToken, true /* onTop */);
|
||||||
mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(wct,
|
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
|
||||||
null /* organizer */);
|
|
||||||
// Home should now be on top. No change occurs in second tile, so not reported
|
// Home should now be on top. No change occurs in second tile, so not reported
|
||||||
assertEquals(1, lastReportedTiles.size());
|
assertEquals(1, lastReportedTiles.size());
|
||||||
assertEquals(ACTIVITY_TYPE_HOME,
|
assertEquals(ACTIVITY_TYPE_HOME,
|
||||||
@@ -683,9 +674,6 @@ public class TaskOrganizerTests extends WindowTestsBase {
|
|||||||
public void taskVanished(RunningTaskInfo info) {
|
public void taskVanished(RunningTaskInfo info) {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) {
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onTaskInfoChanged(RunningTaskInfo info) {
|
public void onTaskInfoChanged(RunningTaskInfo info) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
package com.android.test.taskembed;
|
package com.android.test.taskembed;
|
||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityTaskManager;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -27,6 +27,8 @@ import android.content.Intent;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
@@ -34,8 +36,10 @@ import android.view.SurfaceHolder;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.window.ITaskOrganizer;
|
import android.window.ITaskOrganizer;
|
||||||
|
import android.window.IWindowContainerTransactionCallback;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
public class TaskOrganizerMultiWindowTest extends Activity {
|
public class TaskOrganizerMultiWindowTest extends Activity {
|
||||||
class SplitLayout extends LinearLayout implements View.OnTouchListener {
|
class SplitLayout extends LinearLayout implements View.OnTouchListener {
|
||||||
@@ -112,8 +116,7 @@ public class TaskOrganizerMultiWindowTest extends Activity {
|
|||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
wct.setBounds(mWc, new Rect(0, 0, width, height));
|
wct.setBounds(mWc, new Rect(0, 0, width, height));
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct,
|
WindowOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
|
||||||
mOrganizer);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// Oh well
|
// Oh well
|
||||||
}
|
}
|
||||||
@@ -127,6 +130,25 @@ public class TaskOrganizerMultiWindowTest extends Activity {
|
|||||||
class Organizer extends ITaskOrganizer.Stub {
|
class Organizer extends ITaskOrganizer.Stub {
|
||||||
private int receivedTransactions = 0;
|
private int receivedTransactions = 0;
|
||||||
SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
|
SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
|
||||||
|
IWindowContainerTransactionCallback mTransactionCallback =
|
||||||
|
new IWindowContainerTransactionCallback() {
|
||||||
|
@Override
|
||||||
|
public void transactionReady(int id, SurfaceControl.Transaction t)
|
||||||
|
throws RemoteException {
|
||||||
|
mergedTransaction.merge(t);
|
||||||
|
receivedTransactions++;
|
||||||
|
if (receivedTransactions == 2) {
|
||||||
|
mergedTransaction.apply();
|
||||||
|
receivedTransactions = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder asBinder() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void taskAppeared(ActivityManager.RunningTaskInfo ti) {
|
public void taskAppeared(ActivityManager.RunningTaskInfo ti) {
|
||||||
if (!gotFirstTask) {
|
if (!gotFirstTask) {
|
||||||
@@ -138,14 +160,6 @@ public class TaskOrganizerMultiWindowTest extends Activity {
|
|||||||
}
|
}
|
||||||
public void taskVanished(ActivityManager.RunningTaskInfo ti) {
|
public void taskVanished(ActivityManager.RunningTaskInfo ti) {
|
||||||
}
|
}
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) {
|
|
||||||
mergedTransaction.merge(t);
|
|
||||||
receivedTransactions++;
|
|
||||||
if (receivedTransactions == 2) {
|
|
||||||
mergedTransaction.apply();
|
|
||||||
receivedTransactions = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
||||||
}
|
}
|
||||||
@@ -158,9 +172,7 @@ public class TaskOrganizerMultiWindowTest extends Activity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(mOrganizer,
|
TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_MULTI_WINDOW);
|
||||||
WINDOWING_MODE_MULTI_WINDOW);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,19 +17,19 @@
|
|||||||
package com.android.test.taskembed;
|
package com.android.test.taskembed;
|
||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||||
|
import static android.window.WindowOrganizer.TaskOrganizer;
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityTaskManager;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.view.SurfaceControl;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.window.ITaskOrganizer;
|
import android.window.ITaskOrganizer;
|
||||||
import android.window.WindowContainerTransaction;
|
import android.window.WindowContainerTransaction;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
import android.window.WindowOrganizer;
|
||||||
|
|
||||||
public class TaskOrganizerPipTest extends Service {
|
public class TaskOrganizerPipTest extends Service {
|
||||||
static final int PIP_WIDTH = 640;
|
static final int PIP_WIDTH = 640;
|
||||||
@@ -44,14 +44,12 @@ public class TaskOrganizerPipTest extends Service {
|
|||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
wct.scheduleFinishEnterPip(ti.token, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT));
|
wct.scheduleFinishEnterPip(ti.token, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT));
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct, null);
|
WindowOrganizer.applyTransaction(wct);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void taskVanished(ActivityManager.RunningTaskInfo ti) {
|
public void taskVanished(ActivityManager.RunningTaskInfo ti) {
|
||||||
}
|
}
|
||||||
public void transactionReady(int id, SurfaceControl.Transaction t) {
|
|
||||||
}
|
|
||||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,9 +66,7 @@ public class TaskOrganizerPipTest extends Service {
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ActivityTaskManager.getTaskOrganizerController().registerTaskOrganizer(mOrganizer,
|
TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_PINNED);
|
||||||
WINDOWING_MODE_PINNED);
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user