diff options
3 files changed, 61 insertions, 17 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java index a452013bf42a..7d84bdf78056 100644 --- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java +++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java @@ -49,6 +49,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.os.Bundle; +import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -64,7 +65,7 @@ import com.android.server.am.ActivityManagerService; import com.android.server.wm.ActivityInterceptorCallback.ActivityInterceptResult; /** - * A class that contains activity intercepting logic for {@link ActivityStarter#startActivityLocked} + * A class that contains activity intercepting logic for {@link ActivityStarter#execute()} * It's initialized via setStates and interception occurs via the intercept method. * * Note that this class is instantiated when {@link ActivityManagerService} gets created so there @@ -104,6 +105,7 @@ class ActivityStartInterceptor { ActivityInfo mAInfo; String mResolvedType; Task mInTask; + TaskFragment mInTaskFragment; ActivityOptions mActivityOptions; ActivityStartInterceptor( @@ -135,15 +137,46 @@ class ActivityStartInterceptor { } private IntentSender createIntentSenderForOriginalIntent(int callingUid, int flags) { - Bundle activityOptions = deferCrossProfileAppsAnimationIfNecessary(); + Bundle bOptions = deferCrossProfileAppsAnimationIfNecessary(); + final TaskFragment taskFragment = getLaunchTaskFragment(); + // If the original intent is going to be embedded, try to forward the embedding TaskFragment + // and its task id to embed back the original intent. + if (taskFragment != null) { + ActivityOptions activityOptions = bOptions != null + ? ActivityOptions.fromBundle(bOptions) + : ActivityOptions.makeBasic(); + activityOptions.setLaunchTaskFragmentToken(taskFragment.getFragmentToken()); + bOptions = activityOptions.toBundle(); + } final IIntentSender target = mService.getIntentSenderLocked( INTENT_SENDER_ACTIVITY, mCallingPackage, mCallingFeatureId, callingUid, mUserId, null /*token*/, null /*resultCode*/, 0 /*requestCode*/, new Intent[] { mIntent }, new String[] { mResolvedType }, - flags, activityOptions); + flags, bOptions); return new IntentSender(target); } + + /** + * A helper function to obtain the targeted {@link TaskFragment} during + * {@link #intercept(Intent, ResolveInfo, ActivityInfo, String, Task, TaskFragment, int, int, + * ActivityOptions)} if any. + */ + @Nullable + private TaskFragment getLaunchTaskFragment() { + if (mInTaskFragment != null) { + return mInTaskFragment; + } + if (mActivityOptions == null) { + return null; + } + final IBinder taskFragToken = mActivityOptions.getLaunchTaskFragmentToken(); + if (taskFragToken == null) { + return null; + } + return TaskFragment.fromTaskFragmentToken(taskFragToken, mService); + } + /** * Intercept the launch intent based on various signals. If an interception happened the * internal variables get assigned and need to be read explicitly by the caller. @@ -151,7 +184,8 @@ class ActivityStartInterceptor { * @return true if an interception occurred */ boolean intercept(Intent intent, ResolveInfo rInfo, ActivityInfo aInfo, String resolvedType, - Task inTask, int callingPid, int callingUid, ActivityOptions activityOptions) { + Task inTask, TaskFragment inTaskFragment, int callingPid, int callingUid, + ActivityOptions activityOptions) { mUserManager = UserManager.get(mServiceContext); mIntent = intent; @@ -161,6 +195,7 @@ class ActivityStartInterceptor { mAInfo = aInfo; mResolvedType = resolvedType; mInTask = inTask; + mInTaskFragment = inTaskFragment; mActivityOptions = activityOptions; if (interceptQuietProfileIfNeeded()) { @@ -332,12 +367,21 @@ class ActivityStartInterceptor { mCallingPid = mRealCallingPid; mCallingUid = mRealCallingUid; mResolvedType = null; + final TaskFragment taskFragment = getLaunchTaskFragment(); // If we are intercepting and there was a task, convert it into an extra for the // ConfirmCredentials intent and unassign it, as otherwise the task will move to // front even if ConfirmCredentials is cancelled. if (mInTask != null) { mIntent.putExtra(EXTRA_TASK_ID, mInTask.mTaskId); mInTask = null; + } else if (taskFragment != null) { + // If the original intent is started to an embedded TaskFragment, append its parent task + // id to extra. It is to embed back the original intent to the TaskFragment with the + // same task. + final Task parentTask = taskFragment.getTask(); + if (parentTask != null) { + mIntent.putExtra(EXTRA_TASK_ID, parentTask.mTaskId); + } } if (mActivityOptions == null) { mActivityOptions = ActivityOptions.makeBasic(); diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index a27352921caa..890b91025151 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1060,8 +1060,8 @@ class ActivityStarter { mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage, callingFeatureId); - if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, - callingUid, checkedOptions)) { + if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment, + callingPid, callingUid, checkedOptions)) { // 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; 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 73e409abf0c1..1575336600b4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java @@ -192,7 +192,7 @@ public class ActivityStartInterceptorTest { .thenReturn(PLATFORM_PACKAGE_NAME); // THEN calling intercept returns true - assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); // THEN the returned intent is the admin support intent assertEquals(ADMIN_SUPPORT_INTENT, mInterceptor.mIntent); @@ -203,7 +203,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, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); // Check intent parameters assertEquals(dialogInfo, @@ -234,7 +234,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, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); assertTrue(BlockedAppActivity.createIntent(TEST_USER_ID, TEST_PACKAGE_NAME) .filterEquals(mInterceptor.mIntent)); @@ -246,7 +246,7 @@ public class ActivityStartInterceptorTest { when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true); // THEN calling intercept returns true - assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); // THEN the returned intent is the quiet mode intent assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID) @@ -260,7 +260,7 @@ public class ActivityStartInterceptorTest { when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true); // THEN calling intercept returns true - assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); // THEN the returned intent is the quiet mode intent assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID) @@ -273,7 +273,7 @@ public class ActivityStartInterceptorTest { when(mAmInternal.shouldConfirmCredentials(TEST_USER_ID)).thenReturn(true); // THEN calling intercept returns true - mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null); + mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null); // THEN the returned intent is the quiet mode intent assertTrue(CONFIRM_CREDENTIALS_INTENT.filterEquals(mInterceptor.mIntent)); @@ -286,7 +286,7 @@ public class ActivityStartInterceptorTest { .thenReturn("This app is bad"); // THEN calling intercept returns true - assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); // THEN the returned intent is the harmful app warning intent assertEquals(HarmfulAppWarningActivity.class.getName(), @@ -298,7 +298,7 @@ public class ActivityStartInterceptorTest { // GIVEN that none of the interception conditions are met // THEN calling intercept returns false - assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); } public void addMockInterceptorCallback( @@ -323,7 +323,7 @@ public class ActivityStartInterceptorTest { new Intent("android.test.foo"), ActivityOptions.makeBasic().setLaunchDisplayId(3)); - assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); assertEquals("android.test.foo", mInterceptor.mIntent.getAction()); assertEquals(3, mInterceptor.mActivityOptions.getLaunchDisplayId()); } @@ -332,7 +332,7 @@ public class ActivityStartInterceptorTest { public void testInterceptionCallback_singleCallbackReturnsNull() { addMockInterceptorCallback(null, null); - assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertFalse(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); } @Test @@ -340,7 +340,7 @@ public class ActivityStartInterceptorTest { addMockInterceptorCallback(null, null); addMockInterceptorCallback(new Intent("android.test.second"), null); - assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, 0, 0, null)); + assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null)); assertEquals("android.test.second", mInterceptor.mIntent.getAction()); } |