summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java52
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java22
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());
}