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

Commit 653dd7b1 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I0677bca4,I7cad6529

* changes:
  Fix autolaunching.
  Create a PackageMonitor instance for each profile.
parents 5e7253dd 7981b123
Loading
Loading
Loading
Loading
+59 −2
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@ package com.android.internal.app;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.View;
import android.view.ViewGroup;

@@ -27,6 +29,7 @@ import com.android.internal.widget.PagerAdapter;
import com.android.internal.widget.ViewPager;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@@ -46,11 +49,17 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
    private int mCurrentPage;
    private OnProfileSelectedListener mOnProfileSelectedListener;
    private Set<Integer> mLoadedPages;
    private final UserHandle mPersonalProfileUserHandle;
    private final UserHandle mWorkProfileUserHandle;

    AbstractMultiProfilePagerAdapter(Context context, int currentPage) {
    AbstractMultiProfilePagerAdapter(Context context, int currentPage,
            UserHandle personalProfileUserHandle,
            UserHandle workProfileUserHandle) {
        mContext = Objects.requireNonNull(context);
        mCurrentPage = currentPage;
        mLoadedPages = new HashSet<>();
        mPersonalProfileUserHandle = personalProfileUserHandle;
        mWorkProfileUserHandle = workProfileUserHandle;
    }

    void setOnProfileSelectedListener(OnProfileSelectedListener listener) {
@@ -72,7 +81,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
            public void onPageSelected(int position) {
                mCurrentPage = position;
                if (!mLoadedPages.contains(position)) {
                    getActiveListAdapter().rebuildList();
                    rebuildActiveTab(true);
                    mLoadedPages.add(position);
                }
                if (mOnProfileSelectedListener != null) {
@@ -85,6 +94,13 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
        mLoadedPages.add(mCurrentPage);
    }

    void clearInactiveProfileCache() {
        if (mLoadedPages.size() == 1) {
            return;
        }
        mLoadedPages.remove(1 - mCurrentPage);
    }

    @Override
    public ViewGroup instantiateItem(ViewGroup container, int position) {
        final ProfileDescriptor profileDescriptor = getItem(position);
@@ -187,12 +203,53 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
    @VisibleForTesting
    public abstract @Nullable ResolverListAdapter getInactiveListAdapter();

    public abstract ResolverListAdapter getPersonalListAdapter();

    public abstract @Nullable ResolverListAdapter getWorkListAdapter();

    abstract Object getCurrentRootAdapter();

    abstract ViewGroup getActiveAdapterView();

    abstract @Nullable ViewGroup getInactiveAdapterView();

    boolean rebuildActiveTab(boolean post) {
        return rebuildTab(getActiveListAdapter(), post);
    }

    boolean rebuildInactiveTab(boolean post) {
        if (getItemCount() == 1) {
            return false;
        }
        return rebuildTab(getInactiveListAdapter(), post);
    }

    private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) {
        UserHandle listUserHandle = activeListAdapter.getUserHandle();
        if (UserHandle.myUserId() != listUserHandle.getIdentifier() &&
                !hasAppsInOtherProfile(activeListAdapter)) {
            // TODO(arangelov): Show empty state UX here
            return false;
        } else {
            return activeListAdapter.rebuildList(doPostProcessing);
        }
    }

    private boolean hasAppsInOtherProfile(ResolverListAdapter adapter) {
        if (mWorkProfileUserHandle == null) {
            return false;
        }
        List<ResolverActivity.ResolvedComponentInfo> resolversForIntent =
                adapter.getResolversForUser(UserHandle.of(UserHandle.myUserId()));
        for (ResolverActivity.ResolvedComponentInfo info : resolversForIntent) {
            ResolveInfo resolveInfo = info.getResolveInfoAt(0);
            if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) {
                return true;
            }
        }
        return false;
    }

    protected class ProfileDescriptor {
        final ViewGroup rootView;
        ProfileDescriptor(ViewGroup rootView) {
+23 −9
Original line number Diff line number Diff line
@@ -793,7 +793,9 @@ public class ChooserActivity extends ResolverActivity implements
                /* userHandle */ UserHandle.of(UserHandle.myUserId()));
        return new ChooserMultiProfilePagerAdapter(
                /* context */ this,
                adapter);
                adapter,
                getPersonalProfileUserHandle(),
                /* workProfileUserHandle= */ null);
    }

    private ChooserMultiProfilePagerAdapter createChooserMultiProfilePagerAdapterForTwoProfiles(
@@ -820,7 +822,9 @@ public class ChooserActivity extends ResolverActivity implements
                /* context */ this,
                personalAdapter,
                workAdapter,
                /* defaultProfile */ getCurrentProfile());
                /* defaultProfile */ getCurrentProfile(),
                getPersonalProfileUserHandle(),
                getWorkProfileUserHandle());
    }

    @Override
