Merge "Fix crash on devices that don't support multiwindow" into rvc-dev

This commit is contained in:
Evan Rosky
2020-03-28 00:40:49 +00:00
committed by Android (Google) Code Review
4 changed files with 71 additions and 46 deletions

View File

@@ -25,6 +25,7 @@ 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;
@@ -32,11 +33,11 @@ import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.provider.Settings; import android.provider.Settings;
import android.util.Slog; import android.util.Slog;
import android.window.IWindowContainer;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.SurfaceSession; import android.view.SurfaceSession;
import android.view.View; import android.view.View;
import android.window.IWindowContainer;
import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction;
import android.window.WindowOrganizer; import android.window.WindowOrganizer;
@@ -112,6 +113,9 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
private DisplayChangeController.OnDisplayChangingListener mRotationController = private DisplayChangeController.OnDisplayChangingListener mRotationController =
(display, fromRotation, toRotation, t) -> { (display, fromRotation, toRotation, t) -> {
if (!mSplits.isSplitScreenSupported()) {
return;
}
DisplayLayout displayLayout = DisplayLayout displayLayout =
new DisplayLayout(mDisplayController.getDisplayLayout(display)); new DisplayLayout(mDisplayController.getDisplayLayout(display));
SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits); SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
@@ -472,6 +476,10 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
mDisplayController.getDisplayLayout(displayId), mSplits); mDisplayController.getDisplayLayout(displayId), mSplits);
mImeController.addPositionProcessor(mImePositionProcessor); mImeController.addPositionProcessor(mImePositionProcessor);
mDisplayController.addDisplayChangingController(mRotationController); mDisplayController.addDisplayChangingController(mRotationController);
if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
removeDivider();
return;
}
try { try {
mSplits.init(mSurfaceSession); mSplits.init(mSurfaceSession);
// Set starting tile bounds based on middle target // Set starting tile bounds based on middle target
@@ -481,13 +489,15 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
WindowOrganizer.applyTransaction(tct); WindowOrganizer.applyTransaction(tct);
} 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);
removeDivider();
return;
} }
update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration()); update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration());
} }
@Override @Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
if (displayId != DEFAULT_DISPLAY) { if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
return; return;
} }
mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId), mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),

View File

