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

Commit 9085abc4 authored by Himanshu Gupta's avatar Himanshu Gupta
Browse files

Include cloned apps in system sharesheet.

This CL is the first of multiple Cls which integrate Cloned Apps
with the system sharesheet.
Contents:
1. Adding API to get UserHandle from ResolveInfo.
2. Adding userHandle to uniquely identify ResolveInfo in sharesheet.
3. Loading Icons with userHandle supplied from 1.
4. Personal Adaptor starts with Cloned User Id when sharesheet is
   started in Cloned App.
5. AzInfoComparator adds userHandle to sort apps.
6. Different Disambiguation dialog for last choosen activity is
   disabled, when clonedProfile is present.
7. Setting 'Always' choosen activity is disabled personal adapter when
   clonedProfile is present.
8. Profile based icons added in Dialog Boxes. (Stacked apps and Long
   press)

Bug: 240100378

Test: atest ResolverActivityTest

Change-Id: I5eb288e4f3059f0945a8c3ff410b19b8820a69cf
parent b773380d
Loading
Loading
Loading
Loading
+9 −14
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@
package com.android.internal.app;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.content.ContentResolver;
@@ -60,16 +60,19 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
    private Set<Integer> mLoadedPages;
    private final EmptyStateProvider mEmptyStateProvider;
    private final UserHandle mWorkProfileUserHandle;
    private final UserHandle mCloneUserHandle;
    private final QuietModeManager mQuietModeManager;

    AbstractMultiProfilePagerAdapter(Context context, int currentPage,
            EmptyStateProvider emptyStateProvider,
            QuietModeManager quietModeManager,
            UserHandle workProfileUserHandle) {
            UserHandle workProfileUserHandle,
            UserHandle cloneUserHandle) {
        mContext = Objects.requireNonNull(context);
        mCurrentPage = currentPage;
        mLoadedPages = new HashSet<>();
        mWorkProfileUserHandle = workProfileUserHandle;
        mCloneUserHandle = cloneUserHandle;
        mEmptyStateProvider = emptyStateProvider;
        mQuietModeManager = quietModeManager;
    }
@@ -160,6 +163,10 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
        return null;
    }

    public UserHandle getCloneUserHandle() {
        return mCloneUserHandle;
    }

    /**
     * Returns the {@link ProfileDescriptor} relevant to the given <code>pageIndex</code>.
     * <ul>
@@ -317,18 +324,6 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
        showEmptyState(listAdapter, emptyState, clickListener);
    }

    /**
     * Class to get user id of the current process
     */
    public static class MyUserIdProvider {
        /**
         * @return user id of the current process
         */
        public int getMyUserId() {
            return UserHandle.myUserId();
        }
    }

    /**
     * Utility class to check if there are cross profile intents, it is in a separate class so
     * it could be mocked in tests
+38 −18
Original line number Diff line number Diff line
@@ -873,7 +873,7 @@ public class ChooserActivity extends ResolverActivity implements

        return new NoCrossProfileEmptyStateProvider(getPersonalProfileUserHandle(),
                noWorkToPersonalEmptyState, noPersonalToWorkEmptyState,
                createCrossProfileIntentsChecker(), createMyUserIdProvider());
                createCrossProfileIntentsChecker(), getTabOwnerUserHandleForLaunch());
    }

    private ChooserMultiProfilePagerAdapter createChooserMultiProfilePagerAdapterForOneProfile(
@@ -886,13 +886,14 @@ public class ChooserActivity extends ResolverActivity implements
                initialIntents,
                rList,
                filterLastUsed,
                /* userHandle */ UserHandle.of(UserHandle.myUserId()));
                /* userHandle */ getPersonalProfileUserHandle());
        return new ChooserMultiProfilePagerAdapter(
                /* context */ this,
                adapter,
                createEmptyStateProvider(/* workProfileUserHandle= */ null),
                mQuietModeManager,
                /* workProfileUserHandle= */ null,
                getCloneProfileUserHandle(),
                mMaxTargetsPerRow);
    }