@@ -872,11 +876,11 @@ public class ChooserActivity extends ResolverActivity implements
    }

    @Override
    protected PackageMonitor createPackageMonitor() {
    protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) {
        return new PackageMonitor() {
            @Override
            public void onSomePackagesChanged() {
                handlePackagesChanged();
                handlePackagesChanged(listAdapter);
            }
        };
    }
@@ -885,9 +889,19 @@ public class ChooserActivity extends ResolverActivity implements
     * Update UI to reflect changes in data.
     */
    public void handlePackagesChanged() {
        // TODO(arangelov): Dispatch this to all adapters when we have the helper methods
        // in a follow-up CL
        handlePackagesChanged(/* listAdapter */ null);
    }

    /**
     * Update UI to reflect changes in data.
     * <p>If {@code listAdapter} is {@code null}, both profile list adapters are updated.
     */
    private void handlePackagesChanged(@Nullable ResolverListAdapter listAdapter) {
        if (listAdapter == null) {
            mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
        } else {
            listAdapter.handlePackagesChanged();
        }
        updateProfileViewButton();
    }

@@ -2458,10 +2472,10 @@ public class ChooserActivity extends ResolverActivity implements
    }

    @Override // ResolverListCommunicator
    public void onHandlePackagesChanged() {
    public void onHandlePackagesChanged(ResolverListAdapter listAdapter) {
        mServicesRequested.clear();
        mChooserMultiProfilePagerAdapter.getActiveListAdapter().notifyDataSetChanged();
        super.onHandlePackagesChanged();
        super.onHandlePackagesChanged(listAdapter);
    }

    @Override // SelectableTargetInfoCommunicator
+7 −6
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.internal.app;
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE;
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.prediction.AppPredictor;
import android.content.ComponentName;
@@ -176,7 +175,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
            Log.d(TAG, "clearing queryTargets on package change");
        }
        createPlaceHolders();
        mChooserListCommunicator.onHandlePackagesChanged();
        mChooserListCommunicator.onHandlePackagesChanged(this);

    }

@@ -541,7 +540,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
    @Override
    AsyncTask<List<ResolvedComponentInfo>,
                Void,
                List<ResolvedComponentInfo>> createSortingTask() {
                List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) {
        return new AsyncTask<List<ResolvedComponentInfo>,
                Void,
                List<ResolvedComponentInfo>>() {
@@ -554,10 +553,12 @@ public class ChooserListAdapter extends ResolverListAdapter {
            }
            @Override
            protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
                processSortedList(sortedComponents);
                processSortedList(sortedComponents, doPostProcessing);
                if (doPostProcessing) {
                    mChooserListCommunicator.updateProfileViewButton();
                    notifyDataSetChanged();
                }
            }
        };
    }

+20 −4
Original line number Diff line number Diff line
@@ -38,8 +38,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
    private final ChooserProfileDescriptor[] mItems;

    ChooserMultiProfilePagerAdapter(Context context,
            ChooserActivity.ChooserGridAdapter adapter) {
        super(context, /* currentPage */ 0);
            ChooserActivity.ChooserGridAdapter adapter,
            UserHandle personalProfileUserHandle,
            UserHandle workProfileUserHandle) {
        super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle);
        mItems = new ChooserProfileDescriptor[] {
                createProfileDescriptor(adapter)
        };
