diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index c82ab6c79e9db..3e7f24b034ac3 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -169,6 +169,17 @@ public class ChooserActivity extends ResolverActivity implements public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP"; + /** + * Integer extra to indicate which profile should be automatically selected. + *

Can only be used if there is a work profile. + *

Possible values can be either {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}. + */ + static final String EXTRA_SELECTED_PROFILE = + "com.android.internal.app.ChooserActivity.EXTRA_SELECTED_PROFILE"; + + static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL; + static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK; + private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions"; private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label"; @@ -860,15 +871,31 @@ public class ChooserActivity extends ResolverActivity implements filterLastUsed, mUseLayoutForBrowsables, /* userHandle */ getWorkProfileUserHandle()); + int selectedProfile = findSelectedProfile(); return new ChooserMultiProfilePagerAdapter( /* context */ this, personalAdapter, workAdapter, - /* defaultProfile */ getCurrentProfile(), + selectedProfile, getPersonalProfileUserHandle(), getWorkProfileUserHandle()); } + private int findSelectedProfile() { + int selectedProfile; + if (getIntent().hasExtra(EXTRA_SELECTED_PROFILE)) { + selectedProfile = getIntent().getIntExtra(EXTRA_SELECTED_PROFILE, /* defValue = */ -1); + if (selectedProfile != PROFILE_PERSONAL && selectedProfile != PROFILE_WORK) { + throw new IllegalArgumentException(EXTRA_SELECTED_PROFILE + " has invalid value " + + selectedProfile + ". Must be either ChooserActivity.PROFILE_PERSONAL or " + + "ChooserActivity.PROFILE_WORK."); + } + } else { + selectedProfile = getProfileForUser(getUser()); + } + return selectedProfile; + } + @Override protected boolean postRebuildList(boolean rebuildCompleted) { updateStickyContentPreview(); @@ -2479,7 +2506,10 @@ public class ChooserActivity extends ResolverActivity implements gridAdapter.getMaxTargetsPerRow()); } - if (mChooserMultiProfilePagerAdapter.getCurrentUserHandle() != getUser()) { + UserHandle currentUserHandle = mChooserMultiProfilePagerAdapter.getCurrentUserHandle(); + int currentProfile = getProfileForUser(currentUserHandle); + int initialProfile = findSelectedProfile(); + if (currentProfile != initialProfile) { return; } @@ -2576,6 +2606,19 @@ public class ChooserActivity extends ResolverActivity implements } } + /** + * Returns {@link #PROFILE_PERSONAL}, {@link #PROFILE_WORK}, or -1 if the given user handle + * does not match either the personal or work user handle. + **/ + private int getProfileForUser(UserHandle currentUserHandle) { + if (currentUserHandle == getPersonalProfileUserHandle()) { + return PROFILE_PERSONAL; + } else if (currentUserHandle == getWorkProfileUserHandle()) { + return PROFILE_WORK; + } + return -1; + } + private ViewGroup getCurrentEmptyStateView() { int currentPage = mChooserMultiProfilePagerAdapter.getCurrentPage(); return mChooserMultiProfilePagerAdapter.getItem(currentPage).getEmptyStateView(); diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 9bdfa4ad4e438..36eecfb685e8f 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -108,20 +108,16 @@ public class IntentForwarderActivity extends Activity { finish(); return; } + if (Intent.ACTION_CHOOSER.equals(intentReceived.getAction())) { + launchChooserActivityWithCorrectTab(intentReceived, className); + return; + } final int callingUserId = getUserId(); final Intent newIntent = canForward(intentReceived, getUserId(), targetUserId, mInjector.getIPackageManager(), getContentResolver()); if (newIntent != null) { - if (Intent.ACTION_CHOOSER.equals(newIntent.getAction())) { - Intent innerIntent = newIntent.getParcelableExtra(Intent.EXTRA_INTENT); - // At this point, innerIntent is not null. Otherwise, canForward would have returned - // false. - innerIntent.prepareToLeaveUser(callingUserId); - innerIntent.fixUris(callingUserId); - } else { - newIntent.prepareToLeaveUser(callingUserId); - } + newIntent.prepareToLeaveUser(callingUserId); final ResolveInfo ri = mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId); @@ -153,6 +149,33 @@ public class IntentForwarderActivity extends Activity { finish(); } + private void launchChooserActivityWithCorrectTab(Intent intentReceived, String className) { + // When showing the sharesheet, instead of forwarding to the other profile, + // we launch the sharesheet in the current user and select the other tab. + // This fixes b/152866292 where the user can not go back to the original profile + // when cross-profile intents are disabled. + int selectedProfile = findSelectedProfile(className); + sanitizeIntent(intentReceived); + intentReceived.putExtra(ChooserActivity.EXTRA_SELECTED_PROFILE, selectedProfile); + Intent innerIntent = intentReceived.getParcelableExtra(Intent.EXTRA_INTENT); + if (innerIntent == null) { + Slog.wtf(TAG, "Cannot start a chooser intent with no extra " + Intent.EXTRA_INTENT); + return; + } + sanitizeIntent(innerIntent); + startActivity(intentReceived); + finish(); + } + + private int findSelectedProfile(String className) { + if (className.equals(FORWARD_INTENT_TO_PARENT)) { + return ChooserActivity.PROFILE_PERSONAL; + } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { + return ChooserActivity.PROFILE_WORK; + } + return -1; + } + private boolean shouldShowDisclosure(@Nullable ResolveInfo ri, Intent intent) { if (!isDeviceProvisioned()) { return false; diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java index 8cf146ea801d2..769c578356628 100644 --- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java @@ -213,13 +213,9 @@ public class IntentForwarderActivityTest { } @Test - public void forwardToManagedProfile_canForward_chooserIntent() throws Exception { + public void launchInSameProfile_chooserIntent() { sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME; - // Intent can be forwarded. - when(mIPm.canForwardTo( - any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true); - // Manage profile exists. List profiles = new ArrayList<>(); profiles.add(CURRENT_USER_INFO); @@ -235,10 +231,6 @@ public class IntentForwarderActivityTest { intent.putExtra(Intent.EXTRA_INTENT, sendIntent); IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent); - ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mIPm).canForwardTo(intentCaptor.capture(), eq(TYPE_PLAIN_TEXT), anyInt(), anyInt()); - assertEquals(Intent.ACTION_SEND, intentCaptor.getValue().getAction()); - assertNotNull(activity.mStartActivityIntent); assertEquals(Intent.ACTION_CHOOSER, activity.mStartActivityIntent.getAction()); assertNull(activity.mStartActivityIntent.getPackage()); @@ -249,9 +241,9 @@ public class IntentForwarderActivityTest { assertEquals(Intent.ACTION_SEND, innerIntent.getAction()); assertNull(innerIntent.getComponent()); assertNull(innerIntent.getPackage()); - assertEquals(CURRENT_USER_INFO.id, innerIntent.getContentUserHint()); + assertEquals(UserHandle.USER_CURRENT, innerIntent.getContentUserHint()); - assertEquals(MANAGED_PROFILE_INFO.id, activity.mUserIdActivityLaunchedIn); + assertEquals(CURRENT_USER_INFO.id, activity.mUserIdActivityLaunchedIn); } @Test @@ -655,6 +647,12 @@ public class IntentForwarderActivityTest { mUserIdActivityLaunchedIn = userId; } + @Override + public void startActivity(Intent intent) { + mStartActivityIntent = intent; + mUserIdActivityLaunchedIn = getUserId(); + } + @Override protected MetricsLogger getMetricsLogger() { return mMetricsLogger;