From 16406c38d8783ef4353f1348f979c68d553b39df Mon Sep 17 00:00:00 2001 From: Alex Kershaw Date: Mon, 17 Feb 2020 12:28:53 +0000 Subject: [PATCH] CrossProfileApps#startActivity by intent starts in same task by default This is based on developer feedback from Google Calendar. Tweak the API to take in the calling activity. Javadoc in ActivityTaskManagerInternal's new method is copied from the existing method. Bug: 149677845 Bug: 136249261 Test: atest com.android.cts.devicepolicy.CrossProfileAppsHostSideTest#testStartActivityIntent_sameTaskByDefault Change-Id: I2f2d4d8fd82febf4916ba70a08de5e71c678a1f4 --- api/current.txt | 2 +- .../android/content/pm/CrossProfileApps.java | 12 +++++++-- .../android/content/pm/ICrossProfileApps.aidl | 2 +- .../pm/CrossProfileAppsServiceImpl.java | 18 ++++++++++--- .../server/pm/LauncherAppsService.java | 9 ++++--- .../wm/ActivityTaskManagerInternal.java | 3 ++- .../server/wm/ActivityTaskManagerService.java | 5 ++-- .../pm/CrossProfileAppsServiceImplTest.java | 27 +++++++++++++++++++ 8 files changed, 65 insertions(+), 13 deletions(-) diff --git a/api/current.txt b/api/current.txt index c2bbb6d932e63..bb0e43c16ab53 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11563,7 +11563,7 @@ package android.content.pm { method @NonNull public android.graphics.drawable.Drawable getProfileSwitchingIconDrawable(@NonNull android.os.UserHandle); method @NonNull public CharSequence getProfileSwitchingLabel(@NonNull android.os.UserHandle); method @NonNull public java.util.List getTargetUserProfiles(); - method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle); + method @RequiresPermission(anyOf={android.Manifest.permission.INTERACT_ACROSS_PROFILES, "android.permission.INTERACT_ACROSS_USERS"}) public void startActivity(@NonNull android.content.Intent, @NonNull android.os.UserHandle, @Nullable android.app.Activity); method public void startMainActivity(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle); field public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED = "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED"; } diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java index eb1da67972fdd..3261cb124e008 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -19,6 +19,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.app.Activity; import android.app.AppOpsManager.Mode; import android.content.ComponentName; import android.content.Context; @@ -116,18 +117,25 @@ public class CrossProfileApps { * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by * {@link #getTargetUserProfiles()} if different to the calling user, otherwise a * {@link SecurityException} will be thrown. + * @param callingActivity The activity to start the new activity from for the purposes of + * deciding which task the new activity should belong to. If {@code null}, the activity + * will always be started in a new task. */ @RequiresPermission(anyOf = { android.Manifest.permission.INTERACT_ACROSS_PROFILES, android.Manifest.permission.INTERACT_ACROSS_USERS}) - public void startActivity(@NonNull Intent intent, @NonNull UserHandle targetUser) { + public void startActivity( + @NonNull Intent intent, + @NonNull UserHandle targetUser, + @Nullable Activity callingActivity) { try { mService.startActivityAsUserByIntent( mContext.getIApplicationThread(), mContext.getPackageName(), mContext.getFeatureId(), intent, - targetUser.getIdentifier()); + targetUser.getIdentifier(), + callingActivity != null ? callingActivity.getActivityToken() : null); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl index 98bf2ddd0e1b8..5a6e008608f31 100644 --- a/core/java/android/content/pm/ICrossProfileApps.aidl +++ b/core/java/android/content/pm/ICrossProfileApps.aidl @@ -31,7 +31,7 @@ interface ICrossProfileApps { in String callingFeatureId, in ComponentName component, int userId, boolean launchMainActivity); void startActivityAsUserByIntent(in IApplicationThread caller, in String callingPackage, - in String callingFeatureId, in Intent intent, int userId); + in String callingFeatureId, in Intent intent, int userId, in IBinder callingActivity); List getTargetUserProfiles(in String callingPackage); boolean canInteractAcrossProfiles(in String callingPackage); boolean canRequestInteractAcrossProfiles(in String callingPackage); diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java index 3939f2642bc81..a83102552ae4e 100644 --- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java @@ -45,6 +45,7 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Binder; +import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -167,6 +168,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { launchIntent.setComponent(component); mInjector.getActivityTaskManagerInternal().startActivityAsUser( caller, callingPackage, callingFeatureId, launchIntent, + /* resultTo= */ null, + Intent.FLAG_ACTIVITY_NEW_TASK, launchMainActivity ? ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle() : null, @@ -179,7 +182,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { String callingPackage, String callingFeatureId, Intent intent, - @UserIdInt int userId) throws RemoteException { + @UserIdInt int userId, + IBinder callingActivity) throws RemoteException { Objects.requireNonNull(callingPackage); Objects.requireNonNull(intent); Objects.requireNonNull(intent.getComponent(), "The intent must have a Component set"); @@ -214,8 +218,16 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { verifyActivityCanHandleIntent(launchIntent, callingUid, userId); - mInjector.getActivityTaskManagerInternal().startActivityAsUser(caller, callingPackage, - callingFeatureId, launchIntent, /* options= */ null, userId); + mInjector.getActivityTaskManagerInternal() + .startActivityAsUser( + caller, + callingPackage, + callingFeatureId, + launchIntent, + callingActivity, + /* startFlags= */ 0, + /* options= */ null, + userId); logStartActivityByIntent(callingPackage); } diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index f93c663c551c1..3a162173a59fc 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -896,7 +896,8 @@ public class LauncherAppsService extends SystemService { i.setSourceBounds(sourceBounds); mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, - callingFeatureId, i, opts, userId); + callingFeatureId, i, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK, opts, + userId); } @Override @@ -955,7 +956,8 @@ public class LauncherAppsService extends SystemService { Binder.restoreCallingIdentity(ident); } mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, - callingFeatureId, launchIntent, opts, user.getIdentifier()); + callingFeatureId, launchIntent, /* resultTo= */ null, + Intent.FLAG_ACTIVITY_NEW_TASK, opts, user.getIdentifier()); } @Override @@ -978,7 +980,8 @@ public class LauncherAppsService extends SystemService { Binder.restoreCallingIdentity(ident); } mActivityTaskManagerInternal.startActivityAsUser(caller, callingPackage, - callingFeatureId, intent, opts, user.getIdentifier()); + callingFeatureId, intent, /* resultTo= */ null, Intent.FLAG_ACTIVITY_NEW_TASK, + opts, user.getIdentifier()); } /** Checks if user is a profile of or same as listeningUser. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index 7302e529c1ebe..6522294bd083d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -231,7 +231,8 @@ public abstract class ActivityTaskManagerInternal { * @return error codes used by {@link IActivityManager#startActivity} and its siblings. */ public abstract int startActivityAsUser(IApplicationThread caller, String callingPackage, - @Nullable String callingFeatureId, Intent intent, @Nullable Bundle options, int userId); + @Nullable String callingFeatureId, Intent intent, @Nullable IBinder resultTo, + int startFlags, @Nullable Bundle options, int userId); /** * Called when Keyguard flags might have changed. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f777e909510d0..882d5c70de25a 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -6254,11 +6254,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public int startActivityAsUser(IApplicationThread caller, String callerPackage, - @Nullable String callerFeatureId, Intent intent, Bundle options, int userId) { + @Nullable String callerFeatureId, Intent intent, @Nullable IBinder resultTo, + int startFlags, Bundle options, int userId) { return ActivityTaskManagerService.this.startActivityAsUser( caller, callerPackage, callerFeatureId, intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options, userId, + resultTo, null, 0, startFlags, null, options, userId, false /*validateIncomingUser*/); } diff --git a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java index 3708571dbdcfd..e79b5af32b195 100644 --- a/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java @@ -31,6 +31,7 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.os.Bundle; +import android.os.IBinder; import android.os.UserHandle; import android.os.UserManager; import android.platform.test.annotations.Presubmit; @@ -237,6 +238,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -260,6 +263,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -285,6 +290,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -310,6 +317,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -333,6 +342,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -356,6 +367,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -381,6 +394,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -411,6 +426,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -434,6 +451,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -457,6 +476,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -480,6 +501,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -503,6 +526,8 @@ public class CrossProfileAppsServiceImplTest { anyString(), nullable(String.class), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), anyInt()); } @@ -525,6 +550,8 @@ public class CrossProfileAppsServiceImplTest { eq(PACKAGE_ONE), eq(FEATURE_ID), any(Intent.class), + nullable(IBinder.class), + anyInt(), nullable(Bundle.class), eq(PRIMARY_USER)); }