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

Commit 66f1f9e2 authored by Antoan Angelov's avatar Antoan Angelov Committed by Android (Google) Code Review
Browse files

Merge "Launch intent resolver in same profile when used for sharing" into rvc-dev

parents bde97baf eb7793a2
Loading
Loading
Loading
Loading
+2 −20
Original line number Diff line number Diff line
@@ -171,17 +171,6 @@ 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";
@@ -928,15 +917,8 @@ public class ChooserActivity extends ResolverActivity implements
    }

    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 {
        int selectedProfile = getSelectedProfileExtra();
        if (selectedProfile == -1) {
            selectedProfile = getProfileForUser(getUser());
        }
        return selectedProfile;
+68 −14
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.internal.app;

import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;

import static com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE;

import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.Activity;
@@ -26,6 +28,7 @@ import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -74,6 +77,9 @@ public class IntentForwarderActivity extends Activity {

    private static final String TEL_SCHEME = "tel";

    private static final ComponentName RESOLVER_COMPONENT_NAME =
            new ComponentName("android", ResolverActivity.class.getName());

    private Injector mInjector;

    private MetricsLogger mMetricsLogger;
@@ -136,21 +142,50 @@ public class IntentForwarderActivity extends Activity {
        }

        newIntent.prepareToLeaveUser(callingUserId);
        maybeShowDisclosureAsync(intentReceived, newIntent, targetUserId, userMessageId);
        CompletableFuture.runAsync(() ->
                        startActivityAsCaller(newIntent, targetUserId), mExecutorService)
                .thenAcceptAsync(result -> finish(), getApplicationContext().getMainExecutor());
    }

    private void maybeShowDisclosureAsync(
            Intent intentReceived, Intent newIntent, int userId, int messageId) {
        final CompletableFuture<ResolveInfo> resolveInfoFuture =
                mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, userId);
        resolveInfoFuture.thenAcceptAsync(ri -> {
            if (shouldShowDisclosure(ri, intentReceived)) {
        final CompletableFuture<ResolveInfo> targetResolveInfoFuture =
                mInjector.resolveActivityAsUser(newIntent, MATCH_DEFAULT_ONLY, targetUserId);
        targetResolveInfoFuture
                .thenApplyAsync(targetResolveInfo -> {
                    if (isResolverActivityResolveInfo(targetResolveInfo)) {
                        launchResolverActivityWithCorrectTab(intentReceived, className, newIntent,
                                callingUserId, targetUserId);
                        return targetResolveInfo;
                    }
                    startActivityAsCaller(newIntent, targetUserId);
                    return targetResolveInfo;
                }, mExecutorService)
                .thenAcceptAsync(result -> {
                    maybeShowDisclosure(intentReceived, result, userMessageId);
                    finish();
                }, getApplicationContext().getMainExecutor());
    }

    private boolean isIntentForwarderResolveInfo(ResolveInfo resolveInfo) {
        if (resolveInfo == null) {
            return false;
        }
        ActivityInfo activityInfo = resolveInfo.activityInfo;
        if (activityInfo == null) {
            return false;
        }
        if (!"android".equals(activityInfo.packageName)) {
            return false;
        }
        return activityInfo.name.equals(FORWARD_INTENT_TO_PARENT)
                || activityInfo.name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE);
    }

    private boolean isResolverActivityResolveInfo(@Nullable ResolveInfo resolveInfo) {
        return resolveInfo != null
                && resolveInfo.activityInfo != null
                && RESOLVER_COMPONENT_NAME.equals(resolveInfo.activityInfo.getComponentName());
    }

    private void maybeShowDisclosure(
            Intent intentReceived, ResolveInfo resolveInfo, int messageId) {
        if (shouldShowDisclosure(resolveInfo, intentReceived)) {
            mInjector.showToast(messageId, Toast.LENGTH_LONG);
        }
        }, getApplicationContext().getMainExecutor());
    }

    private void startActivityAsCaller(Intent newIntent, int userId) {
@@ -185,7 +220,7 @@ public class IntentForwarderActivity extends Activity {
        // when cross-profile intents are disabled.
        int selectedProfile = findSelectedProfile(className);
        sanitizeIntent(intentReceived);
        intentReceived.putExtra(ChooserActivity.EXTRA_SELECTED_PROFILE, selectedProfile);
        intentReceived.putExtra(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);
@@ -196,6 +231,25 @@ public class IntentForwarderActivity extends Activity {
        finish();
    }

    private void launchResolverActivityWithCorrectTab(Intent intentReceived, String className,
            Intent newIntent, int callingUserId, int targetUserId) {
        // When showing the intent resolver, instead of forwarding to the other profile,
        // we launch it in the current user and select the other tab. This fixes b/155874820.
        //
        // In the case when there are 0 targets in the current profile and >1 apps in the other
        // profile, the package manager launches the intent resolver in the other profile.
        // If that's the case, we launch the resolver in the target user instead (other profile).
        ResolveInfo callingResolveInfo = mInjector.resolveActivityAsUser(
                newIntent, MATCH_DEFAULT_ONLY, callingUserId).join();
        int userId = isIntentForwarderResolveInfo(callingResolveInfo)
                ? targetUserId : callingUserId;
        int selectedProfile = findSelectedProfile(className);
        sanitizeIntent(intentReceived);
        intentReceived.putExtra(EXTRA_SELECTED_PROFILE, selectedProfile);
        startActivityAsCaller(intentReceived, null, null, false, userId);
        finish();
    }

    private int findSelectedProfile(String className) {
        if (className.equals(FORWARD_INTENT_TO_PARENT)) {
            return ChooserActivity.PROFILE_PERSONAL;
+34 −0
Original line number Diff line number Diff line
@@ -179,6 +179,17 @@ public class ResolverActivity extends Activity implements
    // Intent extra for connected audio devices
    public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device";

    /**
     * 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.ResolverActivity.EXTRA_SELECTED_PROFILE";

    static final int PROFILE_PERSONAL = AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
    static final int PROFILE_WORK = AbstractMultiProfilePagerAdapter.PROFILE_WORK;

    private BroadcastReceiver mWorkProfileStateReceiver;
    private UserHandle mHeaderCreatorUser;

@@ -475,6 +486,10 @@ public class ResolverActivity extends Activity implements
                selectedProfile = PROFILE_WORK;
            }
        }
        int selectedProfileExtra = getSelectedProfileExtra();
        if (selectedProfileExtra != -1) {
            selectedProfile = selectedProfileExtra;
        }
        // We only show the default app for the profile of the current user. The filterLastUsed
        // flag determines whether to show a default app and that app is not shown in the
        // resolver list. So filterLastUsed should be false for the other profile.
@@ -511,6 +526,25 @@ public class ResolverActivity extends Activity implements
        return R.style.Theme_DeviceDefault_Resolver;
    }

    /**
     * Returns {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK} if the {@link
     * #EXTRA_SELECTED_PROFILE} extra was supplied, or {@code -1} if no extra was supplied.
     * @throws IllegalArgumentException if the value passed to the {@link #EXTRA_SELECTED_PROFILE}
     * extra is not {@link #PROFILE_PERSONAL} or {@link #PROFILE_WORK}
     */
    int getSelectedProfileExtra() {
        int selectedProfile = -1;
        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 ResolverActivity.PROFILE_PERSONAL or "
                        + "ResolverActivity.PROFILE_WORK.");
            }
        }
        return selectedProfile;
    }

    /**
     * Returns the user id of the user that the starting intent originated from.
     * <p>This is not necessarily equal to {@link #getUserId()} or {@link UserHandle#myUserId()},