Loading services/core/java/com/android/server/wm/ActivityStarter.java +15 −3 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ import com.android.server.wm.BackgroundActivityStartController.BalCode; import com.android.server.wm.BackgroundActivityStartController.BalVerdict; import com.android.server.wm.LaunchParamsController.LaunchParams; import com.android.server.wm.TaskFragment.EmbeddingCheckResult; import com.android.wm.shell.Flags; import java.io.PrintWriter; import java.lang.annotation.Retention; Loading Loading @@ -1723,7 +1724,14 @@ class ActivityStarter { // Get top task at beginning because the order may be changed when reusing existing task. final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask(); final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null; final Task reusedTask = resolveReusableTask(); final boolean sourceActivityLaunchedFromBubble = sourceRecord != null && sourceRecord.getLaunchedFromBubble(); // if the flag is enabled, allow reusing bubbled tasks only if the source activity is // bubbled. final boolean includeLaunchedFromBubble = Flags.onlyReuseBubbledTaskWhenLaunchedFromBubble() ? sourceActivityLaunchedFromBubble : true; final Task reusedTask = resolveReusableTask(includeLaunchedFromBubble); // If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() Loading Loading @@ -2722,8 +2730,11 @@ class ActivityStarter { /** * Decide whether the new activity should be inserted into an existing task. Returns null * if not or an ActivityRecord with the task into which the new activity should be added. * * @param includeLaunchedFromBubble whether a task whose top activity was launched from a bubble * should be allowed to be reused for the new activity. */ private Task resolveReusableTask() { private Task resolveReusableTask(boolean includeLaunchedFromBubble) { // If a target task is specified, try to reuse that one if (mOptions != null && mOptions.getLaunchTaskId() != INVALID_TASK_ID) { Task launchTask = mRootWindowContainer.anyTaskForId(mOptions.getLaunchTaskId()); Loading Loading @@ -2767,7 +2778,8 @@ class ActivityStarter { } else { // Otherwise find the best task to put the activity in. intentActivity = mRootWindowContainer.findTask(mStartActivity, mPreferredTaskDisplayArea); mRootWindowContainer.findTask(mStartActivity, mPreferredTaskDisplayArea, includeLaunchedFromBubble); } } Loading services/core/java/com/android/server/wm/RootWindowContainer.java +17 −8 Original line number Diff line number Diff line Loading @@ -314,13 +314,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private boolean isDocument; private Uri documentData; void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info) { // determines whether to include bubbled tasks. defaults to true to preserve previous // behavior. private boolean mIncludeLaunchedFromBubble = true; void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info, boolean includeLaunchedFromBubble) { mActivityType = activityType; mTaskAffinity = taskAffinity; mIntent = intent; mInfo = info; mIdealRecord = null; mCandidateRecord = null; mIncludeLaunchedFromBubble = includeLaunchedFromBubble; } /** Loading Loading @@ -362,7 +368,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } // Overlays should not be considered as the task's logical top activity. final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */); final ActivityRecord r = task.getTopNonFinishingActivity( false /* includeOverlays */, mIncludeLaunchedFromBubble); if (r == null || r.finishing || r.mUserId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { Loading Loading @@ -2372,18 +2379,20 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } @Nullable ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea) { ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble) { return findTask(r.getActivityType(), r.taskAffinity, r.intent, r.info, preferredTaskDisplayArea); preferredTaskDisplayArea, includeLaunchedFromBubble); } @Nullable ActivityRecord findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info, TaskDisplayArea preferredTaskDisplayArea) { TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble) { ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of type=%s, taskAffinity=%s, intent=%s" + ", info=%s, preferredTDA=%s", activityType, taskAffinity, intent, info, preferredTaskDisplayArea); mTmpFindTaskResult.init(activityType, taskAffinity, intent, info); + ", info=%s, preferredTDA=%s, includeLaunchedFromBubble=%b", activityType, taskAffinity, intent, info, preferredTaskDisplayArea, includeLaunchedFromBubble); mTmpFindTaskResult.init(activityType, taskAffinity, intent, info, includeLaunchedFromBubble); // Looking up task on preferred display area first ActivityRecord candidateActivity = null; Loading services/core/java/com/android/server/wm/TaskFragment.java +18 −5 Original line number Diff line number Diff line Loading @@ -1104,21 +1104,34 @@ class TaskFragment extends WindowContainer<WindowContainer> { } ActivityRecord getTopNonFinishingActivity() { return getTopNonFinishingActivity(true /* includeOverlays */); return getTopNonFinishingActivity( true /* includeOverlays */, true /* includeLaunchedFromBubble */); } /** * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to * the current user. * @param includeOverlays whether the task overlay activity should be included. * @param includeLaunchedFromBubble whether activities that were launched from a bubble should * be included. * @see #topRunningActivity(boolean) */ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) { // Split into 2 to avoid object creation due to variable capture. ActivityRecord getTopNonFinishingActivity(boolean includeOverlays, boolean includeLaunchedFromBubble) { // Split to avoid object creation due to variable capture. if (includeOverlays) { return getActivity((r) -> !r.finishing); if (includeLaunchedFromBubble) { return getActivity(r -> !r.finishing); } else { return getActivity(r -> !r.finishing && !r.getLaunchedFromBubble()); } } if (includeLaunchedFromBubble) { return getActivity(r -> !r.finishing && !r.isTaskOverlay()); } else { return getActivity( r -> !r.finishing && !r.isTaskOverlay() && !r.getLaunchedFromBubble()); } return getActivity((r) -> !r.finishing && !r.isTaskOverlay()); } ActivityRecord topRunningActivity() { Loading services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +125 −5 Original line number Diff line number Diff line Loading @@ -95,6 +95,8 @@ import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; import android.service.voice.IVoiceInteractionSession; Loading @@ -112,6 +114,7 @@ import com.android.server.pm.pkg.AndroidPackage; import com.android.server.wm.BackgroundActivityStartController.BalVerdict; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; import com.android.server.wm.utils.MockTracker; import com.android.wm.shell.Flags; import org.junit.After; import org.junit.Before; Loading Loading @@ -492,7 +495,8 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(splitSecondReusableActivity.mActivityComponent); doReturn(splitSecondReusableActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(splitSecondReusableActivity) .when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testSplitScreenDeliverToTop").execute(); // Ensure result is delivering intent to top. Loading @@ -519,7 +523,8 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(splitSecondReusableActivity.mActivityComponent); doReturn(splitSecondReusableActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(splitSecondReusableActivity) .when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testSplitScreenMoveToFront").execute(); // Ensure result is moving task to front. Loading Loading @@ -566,7 +571,7 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(activities.get(3).mActivityComponent); doReturn(activities.get(3)).when(mRootWindowContainer).findTask(any(), any()); doReturn(activities.get(3)).when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testDesktopModeDeliverToTop").execute(); // Ensure result is delivering intent to top. Loading @@ -593,7 +598,8 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(desktopModeReusableActivity.mActivityComponent); doReturn(desktopModeReusableActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(desktopModeReusableActivity) .when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testDesktopModeMoveToFront").execute(); // Ensure result is moving task to front. Loading Loading @@ -755,7 +761,7 @@ public class ActivityStarterTests extends WindowTestsBase { final ActivityRecord baseActivity = new ActivityBuilder(mAtm).setCreateTask(true).build(); baseActivity.getRootTask().setWindowingMode(WINDOWING_MODE_PINNED); doReturn(baseActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(baseActivity).when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); ActivityOptions rawOptions = ActivityOptions.makeBasic() .setPendingIntentCreatorBackgroundActivityStartMode( Loading Loading @@ -1648,6 +1654,120 @@ public class ActivityStarterTests extends WindowTestsBase { assertNotEquals(inTask, target.getTask()); } @EnableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_reusesBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched with the same component as the bubbled activity final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); startActivityInner(starter, targetRecord, bubbledActivity, null /* options */, null /* inTask */, null /* inTaskFragment */); assertEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @EnableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_nullSourceRecord_doesNotReuseBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); // pass null as the source record startActivityInner(starter, targetRecord, null, null /* options */, null /* inTask */, null /* inTaskFragment */); assertNotEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @EnableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_nonBubbledSourceRecord_doesNotReuseBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create a non bubbled activity final ActivityRecord nonBubbleSourceRecord = new ActivityBuilder(mAtm).setCreateTask(true) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()) .build(); // create the target activity to be launched final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); // use the non bubbled activity as the source startActivityInner(starter, targetRecord, nonBubbleSourceRecord, null /* options */, null /* inTask */, null /* inTaskFragment*/); assertNotEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @DisableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_nullSourceRecord_flagDisabled_reusesBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); // pass null as the source record startActivityInner(starter, targetRecord, null, null /* options */, null /* inTask */, null /* inTaskFragment */); assertEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @DisableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_fromBubble_flagDisabled_reusesBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched with the same component as the bubbled activity final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); startActivityInner(starter, targetRecord, bubbledActivity, null /* options */, null /* inTask */, null /* inTaskFragment */); assertEquals(bubbledActivity.getTask(), targetRecord.getTask()); } private ActivityRecord createBubbledActivity() { final ActivityOptions opts = ActivityOptions.makeBasic(); opts.setTaskAlwaysOnTop(true); opts.setLaunchedFromBubble(true); opts.setLaunchBounds(new Rect(10, 10, 100, 100)); return new ActivityBuilder(mAtm) .setCreateTask(true) .setComponent(ActivityBuilder.getDefaultComponent()) .setActivityOptions(opts) .build(); } private static void startActivityInner(ActivityStarter starter, ActivityRecord target, ActivityRecord source, ActivityOptions options, Task inTask, TaskFragment inTaskFragment) { Loading services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java +6 −5 Original line number Diff line number Diff line Loading @@ -405,11 +405,12 @@ public class RootTaskTests extends WindowTestsBase { final RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult(); result.init(r.getActivityType(), r.taskAffinity, r.intent, r.info); result.init(r.getActivityType(), r.taskAffinity, r.intent, r.info, true); result.process(task); assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */)); assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */)); assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */, true)); assertEquals( taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */, true)); assertNotNull(result.mIdealRecord); } Loading @@ -432,7 +433,7 @@ public class RootTaskTests extends WindowTestsBase { final ActivityRecord r1 = new ActivityBuilder(mAtm).setComponent( target).setTargetActivity(targetActivity).build(); RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult(); result.init(r1.getActivityType(), r1.taskAffinity, r1.intent, r1.info); result.init(r1.getActivityType(), r1.taskAffinity, r1.intent, r1.info, true); result.process(parentTask); assertThat(result.mIdealRecord).isNotNull(); Loading @@ -440,7 +441,7 @@ public class RootTaskTests extends WindowTestsBase { final ActivityRecord r2 = new ActivityBuilder(mAtm).setComponent( alias).setTargetActivity(targetActivity).build(); result = new RootWindowContainer.FindTaskResult(); result.init(r2.getActivityType(), r2.taskAffinity, r2.intent, r2.info); result.init(r2.getActivityType(), r2.taskAffinity, r2.intent, r2.info, true); result.process(parentTask); assertThat(result.mIdealRecord).isNotNull(); } Loading Loading
services/core/java/com/android/server/wm/ActivityStarter.java +15 −3 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ import com.android.server.wm.BackgroundActivityStartController.BalCode; import com.android.server.wm.BackgroundActivityStartController.BalVerdict; import com.android.server.wm.LaunchParamsController.LaunchParams; import com.android.server.wm.TaskFragment.EmbeddingCheckResult; import com.android.wm.shell.Flags; import java.io.PrintWriter; import java.lang.annotation.Retention; Loading Loading @@ -1723,7 +1724,14 @@ class ActivityStarter { // Get top task at beginning because the order may be changed when reusing existing task. final Task prevTopRootTask = mPreferredTaskDisplayArea.getFocusedRootTask(); final Task prevTopTask = prevTopRootTask != null ? prevTopRootTask.getTopLeafTask() : null; final Task reusedTask = resolveReusableTask(); final boolean sourceActivityLaunchedFromBubble = sourceRecord != null && sourceRecord.getLaunchedFromBubble(); // if the flag is enabled, allow reusing bubbled tasks only if the source activity is // bubbled. final boolean includeLaunchedFromBubble = Flags.onlyReuseBubbledTaskWhenLaunchedFromBubble() ? sourceActivityLaunchedFromBubble : true; final Task reusedTask = resolveReusableTask(includeLaunchedFromBubble); // If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() Loading Loading @@ -2722,8 +2730,11 @@ class ActivityStarter { /** * Decide whether the new activity should be inserted into an existing task. Returns null * if not or an ActivityRecord with the task into which the new activity should be added. * * @param includeLaunchedFromBubble whether a task whose top activity was launched from a bubble * should be allowed to be reused for the new activity. */ private Task resolveReusableTask() { private Task resolveReusableTask(boolean includeLaunchedFromBubble) { // If a target task is specified, try to reuse that one if (mOptions != null && mOptions.getLaunchTaskId() != INVALID_TASK_ID) { Task launchTask = mRootWindowContainer.anyTaskForId(mOptions.getLaunchTaskId()); Loading Loading @@ -2767,7 +2778,8 @@ class ActivityStarter { } else { // Otherwise find the best task to put the activity in. intentActivity = mRootWindowContainer.findTask(mStartActivity, mPreferredTaskDisplayArea); mRootWindowContainer.findTask(mStartActivity, mPreferredTaskDisplayArea, includeLaunchedFromBubble); } } Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +17 −8 Original line number Diff line number Diff line Loading @@ -314,13 +314,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private boolean isDocument; private Uri documentData; void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info) { // determines whether to include bubbled tasks. defaults to true to preserve previous // behavior. private boolean mIncludeLaunchedFromBubble = true; void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info, boolean includeLaunchedFromBubble) { mActivityType = activityType; mTaskAffinity = taskAffinity; mIntent = intent; mInfo = info; mIdealRecord = null; mCandidateRecord = null; mIncludeLaunchedFromBubble = includeLaunchedFromBubble; } /** Loading Loading @@ -362,7 +368,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } // Overlays should not be considered as the task's logical top activity. final ActivityRecord r = task.getTopNonFinishingActivity(false /* includeOverlays */); final ActivityRecord r = task.getTopNonFinishingActivity( false /* includeOverlays */, mIncludeLaunchedFromBubble); if (r == null || r.finishing || r.mUserId != userId || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { Loading Loading @@ -2372,18 +2379,20 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } @Nullable ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea) { ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble) { return findTask(r.getActivityType(), r.taskAffinity, r.intent, r.info, preferredTaskDisplayArea); preferredTaskDisplayArea, includeLaunchedFromBubble); } @Nullable ActivityRecord findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info, TaskDisplayArea preferredTaskDisplayArea) { TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble) { ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of type=%s, taskAffinity=%s, intent=%s" + ", info=%s, preferredTDA=%s", activityType, taskAffinity, intent, info, preferredTaskDisplayArea); mTmpFindTaskResult.init(activityType, taskAffinity, intent, info); + ", info=%s, preferredTDA=%s, includeLaunchedFromBubble=%b", activityType, taskAffinity, intent, info, preferredTaskDisplayArea, includeLaunchedFromBubble); mTmpFindTaskResult.init(activityType, taskAffinity, intent, info, includeLaunchedFromBubble); // Looking up task on preferred display area first ActivityRecord candidateActivity = null; Loading
services/core/java/com/android/server/wm/TaskFragment.java +18 −5 Original line number Diff line number Diff line Loading @@ -1104,21 +1104,34 @@ class TaskFragment extends WindowContainer<WindowContainer> { } ActivityRecord getTopNonFinishingActivity() { return getTopNonFinishingActivity(true /* includeOverlays */); return getTopNonFinishingActivity( true /* includeOverlays */, true /* includeLaunchedFromBubble */); } /** * Returns the top-most non-finishing activity, even if the activity is NOT ok to show to * the current user. * @param includeOverlays whether the task overlay activity should be included. * @param includeLaunchedFromBubble whether activities that were launched from a bubble should * be included. * @see #topRunningActivity(boolean) */ ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) { // Split into 2 to avoid object creation due to variable capture. ActivityRecord getTopNonFinishingActivity(boolean includeOverlays, boolean includeLaunchedFromBubble) { // Split to avoid object creation due to variable capture. if (includeOverlays) { return getActivity((r) -> !r.finishing); if (includeLaunchedFromBubble) { return getActivity(r -> !r.finishing); } else { return getActivity(r -> !r.finishing && !r.getLaunchedFromBubble()); } } if (includeLaunchedFromBubble) { return getActivity(r -> !r.finishing && !r.isTaskOverlay()); } else { return getActivity( r -> !r.finishing && !r.isTaskOverlay() && !r.getLaunchedFromBubble()); } return getActivity((r) -> !r.finishing && !r.isTaskOverlay()); } ActivityRecord topRunningActivity() { Loading
services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +125 −5 Original line number Diff line number Diff line Loading @@ -95,6 +95,8 @@ import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; import android.service.voice.IVoiceInteractionSession; Loading @@ -112,6 +114,7 @@ import com.android.server.pm.pkg.AndroidPackage; import com.android.server.wm.BackgroundActivityStartController.BalVerdict; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; import com.android.server.wm.utils.MockTracker; import com.android.wm.shell.Flags; import org.junit.After; import org.junit.Before; Loading Loading @@ -492,7 +495,8 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(splitSecondReusableActivity.mActivityComponent); doReturn(splitSecondReusableActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(splitSecondReusableActivity) .when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testSplitScreenDeliverToTop").execute(); // Ensure result is delivering intent to top. Loading @@ -519,7 +523,8 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(splitSecondReusableActivity.mActivityComponent); doReturn(splitSecondReusableActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(splitSecondReusableActivity) .when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testSplitScreenMoveToFront").execute(); // Ensure result is moving task to front. Loading Loading @@ -566,7 +571,7 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(activities.get(3).mActivityComponent); doReturn(activities.get(3)).when(mRootWindowContainer).findTask(any(), any()); doReturn(activities.get(3)).when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testDesktopModeDeliverToTop").execute(); // Ensure result is delivering intent to top. Loading @@ -593,7 +598,8 @@ public class ActivityStarterTests extends WindowTestsBase { // Start activity and delivered new intent. starter.getIntent().setComponent(desktopModeReusableActivity.mActivityComponent); doReturn(desktopModeReusableActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(desktopModeReusableActivity) .when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); final int result = starter.setReason("testDesktopModeMoveToFront").execute(); // Ensure result is moving task to front. Loading Loading @@ -755,7 +761,7 @@ public class ActivityStarterTests extends WindowTestsBase { final ActivityRecord baseActivity = new ActivityBuilder(mAtm).setCreateTask(true).build(); baseActivity.getRootTask().setWindowingMode(WINDOWING_MODE_PINNED); doReturn(baseActivity).when(mRootWindowContainer).findTask(any(), any()); doReturn(baseActivity).when(mRootWindowContainer).findTask(any(), any(), anyBoolean()); ActivityOptions rawOptions = ActivityOptions.makeBasic() .setPendingIntentCreatorBackgroundActivityStartMode( Loading Loading @@ -1648,6 +1654,120 @@ public class ActivityStarterTests extends WindowTestsBase { assertNotEquals(inTask, target.getTask()); } @EnableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_reusesBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched with the same component as the bubbled activity final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); startActivityInner(starter, targetRecord, bubbledActivity, null /* options */, null /* inTask */, null /* inTaskFragment */); assertEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @EnableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_nullSourceRecord_doesNotReuseBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); // pass null as the source record startActivityInner(starter, targetRecord, null, null /* options */, null /* inTask */, null /* inTaskFragment */); assertNotEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @EnableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_nonBubbledSourceRecord_doesNotReuseBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create a non bubbled activity final ActivityRecord nonBubbleSourceRecord = new ActivityBuilder(mAtm).setCreateTask(true) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()) .build(); // create the target activity to be launched final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); // use the non bubbled activity as the source startActivityInner(starter, targetRecord, nonBubbleSourceRecord, null /* options */, null /* inTask */, null /* inTaskFragment*/); assertNotEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @DisableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_nullSourceRecord_flagDisabled_reusesBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); // pass null as the source record startActivityInner(starter, targetRecord, null, null /* options */, null /* inTask */, null /* inTaskFragment */); assertEquals(bubbledActivity.getTask(), targetRecord.getTask()); } @DisableFlags(Flags.FLAG_ONLY_REUSE_BUBBLED_TASK_WHEN_LAUNCHED_FROM_BUBBLE) @Test public void launchActivity_fromBubble_flagDisabled_reusesBubbledTask() { final ActivityStarter starter = prepareStarter(0, false); final ActivityRecord bubbledActivity = createBubbledActivity(); // create the target activity to be launched with the same component as the bubbled activity final ActivityRecord targetRecord = new ActivityBuilder(mAtm) .setLaunchMode(LAUNCH_SINGLE_TASK) .setComponent(ActivityBuilder.getDefaultComponent()).build(); starter.getIntent().setComponent(bubbledActivity.mActivityComponent); startActivityInner(starter, targetRecord, bubbledActivity, null /* options */, null /* inTask */, null /* inTaskFragment */); assertEquals(bubbledActivity.getTask(), targetRecord.getTask()); } private ActivityRecord createBubbledActivity() { final ActivityOptions opts = ActivityOptions.makeBasic(); opts.setTaskAlwaysOnTop(true); opts.setLaunchedFromBubble(true); opts.setLaunchBounds(new Rect(10, 10, 100, 100)); return new ActivityBuilder(mAtm) .setCreateTask(true) .setComponent(ActivityBuilder.getDefaultComponent()) .setActivityOptions(opts) .build(); } private static void startActivityInner(ActivityStarter starter, ActivityRecord target, ActivityRecord source, ActivityOptions options, Task inTask, TaskFragment inTaskFragment) { Loading
services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java +6 −5 Original line number Diff line number Diff line Loading @@ -405,11 +405,12 @@ public class RootTaskTests extends WindowTestsBase { final RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult(); result.init(r.getActivityType(), r.taskAffinity, r.intent, r.info); result.init(r.getActivityType(), r.taskAffinity, r.intent, r.info, true); result.process(task); assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */)); assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */)); assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */, true)); assertEquals( taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */, true)); assertNotNull(result.mIdealRecord); } Loading @@ -432,7 +433,7 @@ public class RootTaskTests extends WindowTestsBase { final ActivityRecord r1 = new ActivityBuilder(mAtm).setComponent( target).setTargetActivity(targetActivity).build(); RootWindowContainer.FindTaskResult result = new RootWindowContainer.FindTaskResult(); result.init(r1.getActivityType(), r1.taskAffinity, r1.intent, r1.info); result.init(r1.getActivityType(), r1.taskAffinity, r1.intent, r1.info, true); result.process(parentTask); assertThat(result.mIdealRecord).isNotNull(); Loading @@ -440,7 +441,7 @@ public class RootTaskTests extends WindowTestsBase { final ActivityRecord r2 = new ActivityBuilder(mAtm).setComponent( alias).setTargetActivity(targetActivity).build(); result = new RootWindowContainer.FindTaskResult(); result.init(r2.getActivityType(), r2.taskAffinity, r2.intent, r2.info); result.init(r2.getActivityType(), r2.taskAffinity, r2.intent, r2.info, true); result.process(parentTask); assertThat(result.mIdealRecord).isNotNull(); } Loading