Start sharesheet in the same profile instead of switching to other profile.
Instead of starting the sharesheet in the other profile when choosing the "Switch to work"/"Switch to personal" button, we now start the sharesheet in the same profile with the other tab selected. For example, we're in the personal profile and share something via an app that uses its own sharing logic. That shows the "Switch to work" button and when we press it, we now start the sharesheet in the personal profile with the work tab selected. The reason for this is to avoid user confusion when they go back to the personal tab and it shows an empty state screen due to lack of cross-profile intents. Fixes: 152866292 Test: manual Test: atest ChooserActivityTest Test: atest ResolverActivityTest Test: atest IntentForwarderActivityTest#launchInSameProfile_chooserIntent Change-Id: Ic117c9c51c663b6574e7692022bac82f7c899ec2
This commit is contained in:
@@ -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.
|
||||
* <p>Can only be used if there is a work profile.
|
||||
* <p>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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<UserInfo> 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<Intent> 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;
|
||||
|
||||
Reference in New Issue
Block a user