Update smallestScreenWidthDp when split bounds resized
Update smallestScreenWidthDp of the splitting tasks, so client apps can determine which resources they should apply. Fix: 217600744 Fix: 220069817 Test: atest WMShellUnitTests Test: manual check smallestScreenWidthDp of splitting apps in winscope Change-Id: Ie36065a951dfab2d4bb8d7a56dbc12ae03ff4033
This commit is contained in:
@@ -478,16 +478,24 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
|
||||
|
||||
if (!mBounds1.equals(mWinBounds1) || !task1.token.equals(mWinToken1)) {
|
||||
wct.setBounds(task1.token, mBounds1);
|
||||
wct.setSmallestScreenWidthDp(task1.token, getSmallestWidthDp(mBounds1));
|
||||
mWinBounds1.set(mBounds1);
|
||||
mWinToken1 = task1.token;
|
||||
}
|
||||
if (!mBounds2.equals(mWinBounds2) || !task2.token.equals(mWinToken2)) {
|
||||
wct.setBounds(task2.token, mBounds2);
|
||||
wct.setSmallestScreenWidthDp(task2.token, getSmallestWidthDp(mBounds2));
|
||||
mWinBounds2.set(mBounds2);
|
||||
mWinToken2 = task2.token;
|
||||
}
|
||||
}
|
||||
|
||||
private int getSmallestWidthDp(Rect bounds) {
|
||||
final int minWidth = Math.min(bounds.width(), bounds.height());
|
||||
final float density = mContext.getResources().getDisplayMetrics().density;
|
||||
return (int) (minWidth / density);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift configuration bounds to prevent client apps get configuration changed or relaunch. And
|
||||
* restore shifted configuration bounds if it's no longer shifted.
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.wm.shell.splitscreen;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.SurfaceSession;
|
||||
import android.window.WindowContainerToken;
|
||||
import android.window.WindowContainerTransaction;
|
||||
@@ -49,14 +48,13 @@ class MainStage extends StageTaskListener {
|
||||
return mIsActive;
|
||||
}
|
||||
|
||||
void activate(Rect rootBounds, WindowContainerTransaction wct, boolean includingTopTask) {
|
||||
void activate(WindowContainerTransaction wct, boolean includingTopTask) {
|
||||
if (mIsActive) return;
|
||||
|
||||
final WindowContainerToken rootToken = mRootTaskInfo.token;
|
||||
wct.setBounds(rootToken, rootBounds)
|
||||
// Moving the root task to top after the child tasks were re-parented , or the root
|
||||
// task cannot be visible and focused.
|
||||
.reorder(rootToken, true /* onTop */);
|
||||
// Moving the root task to top after the child tasks were re-parented , or the root
|
||||
// task cannot be visible and focused.
|
||||
wct.reorder(rootToken, true /* onTop */);
|
||||
if (includingTopTask) {
|
||||
wct.reparentTasks(
|
||||
null /* currentParent */,
|
||||
|
||||
@@ -354,8 +354,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
mSplitLayout.setDivideRatio(splitRatio);
|
||||
// Build a request WCT that will launch both apps such that task 0 is on the main stage
|
||||
// while task 1 is on the side stage.
|
||||
mMainStage.activate(getMainStageBounds(), wct, false /* reparent */);
|
||||
mSideStage.setBounds(getSideStageBounds(), wct);
|
||||
mMainStage.activate(wct, false /* reparent */);
|
||||
updateWindowBounds(mSplitLayout, wct);
|
||||
|
||||
// Make sure the launch options will put tasks in the corresponding split roots
|
||||
addActivityOptions(mainOptions, mMainStage);
|
||||
@@ -470,13 +470,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
|
||||
mSplitLayout.setDivideRatio(splitRatio);
|
||||
if (mMainStage.isActive()) {
|
||||
mMainStage.moveToTop(getMainStageBounds(), wct);
|
||||
mMainStage.moveToTop(wct);
|
||||
} else {
|
||||
// Build a request WCT that will launch both apps such that task 0 is on the main stage
|
||||
// while task 1 is on the side stage.
|
||||
mMainStage.activate(getMainStageBounds(), wct, false /* reparent */);
|
||||
mMainStage.activate(wct, false /* reparent */);
|
||||
}
|
||||
mSideStage.moveToTop(getSideStageBounds(), wct);
|
||||
mSideStage.moveToTop(wct);
|
||||
updateWindowBounds(mSplitLayout, wct);
|
||||
|
||||
// Make sure the launch options will put tasks in the corresponding split roots
|
||||
addActivityOptions(mainOptions, mMainStage);
|
||||
@@ -774,8 +775,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
setSideStagePosition(startPosition, wct);
|
||||
mSideStage.addTask(taskInfo, wct);
|
||||
}
|
||||
mMainStage.activate(getMainStageBounds(), wct, true /* includingTopTask */);
|
||||
mSideStage.moveToTop(getSideStageBounds(), wct);
|
||||
mMainStage.activate(wct, true /* includingTopTask */);
|
||||
mSideStage.moveToTop(wct);
|
||||
updateWindowBounds(mSplitLayout, wct);
|
||||
}
|
||||
|
||||
void finishEnterSplitScreen(SurfaceControl.Transaction t) {
|
||||
@@ -996,10 +998,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
// Exit to side stage if main stage no longer has children.
|
||||
exitSplitScreen(mSideStage, EXIT_REASON_APP_FINISHED);
|
||||
}
|
||||
} else if (isSideStage) {
|
||||
} else if (isSideStage && !mMainStage.isActive()) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mSplitLayout.init();
|
||||
// Make sure the main stage is active.
|
||||
prepareEnterSplitScreen(wct);
|
||||
mSyncQueue.queue(wct);
|
||||
mSyncQueue.runInSync(t -> {
|
||||
|
||||
@@ -53,8 +53,8 @@ import java.io.PrintWriter;
|
||||
* Base class that handle common task org. related for split-screen stages.
|
||||
* Note that this class and its sub-class do not directly perform hierarchy operations.
|
||||
* They only serve to hold a collection of tasks and provide APIs like
|
||||
* {@link #setBounds(Rect, WindowContainerTransaction)} for the centralized {@link StageCoordinator}
|
||||
* to perform operations in-sync with other containers.
|
||||
* {@link #addTask(ActivityManager.RunningTaskInfo, WindowContainerTransaction)} for the centralized
|
||||
* {@link StageCoordinator} to perform hierarchy operations in-sync with other containers.
|
||||
*
|
||||
* @see StageCoordinator
|
||||
*/
|
||||
@@ -310,13 +310,9 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/);
|
||||
}
|
||||
|
||||
void moveToTop(Rect rootBounds, WindowContainerTransaction wct) {
|
||||
void moveToTop(WindowContainerTransaction wct) {
|
||||
final WindowContainerToken rootToken = mRootTaskInfo.token;
|
||||
wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */);
|
||||
}
|
||||
|
||||
void setBounds(Rect bounds, WindowContainerTransaction wct) {
|
||||
wct.setBounds(mRootTaskInfo.token, bounds);
|
||||
wct.reorder(rootToken, true /* onTop */);
|
||||
}
|
||||
|
||||
void reorderChild(int taskId, boolean onTop, WindowContainerTransaction wct) {
|
||||
|
||||
@@ -28,8 +28,10 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
@@ -38,6 +40,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.internal.policy.DividerSnapAlgorithm;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.ShellTestCase;
|
||||
import com.android.wm.shell.TestRunningTaskInfoBuilder;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -56,6 +59,7 @@ public class SplitLayoutTests extends ShellTestCase {
|
||||
@Mock SplitWindowManager.ParentContainerCallbacks mCallbacks;
|
||||
@Mock DisplayImeController mDisplayImeController;
|
||||
@Mock ShellTaskOrganizer mTaskOrganizer;
|
||||
@Mock WindowContainerTransaction mWct;
|
||||
@Captor ArgumentCaptor<Runnable> mRunnableCaptor;
|
||||
private SplitLayout mSplitLayout;
|
||||
|
||||
@@ -149,6 +153,16 @@ public class SplitLayoutTests extends ShellTestCase {
|
||||
verify(mSplitLayoutHandler).onSnappedToDismiss(eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testApplyTaskChanges_updatesSmallestScreenWidthDp() {
|
||||
final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
|
||||
final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
|
||||
mSplitLayout.applyTaskChanges(mWct, task1, task2);
|
||||
|
||||
verify(mWct).setSmallestScreenWidthDp(eq(task1.token), anyInt());
|
||||
verify(mWct).setSmallestScreenWidthDp(eq(task2.token), anyInt());
|
||||
}
|
||||
|
||||
private void waitDividerFlingFinished() {
|
||||
verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), mRunnableCaptor.capture());
|
||||
mRunnableCaptor.getValue().run();
|
||||
|
||||
@@ -67,8 +67,7 @@ public class MainStageTests extends ShellTestCase {
|
||||
|
||||
@Test
|
||||
public void testActiveDeactivate() {
|
||||
mMainStage.activate(mRootTaskInfo.configuration.windowConfiguration.getBounds(), mWct,
|
||||
true /* reparent */);
|
||||
mMainStage.activate(mWct, true /* reparent */);
|
||||
assertThat(mMainStage.isActive()).isTrue();
|
||||
|
||||
mMainStage.deactivate(mWct);
|
||||
|
||||
@@ -44,7 +44,6 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManager;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.view.SurfaceControl;
|
||||
@@ -421,8 +420,7 @@ public class SplitTransitionTests extends ShellTestCase {
|
||||
mock(SurfaceControl.Transaction.class),
|
||||
mock(SurfaceControl.Transaction.class),
|
||||
mock(Transitions.TransitionFinishCallback.class));
|
||||
mMainStage.activate(new Rect(0, 0, 100, 100), new WindowContainerTransaction(),
|
||||
true /* includingTopTask */);
|
||||
mMainStage.activate(new WindowContainerTransaction(), true /* includingTopTask */);
|
||||
}
|
||||
|
||||
private boolean containsSplitEnter(@NonNull WindowContainerTransaction wct) {
|
||||
|
||||
Reference in New Issue
Block a user