Merge "Support to launch multi-instance when long press to split on an app icon" into tm-qpr-dev
This commit is contained in:
@@ -45,12 +45,10 @@ import android.app.WindowConfiguration;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
@@ -64,19 +62,15 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
import com.android.wm.shell.common.split.SplitLayout;
|
||||
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
|
||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||
import com.android.wm.shell.splitscreen.SplitScreenController;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The policy for handling drag and drop operations to shell.
|
||||
@@ -269,46 +263,10 @@ public class DragAndDropPolicy {
|
||||
mStarter.startShortcut(packageName, id, position, opts, user);
|
||||
} else {
|
||||
final PendingIntent launchIntent = intent.getParcelableExtra(EXTRA_PENDING_INTENT);
|
||||
mStarter.startIntent(launchIntent, getStartIntentFillInIntent(launchIntent, position),
|
||||
position, opts);
|
||||
mStarter.startIntent(launchIntent, null /* fillIntent */, position, opts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fill-in intent to use when starting an app from a drop.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
Intent getStartIntentFillInIntent(PendingIntent launchIntent, @SplitPosition int position) {
|
||||
// Get the drag app
|
||||
final List<ResolveInfo> infos = launchIntent.queryIntentComponents(0 /* flags */);
|
||||
final ComponentName dragIntentActivity = !infos.isEmpty()
|
||||
? infos.get(0).activityInfo.getComponentName()
|
||||
: null;
|
||||
|
||||
// Get the current app (either fullscreen or the remaining app post-drop if in splitscreen)
|
||||
final boolean inSplitScreen = mSplitScreen != null
|
||||
&& mSplitScreen.isSplitScreenVisible();
|
||||
final ComponentName currentActivity;
|
||||
if (!inSplitScreen) {
|
||||
currentActivity = mSession.runningTaskInfo != null
|
||||
? mSession.runningTaskInfo.baseIntent.getComponent()
|
||||
: null;
|
||||
} else {
|
||||
final ActivityManager.RunningTaskInfo nonReplacedTaskInfo =
|
||||
mSplitScreen.getTaskInfo(SplitLayout.reversePosition(position));
|
||||
currentActivity = nonReplacedTaskInfo.baseIntent.getComponent();
|
||||
}
|
||||
|
||||
if (Objects.equals(currentActivity, dragIntentActivity)) {
|
||||
// Only apply MULTIPLE_TASK if we are dragging the same activity
|
||||
final Intent fillInIntent = new Intent();
|
||||
fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Adding MULTIPLE_TASK");
|
||||
return fillInIntent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-drag session data.
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,9 @@ package com.android.wm.shell.splitscreen;
|
||||
|
||||
import static android.app.ActivityManager.START_SUCCESS;
|
||||
import static android.app.ActivityManager.START_TASK_TO_FRONT;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.RemoteAnimationTarget.MODE_OPENING;
|
||||
@@ -58,7 +61,9 @@ import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
@@ -74,6 +79,7 @@ import com.android.wm.shell.common.annotations.ExternalThread;
|
||||
import com.android.wm.shell.common.split.SplitLayout;
|
||||
import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
|
||||
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
|
||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||
import com.android.wm.shell.recents.RecentTasksController;
|
||||
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
|
||||
import com.android.wm.shell.transition.LegacyTransitions;
|
||||
@@ -95,7 +101,7 @@ import java.util.concurrent.Executor;
|
||||
*/
|
||||
// TODO(b/198577848): Implement split screen flicker test to consolidate CUJ of split screen.
|
||||
public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
RemoteCallable<SplitScreenController> {
|
||||
RemoteCallable<SplitScreenController>, ShellTaskOrganizer.FocusListener {
|
||||
private static final String TAG = SplitScreenController.class.getSimpleName();
|
||||
|
||||
static final int EXIT_REASON_UNKNOWN = 0;
|
||||
@@ -143,6 +149,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
// outside the bounds of the roots by being reparented into a higher level fullscreen container
|
||||
private SurfaceControl mSplitTasksContainerLayer;
|
||||
|
||||
private ActivityManager.RunningTaskInfo mFocusingTaskInfo;
|
||||
|
||||
public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
|
||||
SyncTransactionQueue syncQueue, Context context,
|
||||
RootTaskDisplayAreaOrganizer rootTDAOrganizer,
|
||||
@@ -164,6 +172,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
mLogger = new SplitscreenEventLogger();
|
||||
mIconProvider = iconProvider;
|
||||
mRecentTasksOptional = recentTasks;
|
||||
mTaskOrganizer.addFocusListener(this);
|
||||
}
|
||||
|
||||
public SplitScreen asSplitScreen() {
|
||||
@@ -180,6 +189,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
return mMainExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
mFocusingTaskInfo = taskInfo;
|
||||
}
|
||||
|
||||
public void onOrganizerRegistered() {
|
||||
if (mStageCoordinator == null) {
|
||||
// TODO: Multi-display
|
||||
@@ -341,14 +355,21 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options,
|
||||
null /* wct */);
|
||||
|
||||
// Flag this as a no-user-action launch to prevent sending user leaving event to the
|
||||
// current top activity since it's going to be put into another side of the split. This
|
||||
// prevents the current top activity from going into pip mode due to user leaving event.
|
||||
if (fillInIntent == null) {
|
||||
fillInIntent = new Intent();
|
||||
}
|
||||
// Flag this as a no-user-action launch to prevent sending user leaving event to the
|
||||
// current top activity since it's going to be put into another side of the split. This
|
||||
// prevents the current top activity from going into pip mode due to user leaving event.
|
||||
fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
|
||||
|
||||
// Flag with MULTIPLE_TASK if this is launching the same activity into both sides of the
|
||||
// split.
|
||||
if (isLaunchingAdjacently(intent.getIntent(), position)) {
|
||||
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
|
||||
}
|
||||
|
||||
intent.send(mContext, 0, fillInIntent, null /* onFinished */, null /* handler */,
|
||||
null /* requiredPermission */, options);
|
||||
} catch (PendingIntent.CanceledException e) {
|
||||
@@ -358,6 +379,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
|
||||
private void startIntentLegacy(PendingIntent intent, @Nullable Intent fillInIntent,
|
||||
@SplitPosition int position, @Nullable Bundle options) {
|
||||
boolean startSameActivityAdjacently = isLaunchingAdjacently(intent.getIntent(), position);
|
||||
|
||||
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
|
||||
mStageCoordinator.prepareEvictChildTasks(position, evictWct);
|
||||
|
||||
@@ -368,14 +391,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
IRemoteAnimationFinishedCallback finishedCallback,
|
||||
SurfaceControl.Transaction t) {
|
||||
if (apps == null || apps.length == 0) {
|
||||
final ActivityManager.RunningTaskInfo pairedTaskInfo =
|
||||
getTaskInfo(SplitLayout.reversePosition(position));
|
||||
final ComponentName pairedActivity = pairedTaskInfo != null
|
||||
? pairedTaskInfo.baseIntent.getComponent() : null;
|
||||
final ComponentName intentActivity = intent.getIntent() != null
|
||||
? intent.getIntent().getComponent() : null;
|
||||
|
||||
if (Objects.equals(pairedActivity, intentActivity)) {
|
||||
if (startSameActivityAdjacently) {
|
||||
// Switch split position if dragging the same activity to another side.
|
||||
setSideStagePosition(SplitLayout.reversePosition(
|
||||
mStageCoordinator.getSideStagePosition()));
|
||||
@@ -417,11 +433,47 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
fillInIntent = new Intent();
|
||||
}
|
||||
fillInIntent.addFlags(FLAG_ACTIVITY_NO_USER_ACTION);
|
||||
if (startSameActivityAdjacently) {
|
||||
fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, "Adding MULTIPLE_TASK");
|
||||
}
|
||||
|
||||
wct.sendPendingIntent(intent, fillInIntent, options);
|
||||
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
|
||||
}
|
||||
|
||||
/** Returns {@code true} if it's launching the same component on both sides of the split. */
|
||||
@VisibleForTesting
|
||||
boolean isLaunchingAdjacently(@Nullable Intent startIntent,
|
||||
@SplitPosition int position) {
|
||||
if (startIntent == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ComponentName launchingActivity = startIntent.getComponent();
|
||||
if (launchingActivity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isSplitScreenVisible()) {
|
||||
final ActivityManager.RunningTaskInfo pairedTaskInfo =
|
||||
getTaskInfo(SplitLayout.reversePosition(position));
|
||||
final ComponentName pairedActivity = pairedTaskInfo != null
|
||||
? pairedTaskInfo.baseIntent.getComponent() : null;
|
||||
return Objects.equals(launchingActivity, pairedActivity);
|
||||
}
|
||||
|
||||
if (mFocusingTaskInfo != null
|
||||
// TODO (b/238032411): have an API to determine whether an activity is valid for
|
||||
// split screen or not.
|
||||
&& mFocusingTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
||||
&& mFocusingTaskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
|
||||
return Objects.equals(mFocusingTaskInfo.baseIntent.getComponent(), launchingActivity);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) {
|
||||
if (isSplitScreenVisible()) {
|
||||
// Evict child tasks except the top visible one under split root to ensure it could be
|
||||
|
||||
@@ -200,11 +200,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
@Override
|
||||
@CallSuper
|
||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
if (!taskInfo.supportsMultiWindow) {
|
||||
// Leave split screen if the task no longer supports multi window.
|
||||
mCallbacks.onNoLongerSupportMultiWindow();
|
||||
return;
|
||||
}
|
||||
if (mRootTaskInfo.taskId == taskInfo.taskId) {
|
||||
// Inflates split decor view only when the root task is visible.
|
||||
if (mRootTaskInfo.isVisible != taskInfo.isVisible) {
|
||||
@@ -217,6 +212,12 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
}
|
||||
mRootTaskInfo = taskInfo;
|
||||
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
|
||||
if (!taskInfo.supportsMultiWindow) {
|
||||
// Leave split screen if the task no longer supports multi window.
|
||||
mCallbacks.onNoLongerSupportMultiWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
|
||||
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
|
||||
taskInfo.isVisible);
|
||||
|
||||
@@ -34,7 +34,6 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL
|
||||
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT;
|
||||
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP;
|
||||
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
@@ -57,7 +56,6 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Insets;
|
||||
@@ -265,62 +263,6 @@ public class DragAndDropPolicyTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchMultipleTask_differentActivity() {
|
||||
setRunningTask(mFullscreenAppTask);
|
||||
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
|
||||
Intent fillInIntent = mPolicy.getStartIntentFillInIntent(mock(PendingIntent.class), 0);
|
||||
assertNull(fillInIntent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchMultipleTask_differentActivity_inSplitscreen() {
|
||||
setRunningTask(mFullscreenAppTask);
|
||||
doReturn(true).when(mSplitScreenStarter).isSplitScreenVisible();
|
||||
doReturn(mFullscreenAppTask).when(mSplitScreenStarter).getTaskInfo(anyInt());
|
||||
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
|
||||
Intent fillInIntent = mPolicy.getStartIntentFillInIntent(mock(PendingIntent.class), 0);
|
||||
assertNull(fillInIntent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchMultipleTask_sameActivity() {
|
||||
setRunningTask(mFullscreenAppTask);
|
||||
|
||||
// Replace the mocked drag pending intent and ensure it resolves to the same activity
|
||||
PendingIntent launchIntent = mock(PendingIntent.class);
|
||||
ResolveInfo launchInfo = new ResolveInfo();
|
||||
launchInfo.activityInfo = mFullscreenAppTask.topActivityInfo;
|
||||
doReturn(Collections.singletonList(launchInfo))
|
||||
.when(launchIntent).queryIntentComponents(anyInt());
|
||||
mActivityClipData.getItemAt(0).getIntent().putExtra(ClipDescription.EXTRA_PENDING_INTENT,
|
||||
launchIntent);
|
||||
|
||||
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
|
||||
Intent fillInIntent = mPolicy.getStartIntentFillInIntent(launchIntent, 0);
|
||||
assertTrue((fillInIntent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLaunchMultipleTask_sameActivity_inSplitScreen() {
|
||||
setRunningTask(mFullscreenAppTask);
|
||||
|
||||
// Replace the mocked drag pending intent and ensure it resolves to the same activity
|
||||
PendingIntent launchIntent = mock(PendingIntent.class);
|
||||
ResolveInfo launchInfo = new ResolveInfo();
|
||||
launchInfo.activityInfo = mFullscreenAppTask.topActivityInfo;
|
||||
doReturn(Collections.singletonList(launchInfo))
|
||||
.when(launchIntent).queryIntentComponents(anyInt());
|
||||
mActivityClipData.getItemAt(0).getIntent().putExtra(ClipDescription.EXTRA_PENDING_INTENT,
|
||||
launchIntent);
|
||||
|
||||
doReturn(true).when(mSplitScreenStarter).isSplitScreenVisible();
|
||||
doReturn(mFullscreenAppTask).when(mSplitScreenStarter).getTaskInfo(anyInt());
|
||||
mPolicy.start(mLandscapeDisplayLayout, mActivityClipData, mLoggerSessionId);
|
||||
Intent fillInIntent = mPolicy.getStartIntentFillInIntent(launchIntent, 0);
|
||||
assertTrue((fillInIntent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0);
|
||||
}
|
||||
|
||||
private Target filterTargetByType(ArrayList<Target> targets, int type) {
|
||||
for (Target t : targets) {
|
||||
if (type == t.type) {
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.wm.shell.splitscreen;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
|
||||
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.ShellTestCase;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
import com.android.wm.shell.common.DisplayInsetsController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
import com.android.wm.shell.recents.RecentTasksController;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Tests for {@link SplitScreenController}
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SplitScreenControllerTests extends ShellTestCase {
|
||||
|
||||
@Mock ShellTaskOrganizer mTaskOrganizer;
|
||||
@Mock SyncTransactionQueue mSyncQueue;
|
||||
@Mock RootTaskDisplayAreaOrganizer mRootTDAOrganizer;
|
||||
@Mock ShellExecutor mMainExecutor;
|
||||
@Mock DisplayController mDisplayController;
|
||||
@Mock DisplayImeController mDisplayImeController;
|
||||
@Mock DisplayInsetsController mDisplayInsetsController;
|
||||
@Mock Transitions mTransitions;
|
||||
@Mock TransactionPool mTransactionPool;
|
||||
@Mock IconProvider mIconProvider;
|
||||
@Mock Optional<RecentTasksController> mRecentTasks;
|
||||
|
||||
private SplitScreenController mSplitScreenController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mSplitScreenController = spy(new SplitScreenController(mTaskOrganizer, mSyncQueue, mContext,
|
||||
mRootTDAOrganizer, mMainExecutor, mDisplayController, mDisplayImeController,
|
||||
mDisplayInsetsController, mTransitions, mTransactionPool, mIconProvider,
|
||||
mRecentTasks));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsLaunchingAdjacently_notInSplitScreen() {
|
||||
doReturn(false).when(mSplitScreenController).isSplitScreenVisible();
|
||||
|
||||
// Verify launching the same activity returns true.
|
||||
Intent startIntent = createStartIntent("startActivity");
|
||||
ActivityManager.RunningTaskInfo focusTaskInfo =
|
||||
createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
|
||||
mSplitScreenController.onFocusTaskChanged(focusTaskInfo);
|
||||
assertTrue(mSplitScreenController.isLaunchingAdjacently(
|
||||
startIntent, SPLIT_POSITION_TOP_OR_LEFT));
|
||||
|
||||
// Verify launching different activity returns false.
|
||||
Intent diffIntent = createStartIntent("diffActivity");
|
||||
focusTaskInfo =
|
||||
createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, diffIntent);
|
||||
mSplitScreenController.onFocusTaskChanged(focusTaskInfo);
|
||||
assertFalse(mSplitScreenController.isLaunchingAdjacently(
|
||||
startIntent, SPLIT_POSITION_TOP_OR_LEFT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsLaunchingAdjacently_inSplitScreen() {
|
||||
doReturn(true).when(mSplitScreenController).isSplitScreenVisible();
|
||||
|
||||
// Verify launching the same activity returns true.
|
||||
Intent startIntent = createStartIntent("startActivity");
|
||||
ActivityManager.RunningTaskInfo pairingTaskInfo =
|
||||
createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, startIntent);
|
||||
doReturn(pairingTaskInfo).when(mSplitScreenController).getTaskInfo(anyInt());
|
||||
assertTrue(mSplitScreenController.isLaunchingAdjacently(
|
||||
startIntent, SPLIT_POSITION_TOP_OR_LEFT));
|
||||
|
||||
// Verify launching different activity returns false.
|
||||
Intent diffIntent = createStartIntent("diffActivity");
|
||||
pairingTaskInfo =
|
||||
createTaskInfo(WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD, diffIntent);
|
||||
doReturn(pairingTaskInfo).when(mSplitScreenController).getTaskInfo(anyInt());
|
||||
assertFalse(mSplitScreenController.isLaunchingAdjacently(
|
||||
startIntent, SPLIT_POSITION_TOP_OR_LEFT));
|
||||
}
|
||||
|
||||
private Intent createStartIntent(String activityName) {
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName(mContext, activityName));
|
||||
return intent;
|
||||
}
|
||||
|
||||
private ActivityManager.RunningTaskInfo createTaskInfo(int winMode, int actType,
|
||||
Intent strIntent) {
|
||||
ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||
info.configuration.windowConfiguration.setActivityType(actType);
|
||||
info.configuration.windowConfiguration.setWindowingMode(winMode);
|
||||
info.supportsMultiWindow = true;
|
||||
info.baseIntent = strIntent;
|
||||
info.baseActivity = strIntent.getComponent();
|
||||
ActivityInfo activityInfo = new ActivityInfo();
|
||||
activityInfo.packageName = info.baseActivity.getPackageName();
|
||||
activityInfo.name = info.baseActivity.getClassName();
|
||||
info.topActivityInfo = activityInfo;
|
||||
return info;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user