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

Commit b8362e90 authored by Himanshu Gupta's avatar Himanshu Gupta
Browse files

App Cloning fixes for Sharesheet

This Cl adds the following:
1. Fixes a bug where if a cloned app has initialIntents and launches sharesheet,
   initialIntents would always resolve in user 0 (personalProfileHandle) instead
   of clonedProfileHandle
2. TODOs mentioned in ag/20982903 addressed.
3. Test cases added.

Test: atest ChooserActivityTest, atest ResolverActivityTest
Change-Id: Iedb24d8775d08319b136d96d7ffff1665a1b0748
parent 2aebeda4
Loading
Loading
Loading
Loading
+11 −6
Original line number Original line Diff line number Diff line
@@ -2525,8 +2525,7 @@ public class ChooserActivity extends ResolverActivity implements
            List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
            List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
            boolean filterLastUsed, UserHandle userHandle) {
            boolean filterLastUsed, UserHandle userHandle) {
        ChooserListAdapter chooserListAdapter = createChooserListAdapter(context, payloadIntents,
        ChooserListAdapter chooserListAdapter = createChooserListAdapter(context, payloadIntents,
                initialIntents, rList, filterLastUsed,
                initialIntents, rList, filterLastUsed, userHandle);
                createListController(userHandle));
        AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
        AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
        AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
        AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
        chooserListAdapter.setAppPredictor(appPredictor);
        chooserListAdapter.setAppPredictor(appPredictor);
@@ -2536,12 +2535,18 @@ public class ChooserActivity extends ResolverActivity implements


    @VisibleForTesting
    @VisibleForTesting
    public ChooserListAdapter createChooserListAdapter(Context context,
    public ChooserListAdapter createChooserListAdapter(Context context,
            List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
            List<Intent> payloadIntents,
            boolean filterLastUsed, ResolverListController resolverListController) {
            Intent[] initialIntents,
            List<ResolveInfo> rList,
            boolean filterLastUsed,
            UserHandle userHandle) {
        UserHandle initialIntentsUserSpace = isLaunchedAsCloneProfile()
                && userHandle.equals(getPersonalProfileUserHandle())
                ? getCloneProfileUserHandle() : userHandle;
        return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
        return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
                filterLastUsed, resolverListController, this,
                filterLastUsed, createListController(userHandle), this,
                this, context.getPackageManager(),
                this, context.getPackageManager(),
                getChooserActivityLogger());
                getChooserActivityLogger(), initialIntentsUserSpace);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
+12 −3
Original line number Original line Diff line number Diff line
@@ -105,6 +105,9 @@ public class ChooserListAdapter extends ResolverListAdapter {
    private AppPredictor mAppPredictor;
    private AppPredictor mAppPredictor;
    private AppPredictor.Callback mAppPredictorCallback;
    private AppPredictor.Callback mAppPredictorCallback;


    // Represents the UserSpace in which the Initial Intents should be resolved.
    private final UserHandle mInitialIntentsUserSpace;

    // For pinned direct share labels, if the text spans multiple lines, the TextView will consume
    // For pinned direct share labels, if the text spans multiple lines, the TextView will consume
    // the full width, even if the characters actually take up less than that. Measure the actual
    // the full width, even if the characters actually take up less than that. Measure the actual
    // line widths and constrain the View's width based upon that so that the pin doesn't end up
    // line widths and constrain the View's width based upon that so that the pin doesn't end up
@@ -142,11 +145,12 @@ public class ChooserListAdapter extends ResolverListAdapter {
            ChooserListCommunicator chooserListCommunicator,
            ChooserListCommunicator chooserListCommunicator,
            SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
            SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
            PackageManager packageManager,
            PackageManager packageManager,
            ChooserActivityLogger chooserActivityLogger) {
            ChooserActivityLogger chooserActivityLogger,
            UserHandle initialIntentsUserSpace) {
        // Don't send the initial intents through the shared ResolverActivity path,
        // Don't send the initial intents through the shared ResolverActivity path,
        // we want to separate them into a different section.
        // we want to separate them into a different section.
        super(context, payloadIntents, null, rList, filterLastUsed,
        super(context, payloadIntents, null, rList, filterLastUsed,
                resolverListController, chooserListCommunicator, false);
                resolverListController, chooserListCommunicator, false, initialIntentsUserSpace);


        mMaxShortcutTargetsPerApp =
        mMaxShortcutTargetsPerApp =
                context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp);
                context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp);
@@ -154,6 +158,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
        createPlaceHolders();
        createPlaceHolders();
        mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator;
        mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator;
        mChooserActivityLogger = chooserActivityLogger;
        mChooserActivityLogger = chooserActivityLogger;
        mInitialIntentsUserSpace = initialIntentsUserSpace;


        if (initialIntents != null) {
        if (initialIntents != null) {
            for (int i = 0; i < initialIntents.length; i++) {
            for (int i = 0; i < initialIntents.length; i++) {
@@ -197,7 +202,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
                    ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                    ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                    ri.icon = li.getIconResource();
                    ri.icon = li.getIconResource();
                    ri.iconResourceId = ri.icon;
                    ri.iconResourceId = ri.icon;
                    ri.userHandle = getUserHandle();
                    ri.userHandle = mInitialIntentsUserSpace;
                }
                }
                if (userManager.isManagedProfile()) {
                if (userManager.isManagedProfile()) {
                    ri.noResourceId = true;
                    ri.noResourceId = true;
@@ -351,6 +356,10 @@ public class ChooserListAdapter extends ResolverListAdapter {
                // Consolidate multiple targets from same app.
                // Consolidate multiple targets from same app.
                Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
                Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
                for (DisplayResolveInfo info : allTargets) {
                for (DisplayResolveInfo info : allTargets) {
                    if (info.getResolveInfo().userHandle == null) {
                        Log.e(TAG, "ResolveInfo with null UserHandle found: "
                                + info.getResolveInfo());
                    }
                    String resolvedTarget = info.getResolvedComponentName().getPackageName()
                    String resolvedTarget = info.getResolvedComponentName().getPackageName()
                            + '#' + info.getDisplayLabel()
                            + '#' + info.getDisplayLabel()
                            + '#' + ResolverActivity.getResolveInfoUserHandle(
                            + '#' + ResolverActivity.getResolveInfoUserHandle(
+28 −15
Original line number Original line Diff line number Diff line
@@ -33,6 +33,8 @@ import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_S
import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;


import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED;

import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StringRes;
import android.annotation.UiThread;
import android.annotation.UiThread;
@@ -780,7 +782,7 @@ public class ResolverActivity extends Activity implements
        return getCloneProfileUserHandle() != null;
        return getCloneProfileUserHandle() != null;
    }
    }


    private boolean isLaunchedAsCloneProfile() {
    protected final boolean isLaunchedAsCloneProfile() {
        return hasCloneProfile()
        return hasCloneProfile()
                && (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier());
                && (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier());
    }
    }
@@ -1517,9 +1519,7 @@ public class ResolverActivity extends Activity implements
        safelyStartActivityAsUser(cti, user, null);
        safelyStartActivityAsUser(cti, user, null);
    }
    }


    // TODO: Make method public final.
    protected final void safelyStartActivityAsUser(
    @VisibleForTesting
    protected void safelyStartActivityAsUser(
            TargetInfo cti, UserHandle user, @Nullable Bundle options) {
            TargetInfo cti, UserHandle user, @Nullable Bundle options) {
        // We're dispatching intents that might be coming from legacy apps, so
        // We're dispatching intents that might be coming from legacy apps, so
        // don't kill ourselves.
        // don't kill ourselves.
@@ -1609,9 +1609,12 @@ public class ResolverActivity extends Activity implements
        Intent startIntent = getIntent();
        Intent startIntent = getIntent();
        boolean isAudioCaptureDevice =
        boolean isAudioCaptureDevice =
                startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false);
                startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false);
        UserHandle initialIntentsUserSpace = isLaunchedAsCloneProfile()
                && userHandle.equals(getPersonalProfileUserHandle())
                ? getCloneProfileUserHandle() : userHandle;
        return new ResolverListAdapter(context, payloadIntents, initialIntents, rList,
        return new ResolverListAdapter(context, payloadIntents, initialIntents, rList,
                filterLastUsed, createListController(userHandle), this,
                filterLastUsed, createListController(userHandle), this,
                isAudioCaptureDevice);
                isAudioCaptureDevice, initialIntentsUserSpace);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -2535,20 +2538,18 @@ public class ResolverActivity extends Activity implements
        return queryIntentsUser;
        return queryIntentsUser;
    }
    }


    /**
     * This function is temporary in nature, and its usages will be replaced with just
     * resolveInfo.userHandle, once it is available, once sharesheet is stable.
     */
    public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo,
            UserHandle predictedHandle) {
        return resolveInfo.userHandle;
    }

    /**
    /**
     * Returns the {@link List} of {@link UserHandle} to pass on to the
     * Returns the {@link List} of {@link UserHandle} to pass on to the
     * {@link ResolverRankerServiceResolverComparator} as per the provided {@code userHandle}.
     * {@link ResolverRankerServiceResolverComparator} as per the provided {@code userHandle}.
     */
     */
    protected final List<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
    @VisibleForTesting(visibility = PROTECTED)
    public final List<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
        return getResolverRankerServiceUserHandleListInternal(userHandle);
    }

    @VisibleForTesting
    protected List<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
            userHandle) {
        List<UserHandle> userList = new ArrayList<>();
        List<UserHandle> userList = new ArrayList<>();
        userList.add(userHandle);
        userList.add(userHandle);
        // Add clonedProfileUserHandle to the list only if we are:
        // Add clonedProfileUserHandle to the list only if we are:
@@ -2560,4 +2561,16 @@ public class ResolverActivity extends Activity implements
        }
        }
        return userList;
        return userList;
    }
    }

    /**
     * This function is temporary in nature, and its usages will be replaced with just
     * resolveInfo.userHandle, once it is available, once sharesheet is stable.
     */
    public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo,
            UserHandle predictedHandle) {
        if (resolveInfo.userHandle == null) {
            Log.e(TAG, "ResolveInfo with null UserHandle found: " + resolveInfo);
        }
        return resolveInfo.userHandle;
    }
}
}
+10 −2
Original line number Original line Diff line number Diff line
@@ -91,13 +91,16 @@ public class ResolverListAdapter extends BaseAdapter {
    private boolean mIsTabLoaded;
    private boolean mIsTabLoaded;
    private final Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();
    private final Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();
    private final Map<DisplayResolveInfo, LoadLabelTask> mLabelLoaders = new HashMap<>();
    private final Map<DisplayResolveInfo, LoadLabelTask> mLabelLoaders = new HashMap<>();
    // Represents the UserSpace in which the Initial Intents should be resolved.
    private final UserHandle mInitialIntentsUserSpace;


    public ResolverListAdapter(Context context, List<Intent> payloadIntents,
    public ResolverListAdapter(Context context, List<Intent> payloadIntents,
            Intent[] initialIntents, List<ResolveInfo> rList,
            Intent[] initialIntents, List<ResolveInfo> rList,
            boolean filterLastUsed,
            boolean filterLastUsed,
            ResolverListController resolverListController,
            ResolverListController resolverListController,
            ResolverListCommunicator resolverListCommunicator,
            ResolverListCommunicator resolverListCommunicator,
            boolean isAudioCaptureDevice) {
            boolean isAudioCaptureDevice,
            UserHandle initialIntentsUserSpace) {
        mContext = context;
        mContext = context;
        mIntents = payloadIntents;
        mIntents = payloadIntents;
        mInitialIntents = initialIntents;
        mInitialIntents = initialIntents;
@@ -111,6 +114,11 @@ public class ResolverListAdapter extends BaseAdapter {
        mIsAudioCaptureDevice = isAudioCaptureDevice;
        mIsAudioCaptureDevice = isAudioCaptureDevice;
        final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
        final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
        mIconDpi = am.getLauncherLargeIconDensity();
        mIconDpi = am.getLauncherLargeIconDensity();
        mInitialIntentsUserSpace = initialIntentsUserSpace;
    }

    public ResolverListController getResolverListController() {
        return mResolverListController;
    }
    }


    public void handlePackagesChanged() {
    public void handlePackagesChanged() {
@@ -439,7 +447,7 @@ public class ResolverListAdapter extends BaseAdapter {
                        ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                        ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                        ri.icon = li.getIconResource();
                        ri.icon = li.getIconResource();
                        ri.iconResourceId = ri.icon;
                        ri.iconResourceId = ri.icon;
                        ri.userHandle = getUserHandle();
                        ri.userHandle = mInitialIntentsUserSpace;
                    }
                    }
                    if (userManager.isManagedProfile()) {
                    if (userManager.isManagedProfile()) {
                        ri.noResourceId = true;
                        ri.noResourceId = true;
+2 −2
Original line number Original line Diff line number Diff line
@@ -53,7 +53,7 @@ public class ChooserActivityOverrideData {


    @SuppressWarnings("Since15")
    @SuppressWarnings("Since15")
    public Function<PackageManager, PackageManager> createPackageManager;
    public Function<PackageManager, PackageManager> createPackageManager;
    public Function<TargetInfo, Boolean> onSafelyStartCallback;
    public Function<TargetInfo, Boolean> onSafelyStartInternalCallback;
    public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
    public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
    public BiFunction<
    public BiFunction<
            IChooserWrapper, ChooserListAdapter, Pair<Integer, ChooserActivity.ServiceResultInfo[]>>
            IChooserWrapper, ChooserListAdapter, Pair<Integer, ChooserActivity.ServiceResultInfo[]>>
@@ -82,7 +82,7 @@ public class ChooserActivityOverrideData {
    public PackageManager packageManager;
    public PackageManager packageManager;


    public void reset() {
    public void reset() {
        onSafelyStartCallback = null;
        onSafelyStartInternalCallback = null;
        onQueryDirectShareTargets = null;
        onQueryDirectShareTargets = null;
        directShareTargets = null;
        directShareTargets = null;
        isVoiceInteraction = null;
        isVoiceInteraction = null;
Loading