summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Komsiyski <vladokom@google.com> 2023-09-01 10:34:56 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-09-01 10:34:56 +0000
commitd58b2734ddfe18c91bb4c133b8b323fd9cb7f563 (patch)
tree05b8649efc75111ade0c7329a800aa4d045bc1f1
parent12666090a2f3882af02e85dfa2f695397a139cce (diff)
parenta4269d0b8c636c807fef1c12a29aacc5821f1be2 (diff)
Merge "Intercept HOME intents for secondary home displays." into main
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java65
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java13
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java18
-rw-r--r--services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java87
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java89
6 files changed, 204 insertions, 70 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 90e67df65fec..582536b662ce 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2929,7 +2929,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
reparent(newTaskFrag, position);
}
- private boolean isHomeIntent(Intent intent) {
+ static boolean isHomeIntent(Intent intent) {
return ACTION_MAIN.equals(intent.getAction())
&& (intent.hasCategory(CATEGORY_HOME)
|| intent.hasCategory(CATEGORY_SECONDARY_HOME))
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 1eb56f1b7d1c..a5b1132fe499 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -55,6 +55,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -77,7 +78,6 @@ class ActivityStartInterceptor {
private final ActivityTaskManagerService mService;
private final ActivityTaskSupervisor mSupervisor;
- private final RootWindowContainer mRootWindowContainer;
private final Context mServiceContext;
// UserManager cannot be final as it's not ready when this class is instantiated during boot
@@ -110,17 +110,23 @@ class ActivityStartInterceptor {
TaskFragment mInTaskFragment;
ActivityOptions mActivityOptions;
+ /*
+ * Note that this is just a hint of what the launch display area will be as it is
+ * based only on the information at the early pre-interception stage of starting the
+ * intent. The real launch display area calculated later may be different from this one.
+ */
+ TaskDisplayArea mPresumableLaunchDisplayArea;
+
ActivityStartInterceptor(
ActivityTaskManagerService service, ActivityTaskSupervisor supervisor) {
- this(service, supervisor, service.mRootWindowContainer, service.mContext);
+ this(service, supervisor, service.mContext);
}
@VisibleForTesting
ActivityStartInterceptor(ActivityTaskManagerService service, ActivityTaskSupervisor supervisor,
- RootWindowContainer root, Context context) {
+ Context context) {
mService = service;
mSupervisor = supervisor;
- mRootWindowContainer = root;
mServiceContext = context;
}
@@ -162,7 +168,7 @@ class ActivityStartInterceptor {
/**
* A helper function to obtain the targeted {@link TaskFragment} during
* {@link #intercept(Intent, ResolveInfo, ActivityInfo, String, Task, TaskFragment, int, int,
- * ActivityOptions)} if any.
+ * ActivityOptions, TaskDisplayArea)} if any.
*/
@Nullable
private TaskFragment getLaunchTaskFragment() {
@@ -187,7 +193,7 @@ class ActivityStartInterceptor {
*/
boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType,
Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid,
- ActivityOptions activityOptions) {
+ ActivityOptions activityOptions, TaskDisplayArea presumableLaunchDisplayArea) {
mUserManager = UserManager.get(mServiceContext);
mIntent = intent;
@@ -199,6 +205,7 @@ class ActivityStartInterceptor {
mInTask = inTask;
mInTaskFragment = inTaskFragment;
mActivityOptions = activityOptions;
+ mPresumableLaunchDisplayArea = presumableLaunchDisplayArea;
if (interceptQuietProfileIfNeeded()) {
// If work profile is turned off, skip the work challenge since the profile can only
@@ -221,6 +228,11 @@ class ActivityStartInterceptor {
if (interceptLockedManagedProfileIfNeeded()) {
return true;
}
+ if (interceptHomeIfNeeded()) {
+ // Replace primary home intents directed at displays that do not support primary home
+ // but support secondary home with the relevant secondary home activity.
+ return true;
+ }
final SparseArray<ActivityInterceptorCallback> callbacks =
mService.getActivityInterceptorCallbacks();
@@ -470,6 +482,47 @@ class ActivityStartInterceptor {
return true;
}
+ private boolean interceptHomeIfNeeded() {
+ if (mPresumableLaunchDisplayArea == null || mService.mRootWindowContainer == null) {
+ return false;
+ }
+ if (!ActivityRecord.isHomeIntent(mIntent)) {
+ return false;
+ }
+ if (!mIntent.hasCategory(Intent.CATEGORY_HOME)) {
+ // Already a secondary home intent, leave it alone.
+ return false;
+ }
+ if (mService.mRootWindowContainer.shouldPlacePrimaryHomeOnDisplay(
+ mPresumableLaunchDisplayArea.getDisplayId())) {
+ // Primary home can be launched to the display area.
+ return false;
+ }
+ if (!mService.mRootWindowContainer.shouldPlaceSecondaryHomeOnDisplayArea(
+ mPresumableLaunchDisplayArea)) {
+ // Secondary home cannot be launched on the display area.
+ return false;
+ }
+
+ // At this point we have a primary home intent for a display that does not support primary
+ // home activity but it supports secondary home one. So replace it with secondary home.
+ Pair<ActivityInfo, Intent> info = mService.mRootWindowContainer
+ .resolveSecondaryHomeActivity(mUserId, mPresumableLaunchDisplayArea);
+ mIntent = info.second;
+ // The new task flag is needed because the home activity should already be in the root task
+ // and should not be moved to the caller's task. Also, activities cannot change their type,
+ // e.g. a standard activity cannot become a home activity.
+ mIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
+ mCallingPid = mRealCallingPid;
+ mCallingUid = mRealCallingUid;
+ mResolvedType = null;
+
+ mRInfo = mSupervisor.resolveIntent(mIntent, mResolvedType, mUserId, /* flags= */ 0,
+ mRealCallingUid, mRealCallingPid);
+ mAInfo = mSupervisor.resolveActivity(mIntent, mRInfo, mStartFlags, /*profilerInfo=*/ null);
+ return true;
+ }
+
private boolean isPackageSuspended() {
return mAInfo != null && mAInfo.applicationInfo != null
&& (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) != 0;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 1bc78d6e0820..458d1e8fa04b 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1154,10 +1154,12 @@ class ActivityStarter {
}
}
+ final TaskDisplayArea suggestedLaunchDisplayArea =
+ computeSuggestedLaunchDisplayArea(inTask, sourceRecord, checkedOptions);
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage,
callingFeatureId);
if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
- callingPid, callingUid, checkedOptions)) {
+ callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea)) {
// activity start was intercepted, e.g. because the target user is currently in quiet
// mode (turn off work) or the target application is suspended
intent = mInterceptor.mIntent;
@@ -1890,6 +1892,15 @@ class ActivityStarter {
mPreferredWindowingMode = mLaunchParams.mWindowingMode;
}
+ private TaskDisplayArea computeSuggestedLaunchDisplayArea(
+ Task task, ActivityRecord source, ActivityOptions options) {
+ mSupervisor.getLaunchParamsController().calculate(task, /*layout=*/null,
+ /*activity=*/ null, source, options, mRequest, PHASE_DISPLAY, mLaunchParams);
+ return mLaunchParams.hasPreferredTaskDisplayArea()
+ ? mLaunchParams.mPreferredTaskDisplayArea
+ : mRootWindowContainer.getDefaultTaskDisplayArea();
+ }
+
@VisibleForTesting
int isAllowedToStart(ActivityRecord r, boolean newTask, Task targetTask) {
if (r.packageName == null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 57f8268b2fdc..d56acaa00f00 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1608,6 +1608,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
/**
+ * Check if the display is valid for primary home activity.
+ *
+ * @param displayId The target display ID
+ * @return {@code true} if allowed to launch, {@code false} otherwise.
+ */
+ boolean shouldPlacePrimaryHomeOnDisplay(int displayId) {
+ // No restrictions to default display, vr 2d display or main display for visible users.
+ return displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
+ && (displayId == mService.mVr2dDisplayId
+ || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)));
+ }
+
+ /**
* Check if the display area is valid for secondary home activity.
*
* @param taskDisplayArea The target display area.
@@ -1680,10 +1693,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final int displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId()
: INVALID_DISPLAY;
- if (displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY
- && (displayId == mService.mVr2dDisplayId
- || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId)))) {
- // No restrictions to default display, vr 2d display or main display for visible users.
+ if (shouldPlacePrimaryHomeOnDisplay(displayId)) {
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index ad46770432a1..fa620db23306 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -118,12 +118,14 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
root = activity;
}
- if (root == null) {
+ if (root == null && phase != PHASE_DISPLAY) {
// There is a case that can lead us here. The caller is moving the top activity that is
// in a task that has multiple activities to PIP mode. For that the caller is creating a
// new task to host the activity so that we only move the top activity to PIP mode and
// keep other activities in the previous task. There is no point to apply the launch
// logic in this case.
+ // However, for PHASE_DISPLAY the root may be null, but we still want to get a hint of
+ // what the suggested launch display area would be.
return RESULT_SKIP;
}
@@ -395,8 +397,9 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
private TaskDisplayArea getPreferredLaunchTaskDisplayArea(@Nullable Task task,
- @Nullable ActivityOptions options, ActivityRecord source, LaunchParams currentParams,
- @NonNull ActivityRecord activityRecord, @Nullable Request request) {
+ @Nullable ActivityOptions options, @Nullable ActivityRecord source,
+ @Nullable LaunchParams currentParams, @Nullable ActivityRecord activityRecord,
+ @Nullable Request request) {
TaskDisplayArea taskDisplayArea = null;
final WindowContainerToken optionLaunchTaskDisplayAreaToken = options != null
@@ -438,8 +441,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
// If the source activity is a no-display activity, pass on the launch display area token
// from source activity as currently preferred.
- if (taskDisplayArea == null && source != null
- && source.noDisplay) {
+ if (taskDisplayArea == null && source != null && source.noDisplay) {
taskDisplayArea = source.mHandoverTaskDisplayArea;
if (taskDisplayArea != null) {
if (DEBUG) appendLog("display-area-from-no-display-source=" + taskDisplayArea);
@@ -478,21 +480,24 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
}
}
- if (taskDisplayArea == null) {
+ if (taskDisplayArea == null && currentParams != null) {
taskDisplayArea = currentParams.mPreferredTaskDisplayArea;
+ if (DEBUG) appendLog("display-area-from-current-params=" + taskDisplayArea);
}
// Re-route to default display if the device didn't declare support for multi-display
if (taskDisplayArea != null && !mSupervisor.mService.mSupportsMultiDisplay
&& taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY) {
taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-no-multidisplay=" + taskDisplayArea);
}
// Re-route to default display if the home activity doesn't support multi-display
- if (taskDisplayArea != null && activityRecord.isActivityTypeHome()
+ if (taskDisplayArea != null && activityRecord != null && activityRecord.isActivityTypeHome()
&& !mSupervisor.mRootWindowContainer.canStartHomeOnDisplayArea(activityRecord.info,
taskDisplayArea, false /* allowInstrumenting */)) {
taskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-home=" + taskDisplayArea);
}
return (taskDisplayArea != null)
@@ -516,34 +521,56 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
* @return {@link TaskDisplayArea} to house the task
*/
private TaskDisplayArea getFallbackDisplayAreaForActivity(
- @NonNull ActivityRecord activityRecord, @Nullable Request request) {
-
- WindowProcessController controllerFromLaunchingRecord = mSupervisor.mService
- .getProcessController(activityRecord.launchedFromPid,
- activityRecord.launchedFromUid);
- final TaskDisplayArea displayAreaForLaunchingRecord = controllerFromLaunchingRecord == null
- ? null : controllerFromLaunchingRecord.getTopActivityDisplayArea();
- if (displayAreaForLaunchingRecord != null) {
- return displayAreaForLaunchingRecord;
- }
+ @Nullable ActivityRecord activityRecord, @Nullable Request request) {
+ if (activityRecord != null) {
+ WindowProcessController controllerFromLaunchingRecord =
+ mSupervisor.mService.getProcessController(
+ activityRecord.launchedFromPid, activityRecord.launchedFromUid);
+ if (controllerFromLaunchingRecord != null) {
+ final TaskDisplayArea taskDisplayAreaForLaunchingRecord =
+ controllerFromLaunchingRecord.getTopActivityDisplayArea();
+ if (taskDisplayAreaForLaunchingRecord != null) {
+ if (DEBUG) {
+ appendLog("display-area-for-launching-record="
+ + taskDisplayAreaForLaunchingRecord);
+ }
+ return taskDisplayAreaForLaunchingRecord;
+ }
+ }
- WindowProcessController controllerFromProcess = mSupervisor.mService.getProcessController(
- activityRecord.getProcessName(), activityRecord.getUid());
- final TaskDisplayArea displayAreaForRecord = controllerFromProcess == null ? null
- : controllerFromProcess.getTopActivityDisplayArea();
- if (displayAreaForRecord != null) {
- return displayAreaForRecord;
+ WindowProcessController controllerFromProcess =
+ mSupervisor.mService.getProcessController(
+ activityRecord.getProcessName(), activityRecord.getUid());
+ if (controllerFromProcess != null) {
+ final TaskDisplayArea displayAreaForRecord =
+ controllerFromProcess.getTopActivityDisplayArea();
+ if (displayAreaForRecord != null) {
+ if (DEBUG) appendLog("display-area-for-record=" + displayAreaForRecord);
+ return displayAreaForRecord;
+ }
+ }
}
- WindowProcessController controllerFromRequest = request == null ? null : mSupervisor
- .mService.getProcessController(request.realCallingPid, request.realCallingUid);
- final TaskDisplayArea displayAreaFromSourceProcess = controllerFromRequest == null ? null
- : controllerFromRequest.getTopActivityDisplayArea();
- if (displayAreaFromSourceProcess != null) {
- return displayAreaFromSourceProcess;
+ if (request != null) {
+ WindowProcessController controllerFromRequest =
+ mSupervisor.mService.getProcessController(
+ request.realCallingPid, request.realCallingUid);
+ if (controllerFromRequest != null) {
+ final TaskDisplayArea displayAreaFromSourceProcess =
+ controllerFromRequest.getTopActivityDisplayArea();
+ if (displayAreaFromSourceProcess != null) {
+ if (DEBUG) {
+ appendLog("display-area-source-process=" + displayAreaFromSourceProcess);
+ }
+ return displayAreaFromSourceProcess;
+ }
+ }
}
- return mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ final TaskDisplayArea defaultTaskDisplayArea =
+ mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea();
+ if (DEBUG) appendLog("display-area-from-default-fallback=" + defaultTaskDisplayArea);
+ return defaultTaskDisplayArea;
}
private boolean canInheritWindowingModeFromSource(@NonNull DisplayContent display,
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index bcb0c6b5c269..0989db4c25ac 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -59,6 +59,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.testing.DexmakerShareClassLoaderRule;
+import android.util.Pair;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -128,6 +129,8 @@ public class ActivityStartInterceptorTest {
private ActivityManagerInternal mAmInternal;
@Mock
private LockTaskController mLockTaskController;
+ @Mock
+ private TaskDisplayArea mTaskDisplayArea;
private ActivityStartInterceptor mInterceptor;
private ActivityInfo mAInfo = new ActivityInfo();
@@ -139,8 +142,8 @@ public class ActivityStartInterceptorTest {
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mService.mAmInternal = mAmInternal;
- mInterceptor = new ActivityStartInterceptor(
- mService, mSupervisor, mRootWindowContainer, mContext);
+ mService.mRootWindowContainer = mRootWindowContainer;
+ mInterceptor = new ActivityStartInterceptor(mService, mSupervisor, mContext);
mInterceptor.setStates(TEST_USER_ID, TEST_REAL_CALLING_PID, TEST_REAL_CALLING_UID,
TEST_START_FLAGS, TEST_CALLING_PACKAGE, null);
@@ -201,7 +204,7 @@ public class ActivityStartInterceptorTest {
.thenReturn(PLATFORM_PACKAGE_NAME);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the admin support intent
assertEquals(ADMIN_SUPPORT_INTENT, mInterceptor.mIntent);
@@ -212,7 +215,7 @@ public class ActivityStartInterceptorTest {
final String suspendingPackage = "com.test.suspending.package";
final SuspendDialogInfo dialogInfo = suspendPackage(suspendingPackage);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// Check intent parameters
assertEquals(dialogInfo,
@@ -243,7 +246,7 @@ public class ActivityStartInterceptorTest {
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT))
.thenReturn(false);
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertTrue(BlockedAppActivity.createIntent(TEST_USER_ID, TEST_PACKAGE_NAME)
.filterEquals(mInterceptor.mIntent));
@@ -257,7 +260,8 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
// THEN calling intercept returns false because package also has to be suspended.
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
@Test
@@ -268,7 +272,7 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -284,7 +288,7 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -300,7 +304,7 @@ public class ActivityStartInterceptorTest {
when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the quiet mode intent
assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
@@ -313,7 +317,7 @@ public class ActivityStartInterceptorTest {
when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true);
// THEN calling intercept returns true
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is the confirm credentials intent
assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent));
@@ -329,7 +333,7 @@ public class ActivityStartInterceptorTest {
mAInfo.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
// THEN calling intercept returns true
- mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is original intent
assertSame(originalIntent, mInterceptor.mIntent);
@@ -345,7 +349,7 @@ public class ActivityStartInterceptorTest {
mAInfo.directBootAware = false;
// THEN calling intercept returns true
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is the confirm credentials intent
assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent));
@@ -362,7 +366,7 @@ public class ActivityStartInterceptorTest {
mAInfo.directBootAware = true;
// THEN calling intercept returns true
- mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0, null, null);
// THEN the returned intent is original intent
assertSame(originalIntent, mInterceptor.mIntent);
@@ -375,7 +379,7 @@ public class ActivityStartInterceptorTest {
.thenReturn("This app is bad");
// THEN calling intercept returns true
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
// THEN the returned intent is the harmful app warning intent
assertEquals(HarmfulAppWarningActivity.class.getName(),
@@ -383,11 +387,40 @@ public class ActivityStartInterceptorTest {
}
@Test
+ public void testHomeIntentInterception() {
+ // GIVEN a primary home intent and a display area that doesn't support it but supports
+ // secondary home activities
+ Intent originalIntent = new Intent(Intent.ACTION_MAIN);
+ originalIntent.addCategory(Intent.CATEGORY_HOME);
+
+ Intent expectedIntent = new Intent(Intent.ACTION_MAIN);
+ expectedIntent.addCategory(Intent.CATEGORY_SECONDARY_HOME);
+ expectedIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ final int secondaryDisplayId = 7;
+ when(mTaskDisplayArea.getDisplayId()).thenReturn(secondaryDisplayId);
+ when(mRootWindowContainer.shouldPlacePrimaryHomeOnDisplay(eq(secondaryDisplayId)))
+ .thenReturn(false);
+ when(mRootWindowContainer.shouldPlaceSecondaryHomeOnDisplayArea(eq(mTaskDisplayArea)))
+ .thenReturn(true);
+ when(mRootWindowContainer.resolveSecondaryHomeActivity(
+ eq(TEST_USER_ID), eq(mTaskDisplayArea)))
+ .thenReturn(Pair.create(null, expectedIntent));
+
+ // THEN calling intercept returns true
+ assertTrue(mInterceptor.intercept(originalIntent, null, mAInfo, null, null, null, 0, 0,
+ null, mTaskDisplayArea));
+
+ // THEN the returned intent is the secondary home intent
+ assertSame(expectedIntent, mInterceptor.mIntent);
+ }
+
+ @Test
public void testNoInterception() {
// GIVEN that none of the interception conditions are met
// THEN calling intercept returns false
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
public void addMockInterceptorCallback(
@@ -420,7 +453,7 @@ public class ActivityStartInterceptorTest {
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3));
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
}
@@ -429,7 +462,7 @@ public class ActivityStartInterceptorTest {
public void testInterceptionCallback_singleCallbackReturnsNull() {
addMockInterceptorCallback(null, null);
- assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
}
@Test
@@ -437,7 +470,7 @@ public class ActivityStartInterceptorTest {
addMockInterceptorCallback(null, null);
addMockInterceptorCallback(new Intent("android.test.second"), null);
- assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.second", mInterceptor.mIntent.getAction());
}
@@ -447,7 +480,7 @@ public class ActivityStartInterceptorTest {
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3), true);
ActivityInfo aInfo = mAInfo;
- assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
assertEquals(aInfo, mInterceptor.mAInfo); // mAInfo should not be resolved
@@ -459,7 +492,7 @@ public class ActivityStartInterceptorTest {
new Intent("android.test.foo"),
ActivityOptions.makeBasic().setLaunchDisplayId(3));
ActivityInfo aInfo = mAInfo;
- assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null));
+ assertTrue(mInterceptor.intercept(null, null, aInfo, null, null, null, 0, 0, null, null));
assertEquals("android.test.foo", mInterceptor.mIntent.getAction());
assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId());
assertNotEquals(aInfo, mInterceptor.mAInfo); // mAInfo should be resolved after intercept
@@ -488,7 +521,7 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setAction(ACTION_START_SANDBOXED_ACTIVITY);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -505,7 +538,7 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setPackage(sandboxPackageNameMock);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -522,7 +555,7 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
Intent intent = new Intent().setComponent(new ComponentName(sandboxPackageNameMock, ""));
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, times(1)).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));
@@ -539,23 +572,23 @@ public class ActivityStartInterceptorTest {
when(packageManagerMock.getSdkSandboxPackageName()).thenReturn(sandboxPackageNameMock);
// Intent: null
- mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null);
// Action: null, Package: null, ComponentName: null
Intent intent = new Intent();
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong Action
intent = new Intent().setAction(Intent.ACTION_VIEW);
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong Package
intent = new Intent().setPackage("Random");
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
// Wrong ComponentName's package
intent = new Intent().setComponent(new ComponentName("Random", ""));
- mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null);
+ mInterceptor.intercept(intent, null, mAInfo, null, null, null, 0, 0, null, null);
verify(spyCallback, never()).onInterceptActivityLaunch(
any(ActivityInterceptorCallback.ActivityInterceptorInfo.class));