diff options
10 files changed, 68 insertions, 57 deletions
diff --git a/api/current.txt b/api/current.txt index 50b054070919..ea49420cdb65 100644 --- a/api/current.txt +++ b/api/current.txt @@ -11298,7 +11298,7 @@ package android.content.pm.crossprofile { method public android.graphics.drawable.Drawable getProfileSwitchingIcon(android.os.UserHandle); method public java.lang.CharSequence getProfileSwitchingLabel(android.os.UserHandle); method public java.util.List<android.os.UserHandle> getTargetUserProfiles(); - method public void startMainActivity(android.content.ComponentName, android.os.UserHandle, android.graphics.Rect, android.os.Bundle); + method public void startMainActivity(android.content.ComponentName, android.os.UserHandle); } } diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index 4a21f5c424d5..e61c5b7c78a1 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -36,6 +36,7 @@ import android.os.IRemoteCallback; import android.os.Parcelable; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.UserHandle; import android.transition.Transition; import android.transition.TransitionListenerAdapter; import android.transition.TransitionManager; @@ -265,6 +266,8 @@ public class ActivityOptions { public static final int ANIM_CUSTOM_IN_PLACE = 10; /** @hide */ public static final int ANIM_CLIP_REVEAL = 11; + /** @hide */ + public static final int ANIM_OPEN_CROSS_PROFILE_APPS = 12; private String mPackageName; private Rect mLaunchBounds; @@ -486,6 +489,19 @@ public class ActivityOptions { } /** + * Creates an {@link ActivityOptions} object specifying an animation where the new activity + * is started in another user profile by calling {@link + * android.content.pm.crossprofile.CrossProfileApps#startMainActivity(ComponentName, UserHandle) + * }. + * @hide + */ + public static ActivityOptions makeOpenCrossProfileAppsAnimation() { + ActivityOptions options = new ActivityOptions(); + options.mAnimationType = ANIM_OPEN_CROSS_PROFILE_APPS; + return options; + } + + /** * Create an ActivityOptions specifying an animation where a thumbnail * is scaled from a given position to the new activity window that is * being started. diff --git a/core/java/android/content/pm/crossprofile/CrossProfileApps.java b/core/java/android/content/pm/crossprofile/CrossProfileApps.java index c9f184a7da53..414c13894f80 100644 --- a/core/java/android/content/pm/crossprofile/CrossProfileApps.java +++ b/core/java/android/content/pm/crossprofile/CrossProfileApps.java @@ -16,7 +16,6 @@ package android.content.pm.crossprofile; import android.annotation.NonNull; -import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -61,15 +60,10 @@ public class CrossProfileApps { * @param user The UserHandle of the profile, must be one of the users returned by * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will * be thrown. - * @param sourceBounds The Rect containing the source bounds of the clicked icon, see - * {@link android.content.Intent#setSourceBounds(Rect)}. - * @param startActivityOptions Options to pass to startActivity */ - public void startMainActivity(@NonNull ComponentName component, @NonNull UserHandle user, - @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) { + public void startMainActivity(@NonNull ComponentName component, @NonNull UserHandle user) { try { - mService.startActivityAsUser(mContext.getPackageName(), - component, sourceBounds, startActivityOptions, user); + mService.startActivityAsUser(mContext.getPackageName(), component, user); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl b/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl index dd8d04f6cf0e..227f91f5d3e1 100644 --- a/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl +++ b/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl @@ -26,6 +26,7 @@ import android.os.UserHandle; * @hide */ interface ICrossProfileApps { - void startActivityAsUser(in String callingPackage, in ComponentName component, in Rect sourceBounds, in Bundle startActivityOptions, in UserHandle user); + void startActivityAsUser(in String callingPackage, in ComponentName component, + in UserHandle user); List<UserHandle> getTargetUserProfiles(in String callingPackage); }
\ No newline at end of file diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4b2424ffd213..63882e423fce 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1573,6 +1573,8 @@ <java-symbol type="anim" name="voice_activity_close_enter" /> <java-symbol type="anim" name="voice_activity_open_exit" /> <java-symbol type="anim" name="voice_activity_open_enter" /> + <java-symbol type="anim" name="activity_open_exit" /> + <java-symbol type="anim" name="activity_open_enter" /> <java-symbol type="array" name="config_autoRotationTiltTolerance" /> <java-symbol type="array" name="config_keyboardTapVibePattern" /> diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 69f6d5eef275..8eb519797641 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -23,6 +23,7 @@ import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; import static android.app.ActivityOptions.ANIM_CUSTOM; import static android.app.ActivityOptions.ANIM_SCALE_UP; import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION; +import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN; import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP; import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; @@ -1476,6 +1477,9 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } break; + case ANIM_OPEN_CROSS_PROFILE_APPS: + service.mWindowManager.overridePendingAppTransitionStartCrossProfileApps(); + break; default: Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType); break; diff --git a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java index 854b70439d56..d6281c51b3fa 100644 --- a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java +++ b/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java @@ -19,6 +19,7 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE; import android.annotation.UserIdInt; +import android.app.ActivityOptions; import android.app.AppOpsManager; import android.content.ComponentName; import android.content.Context; @@ -74,8 +75,6 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { public void startActivityAsUser( String callingPackage, ComponentName component, - Rect sourceBounds, - Bundle startActivityOptions, UserHandle user) throws RemoteException { Preconditions.checkNotNull(callingPackage); Preconditions.checkNotNull(component); @@ -103,7 +102,6 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { // CATEGORY_LAUNCHER as calling startActivityAsUser ignore them if component is present. final Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); - launchIntent.setSourceBounds(sourceBounds); launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); // Only package name is set here, as opposed to component name, because intent action and @@ -114,7 +112,8 @@ public class CrossProfileAppsServiceImpl extends ICrossProfileApps.Stub { final long ident = mInjector.clearCallingIdentity(); try { launchIntent.setComponent(component); - mContext.startActivityAsUser(launchIntent, startActivityOptions, user); + mContext.startActivityAsUser(launchIntent, + ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(), user); } finally { mInjector.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index c2cbced2311c..4a74e295c8fc 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -44,17 +44,17 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIO import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerInternal.AppTransitionListener; +import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; -import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.proto.AppTransitionProto.APP_TRANSITION_STATE; import static com.android.server.wm.proto.AppTransitionProto.LAST_USED_APP_TRANSITION; import android.annotation.Nullable; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; -import android.graphics.Bitmap; import android.graphics.GraphicBuffer; import android.graphics.Path; import android.graphics.Rect; @@ -64,6 +64,7 @@ import android.os.IBinder; import android.os.IRemoteCallback; import android.os.RemoteException; import android.os.SystemProperties; +import android.os.UserHandle; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; @@ -199,6 +200,13 @@ public class AppTransition implements Dump { private static final int NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN = 6; private static final int NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE = 7; private static final int NEXT_TRANSIT_TYPE_CLIP_REVEAL = 8; + + /** + * Refers to the transition to activity started by using {@link + * android.content.pm.crossprofile.CrossProfileApps#startMainActivity(ComponentName, UserHandle) + * }. + */ + private static final int NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS = 9; private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE; // These are the possible states for the enter/exit activities during a thumbnail transition @@ -1605,6 +1613,17 @@ public class AppTransition implements Dump { + " transit=" + appTransitionToString(transit) + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } + } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS + && (transit == TRANSIT_ACTIVITY_OPEN + || transit == TRANSIT_TASK_OPEN + || transit == TRANSIT_TASK_TO_FRONT)) { + a = loadAnimationRes("android", enter + ? com.android.internal.R.anim.activity_open_enter + : com.android.internal.R.anim.activity_open_exit); + Slog.v(TAG, + "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:" + + " anim=" + a + " transit=" + appTransitionToString(transit) + + " isEntrance=" + enter + " Callers=" + Debug.getCallers(3)); } else { int animAttr = 0; switch (transit) { @@ -1833,6 +1852,17 @@ public class AppTransition implements Dump { } /** + * @see {@link #NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS} + */ + void overridePendingAppTransitionStartCrossProfileApps() { + if (isTransitionSet()) { + clear(); + mNextAppTransitionType = NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS; + postAnimationCallback(); + } + } + + /** * If a future is set for the app transition specs, fetch it in another thread. */ private void fetchAppTransitionSpecsFromFuture() { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 9fc9f3c15cfc..58a5ca498291 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2706,6 +2706,12 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void overridePendingAppTransitionStartCrossProfileApps() { + synchronized (mWindowMap) { + mAppTransition.overridePendingAppTransitionStartCrossProfileApps(); + } + } + void prolongAnimationsFromSpecs(@NonNull AppTransitionAnimationSpec[] specs, boolean scaleUp) { // This is used by freeform <-> recents windows transition. We need to synchronize // the animation with the appearance of the content of recents, so we will make diff --git a/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java index 880b77ed81da..ff55a2ba120b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java @@ -205,8 +205,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_ONE, ACTIVITY_COMPONENT, - null, - null, UserHandle.of(PRIMARY_USER))); verify(mContext, never()) @@ -217,33 +215,6 @@ public class CrossProfileAppsServiceImplTest { } @Test - public void startActivityAsUser_profile_successWithOption() throws Exception { - Bundle options = Bundle.forPair("test_key", "test_value"); - - mCrossProfileAppsServiceImpl.startActivityAsUser( - PACKAGE_ONE, - ACTIVITY_COMPONENT, - null, - options, - UserHandle.of(PROFILE_OF_PRIMARY_USER)); - - ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); - ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); - - verify(mContext) - .startActivityAsUser( - intentCaptor.capture(), - bundleCaptor.capture(), - eq(UserHandle.of(PROFILE_OF_PRIMARY_USER))); - - Intent intent = intentCaptor.getValue(); - assertEquals(ACTIVITY_COMPONENT, intent.getComponent()); - - Bundle bundle = bundleCaptor.getValue(); - assertEquals("test_value", bundle.getString("test_key")); - } - - @Test public void startActivityAsUser_profile_notInstalled() throws Exception { mockAppsInstalled(PACKAGE_ONE, PROFILE_OF_PRIMARY_USER, false); @@ -253,8 +224,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_ONE, ACTIVITY_COMPONENT, - null, - null, UserHandle.of(PROFILE_OF_PRIMARY_USER))); verify(mContext, never()) @@ -272,8 +241,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_TWO, ACTIVITY_COMPONENT, - null, - null, UserHandle.of(PROFILE_OF_PRIMARY_USER))); verify(mContext, never()) @@ -293,8 +260,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_ONE, ACTIVITY_COMPONENT, - null, - null, UserHandle.of(PROFILE_OF_PRIMARY_USER))); verify(mContext, never()) @@ -312,8 +277,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_ONE, new ComponentName(PACKAGE_TWO, "test"), - null, - null, UserHandle.of(PROFILE_OF_PRIMARY_USER))); verify(mContext, never()) @@ -331,8 +294,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_ONE, ACTIVITY_COMPONENT, - null, - null, UserHandle.of(SECONDARY_USER))); verify(mContext, never()) @@ -349,8 +310,6 @@ public class CrossProfileAppsServiceImplTest { mCrossProfileAppsServiceImpl.startActivityAsUser( PACKAGE_ONE, ACTIVITY_COMPONENT, - null, - null, UserHandle.of(PRIMARY_USER)); verify(mContext) |