@@ -923,13 +924,14 @@ public class ChooserActivity extends ResolverActivity implements
                mQuietModeManager,
                selectedProfile,
                getWorkProfileUserHandle(),
                getCloneProfileUserHandle(),
                mMaxTargetsPerRow);
    }

    private int findSelectedProfile() {
        int selectedProfile = getSelectedProfileExtra();
        if (selectedProfile == -1) {
            selectedProfile = getProfileForUser(getUser());
            selectedProfile = getProfileForUser(getTabOwnerUserHandleForLaunch());
        }
        return selectedProfile;
    }
@@ -1800,8 +1802,12 @@ public class ChooserActivity extends ResolverActivity implements
            targetList = new ArrayList<DisplayResolveInfo>();
            targetList.add((DisplayResolveInfo) targetInfo);
        }
        // Adding userHandle from ResolveInfo allows the app icon in Dialog Box to be
        // resolved correctly.
        bundle.putParcelable(ChooserTargetActionsDialogFragment.USER_HANDLE_KEY,
                mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
                getResolveInfoUserHandle(
                        targetInfo.getResolveInfo(),
                        mChooserMultiProfilePagerAdapter.getCurrentUserHandle()));
        bundle.putParcelableArrayList(ChooserTargetActionsDialogFragment.TARGET_INFOS_KEY,
                targetList);
        fragment.setArguments(bundle);
@@ -1865,8 +1871,11 @@ public class ChooserActivity extends ResolverActivity implements
            if (!mti.hasSelected()) {
                ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment();
                Bundle b = new Bundle();
                // Add userHandle based badge to the stackedAppDialogBox.
                b.putParcelable(ChooserTargetActionsDialogFragment.USER_HANDLE_KEY,
                        mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
                        getResolveInfoUserHandle(
                                targetInfo.getResolveInfo(),
                                mChooserMultiProfilePagerAdapter.getCurrentUserHandle()));
                b.putObject(ChooserStackedAppDialogFragment.MULTI_DRI_KEY,
                        mti);
                b.putInt(ChooserStackedAppDialogFragment.WHICH_KEY, which);
@@ -2433,15 +2442,24 @@ public class ChooserActivity extends ResolverActivity implements
     * Sort intents alphabetically based on display label.
     */
    static class AzInfoComparator implements Comparator<DisplayResolveInfo> {
        Collator mCollator;
        Comparator<DisplayResolveInfo> mComparator;
        AzInfoComparator(Context context) {
            mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
            Collator collator = Collator
                    .getInstance(context.getResources().getConfiguration().locale);
            // Adding two stage comparator, first stage compares using displayLabel, next stage
            //  compares using resolveInfo.userHandle
            mComparator = Comparator.comparing(DisplayResolveInfo::getDisplayLabel, collator)
                    .thenComparingInt(displayResolveInfo ->
                            getResolveInfoUserHandle(
                                    displayResolveInfo.getResolveInfo(),
                                    // TODO: User resolveInfo.userHandle, once its available.
                                    UserHandle.SYSTEM).getIdentifier());
        }

        @Override
        public int compare(
                DisplayResolveInfo lhsp, DisplayResolveInfo rhsp) {
            return mCollator.compare(lhsp.getDisplayLabel(), rhsp.getDisplayLabel());
            return mComparator.compare(lhsp, rhsp);
        }
    }

@@ -2466,9 +2484,10 @@ public class ChooserActivity extends ResolverActivity implements
                String referrerPackageName,
                int launchedFromUid,
                UserHandle userId,
                AbstractResolverComparator resolverComparator) {
                AbstractResolverComparator resolverComparator,
                UserHandle queryIntentsAsUser) {
            super(context, pm, targetIntent, referrerPackageName, launchedFromUid, userId,
                    resolverComparator);
                    resolverComparator, queryIntentsAsUser);
        }

        @Override
