Merge "Fix crash on devices that don't support multiwindow" into rvc-dev
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user