@@ -25,7 +25,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.annotation.Nullable; import android.annotation.Nullable;
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;
@@ -130,7 +129,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private int mDividerInsets; private int mDividerInsets;
private final Display mDefaultDisplay; private final Display mDefaultDisplay;
private boolean mSupportSplitScreenMultiWindow;
private int mDividerSize; private int mDividerSize;
private int mTouchElevation; private int mTouchElevation;
@@ -284,8 +282,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
final DisplayManager displayManager = final DisplayManager displayManager =
(DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY); mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
mSupportSplitScreenMultiWindow =
ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
} }
@Override @Override
@@ -358,11 +354,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
@Override @Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 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) { if (mFirstLayout) {
// Wait for first layout so that the ViewRootImpl surface has been created. // Wait for first layout so that the ViewRootImpl surface has been created.
initializeSurfaceState(); initializeSurfaceState();

View File

@@ -49,6 +49,7 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
ArrayList<SurfaceControl> mHomeAndRecentsSurfaces = new ArrayList<>(); ArrayList<SurfaceControl> mHomeAndRecentsSurfaces = new ArrayList<>();
Rect mHomeBounds = new Rect(); Rect mHomeBounds = new Rect();
final Divider mDivider; final Divider mDivider;
private boolean mSplitScreenSupported = false;
SplitScreenTaskOrganizer(Divider divider) { SplitScreenTaskOrganizer(Divider divider) {
mDivider = divider; mDivider = divider;
@@ -57,12 +58,19 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
void init(SurfaceSession session) throws RemoteException { void init(SurfaceSession session) throws RemoteException {
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
try {
mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
mSecondary = TaskOrganizer.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();
} catch (RemoteException e) {
// teardown to prevent callbacks
TaskOrganizer.unregisterOrganizer(this);
throw e;
}
mSplitScreenSupported = true;
// Initialize dim surfaces: // Initialize dim surfaces:
mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface) mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface)
@@ -78,6 +86,10 @@ class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
releaseTransaction(t); releaseTransaction(t);
} }
boolean isSplitScreenSupported() {
return mSplitScreenSupported;
}
SurfaceControl.Transaction getTransaction() { SurfaceControl.Transaction getTransaction() {
return mDivider.mTransactionPool.acquire(); return mDivider.mTransactionPool.acquire();
} }

View File

@@ -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.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 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_CONFIGS;
import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
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.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.os.Binder; import android.os.Binder;
@@ -53,7 +52,7 @@ import java.util.WeakHashMap;
*/ */
class TaskOrganizerController extends ITaskOrganizerController.Stub { class TaskOrganizerController extends ITaskOrganizerController.Stub {
private static final String TAG = "TaskOrganizerController"; 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 * 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 final WindowManagerGlobalLock mGlobalLock;
private class DeathRecipient implements IBinder.DeathRecipient { private class DeathRecipient implements IBinder.DeathRecipient {
int mWindowingMode;
ITaskOrganizer mTaskOrganizer; ITaskOrganizer mTaskOrganizer;
DeathRecipient(ITaskOrganizer organizer, int windowingMode) { DeathRecipient(ITaskOrganizer organizer) {
mTaskOrganizer = organizer; mTaskOrganizer = organizer;
mWindowingMode = windowingMode;
} }
@Override @Override
@@ -86,18 +83,16 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
private class TaskOrganizerState { private class TaskOrganizerState {
private final ITaskOrganizer mOrganizer; private final ITaskOrganizer mOrganizer;
private final DeathRecipient mDeathRecipient; private final DeathRecipient mDeathRecipient;
private final int mWindowingMode;
private final ArrayList<Task> mOrganizedTasks = new ArrayList<>(); private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
TaskOrganizerState(ITaskOrganizer organizer, int windowingMode) { TaskOrganizerState(ITaskOrganizer organizer) {
mOrganizer = organizer; mOrganizer = organizer;
mDeathRecipient = new DeathRecipient(organizer, windowingMode); mDeathRecipient = new DeathRecipient(organizer);
try { try {
organizer.asBinder().linkToDeath(mDeathRecipient, 0); organizer.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
Slog.e(TAG, "TaskOrganizer failed to register death recipient"); Slog.e(TAG, "TaskOrganizer failed to register death recipient");
} }
mWindowingMode = windowingMode;
} }
void addTask(Task t) { void addTask(Task t) {
@@ -120,7 +115,9 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
void dispose() { void dispose() {
releaseTasks(); releaseTasks();
mTaskOrganizersForWindowingMode.get(mWindowingMode).remove(this); for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.asBinder());
}
} }
private void releaseTasks() { 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<>(); new SparseArray<>();
private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>(); private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
@@ -162,10 +159,22 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
*/ */
@Override @Override
public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) { public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
if (windowingMode != WINDOWING_MODE_PINNED if (windowingMode == WINDOWING_MODE_PINNED) {
&& windowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY if (!mService.mSupportsPictureInPicture) {
&& windowingMode != WINDOWING_MODE_SPLIT_SCREEN_SECONDARY throw new UnsupportedOperationException("Picture in picture is not supported on "
&& windowingMode != WINDOWING_MODE_MULTI_WINDOW) { + "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" throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow"
+ " windowing modes are supported for registerTaskOrganizer"); + " windowing modes are supported for registerTaskOrganizer");
} }
@@ -178,19 +187,18 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
+ windowingMode); + windowingMode);
} }
LinkedList<TaskOrganizerState> states; LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode);
if (mTaskOrganizersForWindowingMode.contains(windowingMode)) { if (orgs == null) {
states = mTaskOrganizersForWindowingMode.get(windowingMode); orgs = new LinkedList<>();
} else { mTaskOrganizersForWindowingMode.put(windowingMode, orgs);
states = new LinkedList<>(); }
mTaskOrganizersForWindowingMode.put(windowingMode, states); 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 // 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 // windowing mode, we add report all existing tasks in that mode to the new
// task organizer. // task organizer.
@@ -214,8 +222,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
} }
ITaskOrganizer getTaskOrganizer(int windowingMode) { ITaskOrganizer getTaskOrganizer(int windowingMode) {
final TaskOrganizerState state = mTaskOrganizersForWindowingMode.get(windowingMode, final IBinder organizer =
EMPTY_LIST).peekLast(); mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast();
if (organizer == null) {
return null;
}
final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
if (state == null) { if (state == null) {
return null; return null;
} }