@@ -2533,6 +2552,7 @@ public class ChooserActivity extends ResolverActivity implements
                        getReferrerPackageName(), null, getChooserActivityLogger());
        }

        UserHandle queryIntentsUser = getQueryIntentsUser(userHandle);
        return new ChooserListController(
                this,
                mPm,
@@ -2540,7 +2560,8 @@ public class ChooserActivity extends ResolverActivity implements
                getReferrerPackageName(),
                mLaunchedFromUid,
                userHandle,
                resolverComparator);
                resolverComparator,
                queryIntentsUser == null ? userHandle : queryIntentsUser);
    }

    @VisibleForTesting
@@ -2741,17 +2762,16 @@ 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.
     * Returns {@link #PROFILE_WORK}, if the given user handle matches work user handle.
     * Returns {@link #PROFILE_PERSONAL}, otherwise.
     **/
    private int getProfileForUser(UserHandle currentUserHandle) {
        if (currentUserHandle.equals(getPersonalProfileUserHandle())) {
            return PROFILE_PERSONAL;
        } else if (currentUserHandle.equals(getWorkProfileUserHandle())) {
        if (currentUserHandle.equals(getWorkProfileUserHandle())) {
            return PROFILE_WORK;
        }
        Log.e(TAG, "User " + currentUserHandle + " does not belong to a personal or work profile.");
        return -1;
        // We return personal profile, as it is the default when there is no work profile, personal
        // profile represents rootUser, clonedUser & secondaryUser, covering all use cases.
        return PROFILE_PERSONAL;
    }

    private ViewGroup getActiveEmptyStateView() {
+7 −2
Original line number Diff line number Diff line
@@ -197,6 +197,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
                    ri.nonLocalizedLabel = li.getNonLocalizedLabel();
                    ri.icon = li.getIconResource();
                    ri.iconResourceId = ri.icon;
                    // TODO: Uncomment the below line once userHandle is added to ResolveInfo
                    //ri.userHandle = getUserHandle();
                }
                if (userManager.isManagedProfile()) {
                    ri.noResourceId = true;
@@ -351,7 +353,9 @@ public class ChooserListAdapter extends ResolverListAdapter {
                Map<String, DisplayResolveInfo> consolidated = new HashMap<>();
                for (DisplayResolveInfo info : allTargets) {
                    String resolvedTarget = info.getResolvedComponentName().getPackageName()
                            + '#' + info.getDisplayLabel();
                            + '#' + info.getDisplayLabel()
                            + '#' + ResolverActivity.getResolveInfoUserHandle(
                                    info.getResolveInfo(), getUserHandle()).getIdentifier();
                    DisplayResolveInfo multiDri = consolidated.get(resolvedTarget);
                    if (multiDri == null) {
                        consolidated.put(resolvedTarget, info);
@@ -367,7 +371,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
                }
                List<DisplayResolveInfo> groupedTargets = new ArrayList<>();
                groupedTargets.addAll(consolidated.values());
                Collections.sort(groupedTargets, new ChooserActivity.AzInfoComparator(mContext));
                Collections.sort(groupedTargets,
                        new ChooserActivity.AzInfoComparator(mContext));
                return groupedTargets;
            }
            @Override
+12 −9
Original line number Diff line number Diff line
@@ -45,9 +45,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
            EmptyStateProvider emptyStateProvider,
            QuietModeManager quietModeManager,
            UserHandle workProfileUserHandle,
            UserHandle cloneUserHandle,
            int maxTargetsPerRow) {
        super(context, /* currentPage */ 0, emptyStateProvider, quietModeManager,
                workProfileUserHandle);
                workProfileUserHandle, cloneUserHandle);
        mItems = new ChooserProfileDescriptor[] {
                createProfileDescriptor(adapter)
        };
@@ -61,9 +62,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
            QuietModeManager quietModeManager,
            @Profile int defaultProfile,
            UserHandle workProfileUserHandle,
            UserHandle cloneUserHandle,
            int maxTargetsPerRow) {
        super(context, /* currentPage */ defaultProfile, emptyStateProvider,
                quietModeManager, workProfileUserHandle);
                quietModeManager, workProfileUserHandle, cloneUserHandle);
        mItems = new ChooserProfileDescriptor[] {
                createProfileDescriptor(personalAdapter),
                createProfileDescriptor(workAdapter)
@@ -110,11 +112,12 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
    @Override
    @Nullable
    ChooserListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
        if (getActiveListAdapter().getUserHandle().equals(userHandle)) {
            return getActiveListAdapter();
        } else if (getInactiveListAdapter() != null
                && getInactiveListAdapter().getUserHandle().equals(userHandle)) {
            return getInactiveListAdapter();
        if (getPersonalListAdapter().getUserHandle().equals(userHandle)
                || userHandle.equals(getCloneUserHandle())) {
            return getPersonalListAdapter();
        } else if (getWorkListAdapter() != null
                && getWorkListAdapter().getUserHandle().equals(userHandle)) {
            return getWorkListAdapter();
        }
        return null;
    }
@@ -153,13 +156,13 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
    }

    @Override
    public ResolverListAdapter getPersonalListAdapter() {
    public ChooserListAdapter getPersonalListAdapter() {
        return getAdapterForIndex(PROFILE_PERSONAL).getListAdapter();
    }

    @Override
    @Nullable
    public ResolverListAdapter getWorkListAdapter() {
    public ChooserListAdapter getWorkListAdapter() {
        return getAdapterForIndex(PROFILE_WORK).getListAdapter();
    }

+6 −7
Original line number Diff line number Diff line
@@ -28,10 +28,9 @@ import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.stats.devicepolicy.nano.DevicePolicyEnums;

import com.android.internal.R;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.R;

import java.util.List;

@@ -50,16 +49,16 @@ public class NoAppsAvailableEmptyStateProvider implements EmptyStateProvider {
    @NonNull
    private final String mMetricsCategory;
    @NonNull
    private final MyUserIdProvider mMyUserIdProvider;
    private final UserHandle mTabOwnerUserHandleForLaunch;

    public NoAppsAvailableEmptyStateProvider(Context context, UserHandle workProfileUserHandle,
            UserHandle personalProfileUserHandle, String metricsCategory,
            MyUserIdProvider myUserIdProvider) {
            UserHandle tabOwnerUserHandleForLaunch) {
        mContext = context;
        mWorkProfileUserHandle = workProfileUserHandle;
        mPersonalProfileUserHandle = personalProfileUserHandle;
        mMetricsCategory = metricsCategory;
        mMyUserIdProvider = myUserIdProvider;
        mTabOwnerUserHandleForLaunch = tabOwnerUserHandleForLaunch;
    }

    @Nullable
@@ -69,7 +68,7 @@ public class NoAppsAvailableEmptyStateProvider implements EmptyStateProvider {
        UserHandle listUserHandle = resolverListAdapter.getUserHandle();

        if (mWorkProfileUserHandle != null
                && (mMyUserIdProvider.getMyUserId() == listUserHandle.getIdentifier()
                && (mTabOwnerUserHandleForLaunch.equals(listUserHandle)
                || !hasAppsInOtherProfile(resolverListAdapter))) {

            String title;
@@ -102,7 +101,7 @@ public class NoAppsAvailableEmptyStateProvider implements EmptyStateProvider {
            return false;
        }
        List<ResolverActivity.ResolvedComponentInfo> resolversForIntent =
                adapter.getResolversForUser(UserHandle.of(mMyUserIdProvider.getMyUserId()));
                adapter.getResolversForUser(mTabOwnerUserHandleForLaunch);
        for (ResolverActivity.ResolvedComponentInfo info : resolversForIntent) {
            ResolveInfo resolveInfo = info.getResolveInfoAt(0);
            if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) {
Loading