Merge "Re-parent children when Organized Window is no longer controlled" into rvc-dev am: 69722e1b03

Change-Id: I9286bceb6b7ec5422023d3c2e4911307a82c5937
This commit is contained in:
Chavi Weingarten
2020-04-29 20:51:42 +00:00
committed by Automerger Merge Worker
8 changed files with 172 additions and 54 deletions

View File

@@ -36,7 +36,6 @@ import android.provider.Settings;
import android.util.Slog; import android.util.Slog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View; import android.view.View;
import android.window.TaskOrganizer; import android.window.TaskOrganizer;
import android.window.WindowContainerToken; import android.window.WindowContainerToken;
@@ -94,7 +93,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
private boolean mHomeStackResizable = false; private boolean mHomeStackResizable = false;
private ForcedResizableInfoActivityController mForcedResizableController; private ForcedResizableInfoActivityController mForcedResizableController;
private SystemWindows mSystemWindows; private SystemWindows mSystemWindows;
final SurfaceSession mSurfaceSession = new SurfaceSession();
private DisplayController mDisplayController; private DisplayController mDisplayController;
private DisplayImeController mImeController; private DisplayImeController mImeController;
final TransactionPool mTransactionPool; final TransactionPool mTransactionPool;
@@ -493,7 +491,7 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
return; return;
} }
try { try {
mSplits.init(mSurfaceSession); mSplits.init();
// 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;
@@ -505,7 +503,6 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
return; return;
} }
ActivityManagerWrapper.getInstance().registerTaskStackListener(mActivityRestartListener); ActivityManagerWrapper.getInstance().registerTaskStackListener(mActivityRestartListener);
update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration());
} }
@Override @Override
@@ -582,6 +579,15 @@ public class Divider extends SystemUI implements DividerView.DividerCallbacks,
} }
} }
void onTaskVanished() {
mHandler.post(this::removeDivider);
}
void onTasksReady() {
mHandler.post(() -> update(mDisplayController.getDisplayContext(
mContext.getDisplayId()).getResources().getConfiguration()));
}
void updateVisibility(final boolean visible) { void updateVisibility(final boolean visible) {
if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible); if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
if (mVisible != visible) { if (mVisible != visible) {

View File

@@ -47,39 +47,27 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
final Divider mDivider; final Divider mDivider;
private boolean mSplitScreenSupported = false; private boolean mSplitScreenSupported = false;
final SurfaceSession mSurfaceSession = new SurfaceSession();
SplitScreenTaskOrganizer(Divider divider) { SplitScreenTaskOrganizer(Divider divider) {
mDivider = divider; mDivider = divider;
} }
void init(SurfaceSession session) throws RemoteException { void init() throws RemoteException {
registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
try { synchronized (this) {
mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, try {
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
mPrimarySurface = mPrimary.token.getLeash(); WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
mSecondarySurface = mSecondary.token.getLeash(); } catch (Exception e) {
} catch (Exception e) { // teardown to prevent callbacks
// teardown to prevent callbacks unregisterOrganizer();
unregisterOrganizer(); throw e;
throw e; }
} }
mSplitScreenSupported = true;
// Initialize dim surfaces:
mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface)
.setColorLayer().setName("Primary Divider Dim").build();
mSecondaryDim = new SurfaceControl.Builder(session).setParent(mSecondarySurface)
.setColorLayer().setName("Secondary Divider Dim").build();
SurfaceControl.Transaction t = getTransaction();
t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
t.apply();
releaseTransaction(t);
} }
boolean isSplitScreenSupported() { boolean isSplitScreenSupported() {
@@ -94,6 +82,67 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
mDivider.mTransactionPool.release(t); mDivider.mTransactionPool.release(t);
} }
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo) {
synchronized (this) {
if (mPrimary == null || mSecondary == null) {
Log.w(TAG, "Received onTaskAppeared before creating root tasks " + taskInfo);
return;
}
if (taskInfo.token.equals(mPrimary.token)) {
mPrimarySurface = taskInfo.token.getLeash();
} else if (taskInfo.token.equals(mSecondary.token)) {
mSecondarySurface = taskInfo.token.getLeash();
}
if (!mSplitScreenSupported && mPrimarySurface != null && mSecondarySurface != null) {
mSplitScreenSupported = true;
// Initialize dim surfaces:
mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
.setParent(mPrimarySurface).setColorLayer()
.setName("Primary Divider Dim").build();
mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
.setParent(mSecondarySurface).setColorLayer()
.setName("Secondary Divider Dim").build();
SurfaceControl.Transaction t = getTransaction();
t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
t.apply();
releaseTransaction(t);
mDivider.onTasksReady();
}
}
}
@Override
public void onTaskVanished(RunningTaskInfo taskInfo) {
synchronized (this) {
final boolean isPrimaryTask = mPrimary != null
&& taskInfo.token.equals(mPrimary.token);
final boolean isSecondaryTask = mSecondary != null
&& taskInfo.token.equals(mSecondary.token);
if (mSplitScreenSupported && (isPrimaryTask || isSecondaryTask)) {
mSplitScreenSupported = false;
SurfaceControl.Transaction t = getTransaction();
t.remove(mPrimaryDim);
t.remove(mSecondaryDim);
t.remove(mPrimarySurface);
t.remove(mSecondarySurface);
t.apply();
releaseTransaction(t);
mDivider.onTaskVanished();
}
}
}
@Override @Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) { public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
if (taskInfo.displayId != DEFAULT_DISPLAY) { if (taskInfo.displayId != DEFAULT_DISPLAY) {

View File

@@ -140,8 +140,12 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
void setOrganizer(IDisplayAreaOrganizer organizer) { void setOrganizer(IDisplayAreaOrganizer organizer) {
if (mOrganizer == organizer) return; if (mOrganizer == organizer) return;
sendDisplayAreaVanished(); IDisplayAreaOrganizer lastOrganizer = mOrganizer;
// Update the new display area organizer before calling sendDisplayAreaVanished since it
// could result in a new SurfaceControl getting created that would notify the old organizer
// about it.
mOrganizer = organizer; mOrganizer = organizer;
sendDisplayAreaVanished(lastOrganizer);
sendDisplayAreaAppeared(); sendDisplayAreaAppeared();
} }
@@ -150,9 +154,10 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
mOrganizerController.onDisplayAreaAppeared(mOrganizer, this); mOrganizerController.onDisplayAreaAppeared(mOrganizer, this);
} }
void sendDisplayAreaVanished() { void sendDisplayAreaVanished(IDisplayAreaOrganizer organizer) {
if (mOrganizer == null) return; if (organizer == null) return;
mOrganizerController.onDisplayAreaVanished(mOrganizer, this); migrateToNewSurfaceControl();
mOrganizerController.onDisplayAreaVanished(organizer, this);
} }
@Override @Override

View File

@@ -2006,6 +2006,14 @@ class Task extends WindowContainer<WindowContainer> {
return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM); return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
} }
@Override
void migrateToNewSurfaceControl() {
super.migrateToNewSurfaceControl();
mLastSurfaceSize.x = 0;
mLastSurfaceSize.y = 0;
updateSurfaceSize(getPendingTransaction());
}
void updateSurfaceSize(SurfaceControl.Transaction transaction) { void updateSurfaceSize(SurfaceControl.Transaction transaction) {
if (mSurfaceControl == null || mCreatedByOrganizer) { if (mSurfaceControl == null || mCreatedByOrganizer) {
return; return;
@@ -4402,16 +4410,25 @@ class Task extends WindowContainer<WindowContainer> {
return mHasBeenVisible; return mHasBeenVisible;
} }
/** In the case that these three conditions are true, we want to send the Task to /** In the case that these conditions are true, we want to send the Task to the organizer:
* the organizer: * 1. An organizer has been set
* 1. We have a SurfaceControl * 2. The Task was created by the organizer
* 2. An organizer has been set * or
* 3. We have finished drawing * 2a. We have a SurfaceControl
* 2b. We have finished drawing
* Any time any of these conditions are updated, the updating code should call * Any time any of these conditions are updated, the updating code should call
* sendTaskAppeared. * sendTaskAppeared.
*/ */
boolean taskAppearedReady() { boolean taskAppearedReady() {
return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible(); if (mTaskOrganizer == null) {
return false;
}
if (mCreatedByOrganizer) {
return true;
}
return mSurfaceControl != null && getHasBeenVisible();
} }
private void sendTaskAppeared() { private void sendTaskAppeared() {
@@ -4420,9 +4437,9 @@ class Task extends WindowContainer<WindowContainer> {
} }
} }
private void sendTaskVanished() { private void sendTaskVanished(ITaskOrganizer organizer) {
if (mTaskOrganizer != null) { if (organizer != null) {
mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this); mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this);
} }
} }
@@ -4431,9 +4448,13 @@ class Task extends WindowContainer<WindowContainer> {
if (mTaskOrganizer == organizer) { if (mTaskOrganizer == organizer) {
return false; return false;
} }
// Let the old organizer know it has lost control.
sendTaskVanished(); ITaskOrganizer previousOrganizer = mTaskOrganizer;
// Update the new task organizer before calling sendTaskVanished since it could result in
// a new SurfaceControl getting created that would notify the old organizer about it.
mTaskOrganizer = organizer; mTaskOrganizer = organizer;
// Let the old organizer know it has lost control.
sendTaskVanished(previousOrganizer);
if (mTaskOrganizer != null) { if (mTaskOrganizer != null) {
sendTaskAppeared(); sendTaskAppeared();

View File

@@ -211,6 +211,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
void removeTask(Task t) { void removeTask(Task t) {
if (t.mTaskAppearedSent) { if (t.mTaskAppearedSent) {
t.migrateToNewSurfaceControl();
t.mTaskAppearedSent = false; t.mTaskAppearedSent = false;
mOrganizer.onTaskVanished(t); mOrganizer.onTaskVanished(t);
} }

View File

@@ -405,6 +405,40 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
updateSurfacePosition(); updateSurfacePosition();
} }
/**
* Create a new SurfaceControl for this WindowContainer and migrate all properties to the new
* SurfaceControl. Properties include:
* 1. Children
* 2. Position
* 3. Z order
*
* Remove the old SurfaceControl since it's no longer needed.
*
* This is used to revoke control of the SurfaceControl from a client process that was
* previously organizing this WindowContainer.
*/
void migrateToNewSurfaceControl() {
SurfaceControl.Transaction t = getPendingTransaction();
t.remove(mSurfaceControl);
// Clear the last position so the new SurfaceControl will get correct position
mLastSurfacePosition.set(0, 0);
createSurfaceControl(false /* force */);
if (mLastRelativeToLayer != null) {
t.setRelativeLayer(mSurfaceControl, mLastRelativeToLayer, mLastLayer);
} else {
t.setLayer(mSurfaceControl, mLastLayer);
}
for (int i = 0; i < mChildren.size(); i++) {
SurfaceControl sc = mChildren.get(i).getSurfaceControl();
if (sc != null) {
t.reparent(sc, mSurfaceControl);
}
}
scheduleAnimation();
}
/** /**
* Called when the surface is shown for the first time. * Called when the surface is shown for the first time.
*/ */

View File

@@ -18,29 +18,24 @@ package com.android.test.taskembed;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import android.app.ActivityManager;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions; import android.app.ActivityOptions;
import android.content.Context; import android.content.Context;
import android.content.Intent; 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;
import android.view.SurfaceHolder; 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.widget.LinearLayout;
import android.window.IWindowContainerTransactionCallback;
import android.window.TaskOrganizer; import android.window.TaskOrganizer;
import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction;
import android.widget.LinearLayout;
import android.window.WindowContainerTransactionCallback; import android.window.WindowContainerTransactionCallback;
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 {
@@ -173,6 +168,12 @@ public class TaskOrganizerMultiWindowTest extends Activity {
setContentView(splitView); setContentView(splitView);
} }
@Override
protected void onDestroy() {
super.onDestroy();
mOrganizer.unregisterOrganizer();
}
private void addFlags(Intent intent) { private void addFlags(Intent intent) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_ANIMATION);
} }

View File

@@ -24,10 +24,10 @@ import android.content.Intent;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.IBinder; import android.os.IBinder;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.window.TaskOrganizer;
import android.window.WindowContainerTransaction;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.window.TaskOrganizer;
import android.window.WindowContainerTransaction;
public class TaskOrganizerPipTest extends Service { public class TaskOrganizerPipTest extends Service {
static final int PIP_WIDTH = 640; static final int PIP_WIDTH = 640;
@@ -76,5 +76,6 @@ public class TaskOrganizerPipTest extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mOrganizer.unregisterOrganizer();
} }
} }