Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7581390 authored by arangelov's avatar arangelov
Browse files

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
parent 7eb72faa
Loading
Loading
Loading
Loading
+45 −2
Original line number Diff line number Diff line
@@ -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();
+32 −9
Original line number Diff line number Diff line
@@ -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);
            }

            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;
+9 −11
Original line number Diff line number Diff line
@@ -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;