diff options
4 files changed, 71 insertions, 46 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java index 01498f933383..66e321145701 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java @@ -25,6 +25,7 @@ import static android.window.WindowOrganizer.TaskOrganizer; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.app.ActivityTaskManager; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; @@ -32,11 +33,11 @@ import android.os.Handler; import android.os.RemoteException; import android.provider.Settings; import android.util.Slog; -import android.window.IWindowContainer; import android.view.LayoutInflater; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.View; +import android.window.IWindowContainer; import android.window.WindowContainerTransaction; import android.window.WindowOrganizer; @@ -112,6 +113,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, private DisplayChangeController.OnDisplayChangingListener mRotationController = (display, fromRotation, toRotation, t) -> { + if (!mSplits.isSplitScreenSupported()) { + return; + } DisplayLayout displayLayout = new DisplayLayout(mDisplayController.getDisplayLayout(display)); SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits); @@ -472,6 +476,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, mDisplayController.getDisplayLayout(displayId), mSplits); mImeController.addPositionProcessor(mImePositionProcessor); mDisplayController.addDisplayChangingController(mRotationController); + if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) { + removeDivider(); + return; + } try { mSplits.init(mSurfaceSession); // Set starting tile bounds based on middle target @@ -481,13 +489,15 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks, WindowOrganizer.applyTransaction(tct); } catch (Exception e) { Slog.e(TAG, "Failed to register docked stack listener", e); + removeDivider(); + return; } update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration()); } @Override public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { - if (displayId != DEFAULT_DISPLAY) { + if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) { return; } mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId), diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 1aa78311a989..1e4c8e4dc268 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -25,7 +25,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.Nullable; -import android.app.ActivityTaskManager; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; @@ -130,7 +129,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, private int mDividerInsets; private final Display mDefaultDisplay; - private boolean mSupportSplitScreenMultiWindow; private int mDividerSize; private int mTouchElevation; @@ -284,8 +282,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, final DisplayManager displayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); - mSupportSplitScreenMultiWindow = - ActivityTaskManager.supportsSplitScreenMultiWindow(mContext); } @Override @@ -358,11 +354,6 @@ public class DividerView extends FrameLayout implements OnTouchListener, @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (!mSupportSplitScreenMultiWindow) { - super.onLayout(changed, left, top, right, bottom); - return; - } - if (mFirstLayout) { // Wait for first layout so that the ViewRootImpl surface has been created. initializeSurfaceState(); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java index 6cb7f4ff7204..0a528a63009e 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java @@ -49,6 +49,7 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub { ArrayList<SurfaceControl> mHomeAndRecentsSurfaces = new ArrayList<>(); Rect mHomeBounds = new Rect(); final Divider mDivider; + private boolean mSplitScreenSupported = false; SplitScreenTaskOrganizer(Divider divider) { mDivider = divider; @@ -57,12 +58,19 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub { void init(SurfaceSession session) throws RemoteException { TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, - WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, - WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); - mPrimarySurface = mPrimary.token.getLeash(); - mSecondarySurface = mSecondary.token.getLeash(); + try { + mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, + WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); + mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, + WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); + mPrimarySurface = mPrimary.token.getLeash(); + mSecondarySurface = mSecondary.token.getLeash(); + } catch (RemoteException e) { + // teardown to prevent callbacks + TaskOrganizer.unregisterOrganizer(this); + throw e; + } + mSplitScreenSupported = true; // Initialize dim surfaces: mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface) @@ -78,6 +86,10 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub { releaseTransaction(t); } + boolean isSplitScreenSupported() { + return mSplitScreenSupported; + } + SurfaceControl.Transaction getTransaction() { return mDivider.mTransactionPool.acquire(); } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 4382e9d578ad..8a896f52eea7 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -20,14 +20,13 @@ import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; -import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS; import android.annotation.Nullable; import android.app.ActivityManager.RunningTaskInfo; +import android.app.WindowConfiguration; import android.content.Intent; import android.content.pm.ActivityInfo; import android.os.Binder; @@ -53,7 +52,7 @@ import java.util.WeakHashMap; */ class TaskOrganizerController extends ITaskOrganizerController.Stub { private static final String TAG = "TaskOrganizerController"; - private static final LinkedList<TaskOrganizerState> EMPTY_LIST = new LinkedList<>(); + private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>(); /** * Masks specifying which configurations are important to report back to an organizer when @@ -65,12 +64,10 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { private final WindowManagerGlobalLock mGlobalLock; private class DeathRecipient implements IBinder.DeathRecipient { - int mWindowingMode; ITaskOrganizer mTaskOrganizer; - DeathRecipient(ITaskOrganizer organizer, int windowingMode) { + DeathRecipient(ITaskOrganizer organizer) { mTaskOrganizer = organizer; - mWindowingMode = windowingMode; } @Override @@ -86,18 +83,16 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { private class TaskOrganizerState { private final ITaskOrganizer mOrganizer; private final DeathRecipient mDeathRecipient; - private final int mWindowingMode; private final ArrayList<Task> mOrganizedTasks = new ArrayList<>(); - TaskOrganizerState(ITaskOrganizer organizer, int windowingMode) { + TaskOrganizerState(ITaskOrganizer organizer) { mOrganizer = organizer; - mDeathRecipient = new DeathRecipient(organizer, windowingMode); + mDeathRecipient = new DeathRecipient(organizer); try { organizer.asBinder().linkToDeath(mDeathRecipient, 0); } catch (RemoteException e) { Slog.e(TAG, "TaskOrganizer failed to register death recipient"); } - mWindowingMode = windowingMode; } void addTask(Task t) { @@ -120,7 +115,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { void dispose() { releaseTasks(); - mTaskOrganizersForWindowingMode.get(mWindowingMode).remove(this); + for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) { + mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.asBinder()); + } } private void releaseTasks() { @@ -136,7 +133,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } } - private final SparseArray<LinkedList<TaskOrganizerState>> mTaskOrganizersForWindowingMode = + private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode = new SparseArray<>(); private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>(); private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); @@ -162,10 +159,22 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { */ @Override public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) { - if (windowingMode != WINDOWING_MODE_PINNED - && windowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY - && windowingMode != WINDOWING_MODE_SPLIT_SCREEN_SECONDARY - && windowingMode != WINDOWING_MODE_MULTI_WINDOW) { + if (windowingMode == WINDOWING_MODE_PINNED) { + if (!mService.mSupportsPictureInPicture) { + throw new UnsupportedOperationException("Picture in picture is not supported on " + + "this device"); + } + } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) { + if (!mService.mSupportsSplitScreenMultiWindow) { + throw new UnsupportedOperationException("Split-screen is not supported on this " + + "device"); + } + } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) { + if (!mService.mSupportsMultiWindow) { + throw new UnsupportedOperationException("Multi-window is not supported on this " + + "device"); + } + } else { throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow" + " windowing modes are supported for registerTaskOrganizer"); } @@ -178,19 +187,18 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { + windowingMode); } - LinkedList<TaskOrganizerState> states; - if (mTaskOrganizersForWindowingMode.contains(windowingMode)) { - states = mTaskOrganizersForWindowingMode.get(windowingMode); - } else { - states = new LinkedList<>(); - mTaskOrganizersForWindowingMode.put(windowingMode, states); + LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode); + if (orgs == null) { + orgs = new LinkedList<>(); + mTaskOrganizersForWindowingMode.put(windowingMode, orgs); + } + orgs.add(organizer.asBinder()); + if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) { + mTaskOrganizerStates.put(organizer.asBinder(), + new TaskOrganizerState(organizer)); } - final TaskOrganizerState previousState = states.peekLast(); - final TaskOrganizerState state = new TaskOrganizerState(organizer, windowingMode); - states.add(state); - mTaskOrganizerStates.put(organizer.asBinder(), state); - if (previousState == null) { + if (orgs.size() == 1) { // Only in the case where this is the root task organizer for the given // windowing mode, we add report all existing tasks in that mode to the new // task organizer. @@ -214,8 +222,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { } ITaskOrganizer getTaskOrganizer(int windowingMode) { - final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode, - EMPTY_LIST).peekLast(); + final IBinder organizer = + mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast(); + if (organizer == null) { + return null; + } + final TaskOrganizerState state = mTaskOrganizerStates.get(organizer); if (state == null) { return null; } |