@@ -48,8 +50,11 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
    ChooserMultiProfilePagerAdapter(Context context,
            ChooserActivity.ChooserGridAdapter personalAdapter,
            ChooserActivity.ChooserGridAdapter workAdapter,
            @Profile int defaultProfile) {
        super(context, /* currentPage */ defaultProfile);
            @Profile int defaultProfile,
            UserHandle personalProfileUserHandle,
            UserHandle workProfileUserHandle) {
        super(context, /* currentPage */ defaultProfile, personalProfileUserHandle,
                workProfileUserHandle);
        mItems = new ChooserProfileDescriptor[] {
                createProfileDescriptor(personalAdapter),
                createProfileDescriptor(workAdapter)
@@ -130,6 +135,17 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
        return getAdapterForIndex(1 - getCurrentPage()).getListAdapter();
    }

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

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

    @Override
    ChooserActivity.ChooserGridAdapter getCurrentRootAdapter() {
        return getAdapterForIndex(getCurrentPage());
+202 −52
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.internal.app;

import static android.Manifest.permission.INTERACT_ACROSS_PROFILES;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.PermissionChecker.PID_UNKNOWN;

import static com.android.internal.app.AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
import static com.android.internal.app.AbstractMultiProfilePagerAdapter.PROFILE_WORK;
@@ -36,6 +38,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -157,7 +160,8 @@ public class ResolverActivity extends Activity implements
    private static final String TAB_TAG_PERSONAL = "personal";
    private static final String TAB_TAG_WORK = "work";

    private final PackageMonitor mPackageMonitor = createPackageMonitor();
    private PackageMonitor mPersonalPackageMonitor;
    private PackageMonitor mWorkPackageMonitor;

    @VisibleForTesting
    protected AbstractMultiProfilePagerAdapter mMultiProfilePagerAdapter;
@@ -243,11 +247,11 @@ public class ResolverActivity extends Activity implements
        }
    }

    protected PackageMonitor createPackageMonitor() {
    protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) {
        return new PackageMonitor() {
            @Override
            public void onSomePackagesChanged() {
                mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
                listAdapter.handlePackagesChanged();
                updateProfileViewButton();
            }

@@ -327,8 +331,6 @@ public class ResolverActivity extends Activity implements

        mPm = getPackageManager();

        mPackageMonitor.register(this, getMainLooper(), false);
        mRegistered = true;
        mReferrerPackage = getReferrerPackageName();

        // Add our initial intent as the first item, regardless of what else has already been added.
@@ -353,6 +355,18 @@ public class ResolverActivity extends Activity implements
            return;
        }

        mPersonalPackageMonitor = createPackageMonitor(
                mMultiProfilePagerAdapter.getPersonalListAdapter());
        mPersonalPackageMonitor.register(
                this, getMainLooper(), getPersonalProfileUserHandle(), false);
        if (hasWorkProfile()) {
            mWorkPackageMonitor = createPackageMonitor(
                    mMultiProfilePagerAdapter.getWorkListAdapter());
            mWorkPackageMonitor.register(this, getMainLooper(), getWorkProfileUserHandle(), false);
        }

        mRegistered = true;

        final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
        if (rdl != null) {
            rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
@@ -419,7 +433,9 @@ public class ResolverActivity extends Activity implements
                /* userHandle */ UserHandle.of(UserHandle.myUserId()));
        return new ResolverMultiProfilePagerAdapter(
                /* context */ this,
                adapter);
                adapter,
                getPersonalProfileUserHandle(),
                /* workProfileUserHandle= */ null);
    }

    private ResolverMultiProfilePagerAdapter createResolverMultiProfilePagerAdapterForTwoProfiles(
@@ -438,20 +454,23 @@ public class ResolverActivity extends Activity implements
                        == getPersonalProfileUserHandle().getIdentifier()),
                mUseLayoutForBrowsables,
                /* userHandle */ getPersonalProfileUserHandle());
        UserHandle workProfileUserHandle = getWorkProfileUserHandle();
        ResolverListAdapter workAdapter = createResolverListAdapter(
                /* context */ this,
                /* payloadIntents */ mIntents,
                initialIntents,
                rList,
                (filterLastUsed && UserHandle.myUserId()
                        == getWorkProfileUserHandle().getIdentifier()),
                        == workProfileUserHandle.getIdentifier()),
                mUseLayoutForBrowsables,
                /* userHandle */ getWorkProfileUserHandle());
                /* userHandle */ workProfileUserHandle);
        return new ResolverMultiProfilePagerAdapter(
                /* context */ this,
                personalAdapter,
                workAdapter,
                /* defaultProfile */ getCurrentProfile());
                /* defaultProfile */ getCurrentProfile(),
                getPersonalProfileUserHandle(),
                getWorkProfileUserHandle());
    }

    protected @Profile int getCurrentProfile() {
@@ -543,9 +562,6 @@ public class ResolverActivity extends Activity implements
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
        if (mMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
            mMultiProfilePagerAdapter.getInactiveListAdapter().handlePackagesChanged();
        }

        if (mSystemWindowInsets != null) {
            mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
@@ -707,7 +723,16 @@ public class ResolverActivity extends Activity implements
    protected void onRestart() {
        super.onRestart();
        if (!mRegistered) {
            mPackageMonitor.register(this, getMainLooper(), false);
            mPersonalPackageMonitor.register(this, getMainLooper(),
                    getPersonalProfileUserHandle(), false);
            if (hasWorkProfile()) {
                if (mWorkPackageMonitor == null) {
                    mWorkPackageMonitor = createPackageMonitor(
                            mMultiProfilePagerAdapter.getWorkListAdapter());
                }
                mWorkPackageMonitor.register(this, getMainLooper(),
                        getWorkProfileUserHandle(), false);
            }
            mRegistered = true;
        }
        mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
@@ -718,7 +743,10 @@ public class ResolverActivity extends Activity implements
    protected void onStop() {
        super.onStop();
        if (mRegistered) {
            mPackageMonitor.unregister();
            mPersonalPackageMonitor.unregister();
            if (mWorkPackageMonitor != null) {
                mWorkPackageMonitor.unregister();
            }
            mRegistered = false;
        }
        final Intent intent = getIntent();
@@ -913,7 +941,11 @@ public class ResolverActivity extends Activity implements
    }

    @Override // ResolverListCommunicator
    public void onPostListReady(ResolverListAdapter listAdapter) {
    public void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing) {
        if (isAutolaunching() || maybeAutolaunchActivity()) {
            return;
        }
        if (doPostProcessing) {
            if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
                    == UserHandle.myUserId()) {
                setHeader();
@@ -921,18 +953,9 @@ public class ResolverActivity extends Activity implements
            resetButtonBar();
            onListRebuilt(listAdapter);
        }

    protected void onListRebuilt(ResolverListAdapter listAdapter) {
        int count = listAdapter.getUnfilteredCount();
        if (count == 1 && listAdapter.getOtherProfile() == null) {
            // Only one target, so we're a candidate to auto-launch!
            final TargetInfo target = listAdapter.targetInfoForPosition(0, false);
            if (shouldAutoLaunchSingleChoice(target)) {
                safelyStartActivity(target);
                finish();
            }
    }

    protected void onListRebuilt(ResolverListAdapter listAdapter) {
        final ItemClickListener listener = new ItemClickListener();
        setupAdapterListView((ListView) mMultiProfilePagerAdapter.getActiveAdapterView(), listener);
    }
@@ -1132,6 +1155,11 @@ public class ResolverActivity extends Activity implements
    }

    private void safelyStartActivityInternal(TargetInfo cti) {
        mPersonalPackageMonitor.unregister();
        if (mWorkPackageMonitor != null) {
            mWorkPackageMonitor.unregister();
        }
        mRegistered = false;
        // If needed, show that intent is forwarded
        // from managed profile to owner or other way around.
        if (mProfileSwitchMessageId != -1) {
@@ -1247,7 +1275,11 @@ public class ResolverActivity extends Activity implements
            throw new IllegalStateException("mMultiProfilePagerAdapter.getCurrentListAdapter() "
                    + "cannot be null.");
        }
        boolean rebuildCompleted = mMultiProfilePagerAdapter.getActiveListAdapter().rebuildList();
        boolean rebuildCompleted = mMultiProfilePagerAdapter.rebuildActiveTab(true);

        // We partially rebuild the inactive adapter to determine if we should auto launch
        mMultiProfilePagerAdapter.rebuildInactiveTab(false);

        if (useLayoutWithDefault()) {
            mLayoutId = R.layout.resolver_list_with_default;
        } else {
@@ -1274,36 +1306,146 @@ public class ResolverActivity extends Activity implements
     * @return <code>true</code> if the activity is finishing and creation should halt.
     */
    final boolean postRebuildListInternal(boolean rebuildCompleted) {

        int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();

        // We only rebuild asynchronously when we have multiple elements to sort. In the case where
        // we're already done, we can check if we should auto-launch immediately.
        if (rebuildCompleted) {
            if (count == 1
                    && mMultiProfilePagerAdapter.getActiveListAdapter().getOtherProfile() == null) {
        if (rebuildCompleted && maybeAutolaunchActivity()) {
            return true;
        }

        setupViewVisibilities();

        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
            setupProfileTabs();
        }

        return false;
    }

    private int isPermissionGranted(String permission, int uid) {
        return ActivityManager.checkComponentPermission(permission, uid,
                /* owningUid= */-1, /* exported= */ true);
    }

    /**
     * @return {@code true} if a resolved target is autolaunched, otherwise {@code false}
     */
    private boolean maybeAutolaunchActivity() {
        int numberOfProfiles = mMultiProfilePagerAdapter.getItemCount();
        if (numberOfProfiles == 1 && maybeAutolaunchIfSingleTarget()) {
            return true;
        } else if (numberOfProfiles == 2 && maybeAutolaunchIfCrossProfileSupported()) {
            // note that autolaunching when we have 2 profiles, 1 resolved target on the active
            // tab and 0 resolved targets on the inactive tab, is already handled before launching
            // ResolverActivity
            return true;
        }
        return false;
    }

    private boolean maybeAutolaunchIfSingleTarget() {
        int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
        if (count != 1) {
            return false;
        }

        // Only one target, so we're a candidate to auto-launch!
        final TargetInfo target = mMultiProfilePagerAdapter.getActiveListAdapter()
                .targetInfoForPosition(0, false);
        if (shouldAutoLaunchSingleChoice(target)) {
            safelyStartActivity(target);
                    mPackageMonitor.unregister();
                    mRegistered = false;
            finish();
            return true;
        }
        return false;
    }

    /**
     * When we have a personal and a work profile, we auto launch in the following scenario:
     * - There is 1 resolved target on each profile
     * - That target is the same app on both profiles
     * - The target app has permission to communicate cross profiles
     * - The target app has declared it supports cross-profile communication via manifest metadata
     */
    private boolean maybeAutolaunchIfCrossProfileSupported() {
        int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
        if (count != 1) {
            return false;
        }
        ResolverListAdapter inactiveListAdapter =
                mMultiProfilePagerAdapter.getInactiveListAdapter();
        if (inactiveListAdapter.getUnfilteredCount() != 1) {
            return false;
        }
        TargetInfo activeProfileTarget = mMultiProfilePagerAdapter.getActiveListAdapter()
                .targetInfoForPosition(0, false);
        TargetInfo inactiveProfileTarget = inactiveListAdapter.targetInfoForPosition(0, false);
        if (!Objects.equals(activeProfileTarget.getResolvedComponentName(),
                inactiveProfileTarget.getResolvedComponentName())) {
            return false;
        }
        if (!shouldAutoLaunchSingleChoice(activeProfileTarget)) {
            return false;
        }
        String packageName = activeProfileTarget.getResolvedComponentName().getPackageName();
        if (!canAppInteractCrossProfiles(packageName)) {
            return false;
        }

        setupViewVisibilities();
        safelyStartActivity(activeProfileTarget);
        finish();
        return true;
    }

        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
            setupProfileTabs();
    /**
     * Returns whether the package has the necessary permissions to interact across profiles on
     * behalf of a given user.
     *
     * <p>This means meeting the following condition:
     * <ul>
     *     <li>The app's {@link ApplicationInfo#crossProfile} flag must be true, and at least
     *     one of the following conditions must be fulfilled</li>
     *     <li>{@code Manifest.permission.INTERACT_ACROSS_USERS_FULL} granted.</li>
     *     <li>{@code Manifest.permission.INTERACT_ACROSS_USERS} granted.</li>
     *     <li>{@code Manifest.permission.INTERACT_ACROSS_PROFILES} granted, or the corresponding
     *     AppOps {@code android:interact_across_profiles} is set to "allow".</li>
     * </ul>
     *
     */
    private boolean canAppInteractCrossProfiles(String packageName) {
        ApplicationInfo applicationInfo;
        try {
            applicationInfo = getPackageManager().getApplicationInfo(packageName, 0);
        } catch (NameNotFoundException e) {
            Log.e(TAG, "Package " + packageName + " does not exist on current user.");
            return false;
        }
        if (!applicationInfo.crossProfile) {
            return false;
        }

        int packageUid = applicationInfo.uid;

        if (isPermissionGranted(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                packageUid) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        if (isPermissionGranted(android.Manifest.permission.INTERACT_ACROSS_USERS, packageUid)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        if (PermissionChecker.checkPermissionForPreflight(this, INTERACT_ACROSS_PROFILES,
                PID_UNKNOWN, packageUid, packageName) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        return false;
    }

    private boolean isAutolaunching() {
        return !mRegistered && isFinishing();
    }

    private void setupProfileTabs() {
        TabHost tabHost = findViewById(R.id.profile_tabhost);
        tabHost.setup();
@@ -1499,14 +1641,22 @@ public class ResolverActivity extends Activity implements
    }

    @Override // ResolverListCommunicator
    public void onHandlePackagesChanged() {
        ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
        activeListAdapter.rebuildList();
    public void onHandlePackagesChanged(ResolverListAdapter listAdapter) {
        if (listAdapter == mMultiProfilePagerAdapter.getActiveListAdapter()) {
            boolean listRebuilt = mMultiProfilePagerAdapter.rebuildActiveTab(true);
            if (listRebuilt) {
                ResolverListAdapter activeListAdapter =
                        mMultiProfilePagerAdapter.getActiveListAdapter();
                activeListAdapter.notifyDataSetChanged();
                if (activeListAdapter.getCount() == 0) {
                    // We no longer have any items...  just finish the activity.
                    finish();
                }
            }
        } else {
            mMultiProfilePagerAdapter.clearInactiveProfileCache();
        }
    }

    @VisibleForTesting
    public static final class ResolvedComponentInfo {
Loading