Merge changes from topic "AppCloningXSharesheet-master"

* changes:
  Swithing to ResolveInfo.userHandle in Sharesheet.
  Include cloned apps in system sharesheet.
This commit is contained in:
Himanshu Gupta
2023-01-18 14:43:23 +00:00
committed by Android (Google) Code Review
19 changed files with 774 additions and 252 deletions

View File

@@ -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>

View File

@@ -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() {

View File

@@ -197,6 +197,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
ri.iconResourceId = ri.icon;
ri.userHandle = getUserHandle();
}
if (userManager.isManagedProfile()) {
ri.noResourceId = true;
@@ -351,7 +352,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 +370,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

View File

@@ -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();
}

View File

@@ -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) {

View File

@@ -27,7 +27,6 @@ import android.os.UserHandle;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyState;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
/**
* Empty state provider that does not allow cross profile sharing, it will return a blocker
@@ -39,28 +38,28 @@ public class NoCrossProfileEmptyStateProvider implements EmptyStateProvider {
private final EmptyState mNoWorkToPersonalEmptyState;
private final EmptyState mNoPersonalToWorkEmptyState;
private final CrossProfileIntentsChecker mCrossProfileIntentsChecker;
private final MyUserIdProvider mUserIdProvider;
private final UserHandle mTabOwnerUserHandleForLaunch;
public NoCrossProfileEmptyStateProvider(UserHandle personalUserHandle,
EmptyState noWorkToPersonalEmptyState,
EmptyState noPersonalToWorkEmptyState,
CrossProfileIntentsChecker crossProfileIntentsChecker,
MyUserIdProvider myUserIdProvider) {
UserHandle preselectedTabOwnerUserHandle) {
mPersonalProfileUserHandle = personalUserHandle;
mNoWorkToPersonalEmptyState = noWorkToPersonalEmptyState;
mNoPersonalToWorkEmptyState = noPersonalToWorkEmptyState;
mCrossProfileIntentsChecker = crossProfileIntentsChecker;
mUserIdProvider = myUserIdProvider;
mTabOwnerUserHandleForLaunch = preselectedTabOwnerUserHandle;
}
@Nullable
@Override
public EmptyState getEmptyState(ResolverListAdapter resolverListAdapter) {
boolean shouldShowBlocker =
mUserIdProvider.getMyUserId() != resolverListAdapter.getUserHandle().getIdentifier()
!mTabOwnerUserHandleForLaunch.equals(resolverListAdapter.getUserHandle())
&& !mCrossProfileIntentsChecker
.hasCrossProfileIntents(resolverListAdapter.getIntents(),
mUserIdProvider.getMyUserId(),
mTabOwnerUserHandleForLaunch.getIdentifier(),
resolverListAdapter.getUserHandle().getIdentifier());
if (!shouldShowBlocker) {

View File

@@ -166,6 +166,7 @@ public class ResolverActivity extends Activity implements
@UnsupportedAppUsage
protected PackageManager mPm;
protected int mLaunchedFromUid;
private UserHandle mLaunchedFromUserHandle;
private static final String TAG = "ResolverActivity";
private static final boolean DEBUG = false;
@@ -229,12 +230,15 @@ public class ResolverActivity extends Activity implements
private BroadcastReceiver mWorkProfileStateReceiver;
private UserHandle mHeaderCreatorUser;
private UserHandle mPersonalProfileUserHandle;
private UserHandle mWorkProfileUserHandle;
@Nullable
private OnSwitchOnWorkSelectedListener mOnSwitchOnWorkSelectedListener;
private UserHandle mCloneProfileUserHandle;
private UserHandle mTabOwnerUserHandleForLaunch;
protected final LatencyTracker mLatencyTracker = getLatencyTracker();
private LatencyTracker getLatencyTracker() {
@@ -400,6 +404,7 @@ public class ResolverActivity extends Activity implements
setProfileSwitchMessage(intent.getContentUserHint());
mLaunchedFromUid = getLaunchedFromUid();
mLaunchedFromUserHandle = UserHandle.getUserHandleForUid(mLaunchedFromUid);
if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
// Gulp!
finish();
@@ -416,15 +421,21 @@ public class ResolverActivity extends Activity implements
mDefaultTitleResId = defaultTitleRes;
mSupportsAlwaysUseOption = supportsAlwaysUseOption;
mPersonalProfileUserHandle = fetchPersonalProfileUserHandle();
mWorkProfileUserHandle = fetchWorkProfileUserProfile();
mCloneProfileUserHandle = fetchCloneProfileUserHandle();
mTabOwnerUserHandleForLaunch = fetchTabOwnerUserHandleForLaunch();
// The last argument of createResolverListAdapter is whether to do special handling
// of the last used choice to highlight it in the list. We need to always
// turn this off when running under voice interaction, since it results in
// a more complicated UI that the current voice interaction flow is not able
// to handle. We also turn it off when the work tab is shown to simplify the UX.
// We also turn it off when clonedProfile is present on the device, because we might have
// different "last chosen" activities in the different profiles, and PackageManager doesn't
// provide any more information to help us select between them.
boolean filterLastUsed = mSupportsAlwaysUseOption && !isVoiceInteraction()
&& !shouldShowTabs();
&& !shouldShowTabs() && !hasCloneProfile();
mMultiProfilePagerAdapter = createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed);
if (configureContentView()) {
return;
@@ -566,9 +577,12 @@ public class ResolverActivity extends Activity implements
/* devicePolicyEventId= */ RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK,
/* devicePolicyEventCategory= */ ResolverActivity.METRICS_CATEGORY_RESOLVER);
return new NoCrossProfileEmptyStateProvider(getPersonalProfileUserHandle(),
noWorkToPersonalEmptyState, noPersonalToWorkEmptyState,
createCrossProfileIntentsChecker(), createMyUserIdProvider());
return new NoCrossProfileEmptyStateProvider(
getPersonalProfileUserHandle(),
noWorkToPersonalEmptyState,
noPersonalToWorkEmptyState,
createCrossProfileIntentsChecker(),
getTabOwnerUserHandleForLaunch());
}
protected EmptyStateProvider createEmptyStateProvider(
@@ -589,7 +603,7 @@ public class ResolverActivity extends Activity implements
workProfileUserHandle,
getPersonalProfileUserHandle(),
getMetricsCategory(),
createMyUserIdProvider()
getTabOwnerUserHandleForLaunch()
);
// Return composite provider, the order matters (the higher, the more priority)
@@ -609,14 +623,15 @@ public class ResolverActivity extends Activity implements
initialIntents,
rList,
filterLastUsed,
/* userHandle */ UserHandle.of(UserHandle.myUserId()));
/* userHandle */ getPersonalProfileUserHandle());
QuietModeManager quietModeManager = createQuietModeManager();
return new ResolverMultiProfilePagerAdapter(
/* context */ this,
adapter,
createEmptyStateProvider(/* workProfileUserHandle= */ null),
quietModeManager,
/* workProfileUserHandle= */ null);
/* workProfileUserHandle= */ null,
getCloneProfileUserHandle());
}
private UserHandle getIntentUser() {
@@ -634,7 +649,7 @@ public class ResolverActivity extends Activity implements
// this happens, we check for it here and set the current profile's tab.
int selectedProfile = getCurrentProfile();
UserHandle intentUser = getIntentUser();
if (!getUser().equals(intentUser)) {
if (!getTabOwnerUserHandleForLaunch().equals(intentUser)) {
if (getPersonalProfileUserHandle().equals(intentUser)) {
selectedProfile = PROFILE_PERSONAL;
} else if (getWorkProfileUserHandle().equals(intentUser)) {
@@ -674,7 +689,8 @@ public class ResolverActivity extends Activity implements
createEmptyStateProvider(getWorkProfileUserHandle()),
quietModeManager,
selectedProfile,
getWorkProfileUserHandle());
getWorkProfileUserHandle(),
getCloneProfileUserHandle());
}
protected int appliedThemeResId() {
@@ -701,20 +717,35 @@ public class ResolverActivity extends Activity implements
}
protected @Profile int getCurrentProfile() {
return (UserHandle.myUserId() == UserHandle.USER_SYSTEM ? PROFILE_PERSONAL : PROFILE_WORK);
return (UserHandle.myUserId() == getPersonalProfileUserHandle().getIdentifier()
? PROFILE_PERSONAL : PROFILE_WORK);
}
protected UserHandle getPersonalProfileUserHandle() {
return UserHandle.of(ActivityManager.getCurrentUser());
return mPersonalProfileUserHandle;
}
protected @Nullable UserHandle getWorkProfileUserHandle() {
return mWorkProfileUserHandle;
}
protected @Nullable UserHandle getCloneProfileUserHandle() {
return mCloneProfileUserHandle;
}
protected UserHandle getTabOwnerUserHandleForLaunch() {
return mTabOwnerUserHandleForLaunch;
}
protected UserHandle fetchPersonalProfileUserHandle() {
mPersonalProfileUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
return mPersonalProfileUserHandle;
}
protected @Nullable UserHandle fetchWorkProfileUserProfile() {
mWorkProfileUserHandle = null;
UserManager userManager = getSystemService(UserManager.class);
for (final UserInfo userInfo : userManager.getProfiles(ActivityManager.getCurrentUser())) {
for (final UserInfo userInfo : userManager
.getProfiles(mPersonalProfileUserHandle.getIdentifier())) {
if (userInfo.isManagedProfile()) {
mWorkProfileUserHandle = userInfo.getUserHandle();
}
@@ -722,10 +753,38 @@ public class ResolverActivity extends Activity implements
return mWorkProfileUserHandle;
}
protected @Nullable UserHandle fetchCloneProfileUserHandle() {
mCloneProfileUserHandle = null;
UserManager userManager = getSystemService(UserManager.class);
for (final UserInfo userInfo :
userManager.getProfiles(mPersonalProfileUserHandle.getIdentifier())) {
if (userInfo.isCloneProfile()) {
mCloneProfileUserHandle = userInfo.getUserHandle();
}
}
return mCloneProfileUserHandle;
}
private UserHandle fetchTabOwnerUserHandleForLaunch() {
if (isLaunchedAsCloneProfile()) {
return getPersonalProfileUserHandle();
}
return mLaunchedFromUserHandle;
}
private boolean hasWorkProfile() {
return getWorkProfileUserHandle() != null;
}
private boolean hasCloneProfile() {
return getCloneProfileUserHandle() != null;
}
private boolean isLaunchedAsCloneProfile() {
return hasCloneProfile()
&& (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier());
}
protected boolean shouldShowTabs() {
return hasWorkProfile() && ENABLE_TABBED_VIEW;
}
@@ -1123,6 +1182,14 @@ public class ResolverActivity extends Activity implements
mAlwaysButton.setEnabled(false);
return;
}
// In case of clonedProfile being active, we do not allow the 'Always' option in the
// disambiguation dialog of Personal Profile as the package manager cannot distinguish
// between cross-profile preferred activities.
if (hasCloneProfile() && !mMultiProfilePagerAdapter
.getCurrentUserHandle().equals(mWorkProfileUserHandle)) {
mAlwaysButton.setEnabled(false);
return;
}
boolean enabled = false;
ResolveInfo ri = null;
if (hasValidSelection) {
@@ -1431,17 +1498,14 @@ public class ResolverActivity extends Activity implements
return true;
}
@VisibleForTesting
public void safelyStartActivity(TargetInfo cti) {
// We're dispatching intents that might be coming from legacy apps, so
// don't kill ourselves.
StrictMode.disableDeathOnFileUriExposure();
try {
UserHandle currentUserHandle = mMultiProfilePagerAdapter.getCurrentUserHandle();
safelyStartActivityInternal(cti, currentUserHandle, null);
} finally {
StrictMode.enableDeathOnFileUriExposure();
}
/** Start the activity specified by the {@link TargetInfo}.*/
public final void safelyStartActivity(TargetInfo cti) {
// In case cloned apps are present, we would want to start those apps in cloned user
// space, which will not be same as adaptor's userHandle. resolveInfo.userHandle
// identifies the correct user space in such cases.
UserHandle activityUserHandle = getResolveInfoUserHandle(
cti.getResolveInfo(), mMultiProfilePagerAdapter.getCurrentUserHandle());
safelyStartActivityAsUser(cti, activityUserHandle, null);
}
/**
@@ -1449,11 +1513,12 @@ public class ResolverActivity extends Activity implements
* @param cti TargetInfo to be launched.
* @param user User to launch this activity as.
*/
@VisibleForTesting
public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user) {
public final void safelyStartActivityAsUser(TargetInfo cti, UserHandle user) {
safelyStartActivityAsUser(cti, user, null);
}
// TODO: Make method public final.
@VisibleForTesting
protected void safelyStartActivityAsUser(
TargetInfo cti, UserHandle user, @Nullable Bundle options) {
// We're dispatching intents that might be coming from legacy apps, so
@@ -1466,7 +1531,8 @@ public class ResolverActivity extends Activity implements
}
}
private void safelyStartActivityInternal(
@VisibleForTesting
protected void safelyStartActivityInternal(
TargetInfo cti, UserHandle user, @Nullable Bundle options) {
// If the target is suspended, the activity will not be successfully launched.
// Do not unregister from package manager updates in this case
@@ -1550,13 +1616,15 @@ public class ResolverActivity extends Activity implements
@VisibleForTesting
protected ResolverListController createListController(UserHandle userHandle) {
UserHandle queryIntentsUser = getQueryIntentsUser(userHandle);
return new ResolverListController(
this,
mPm,
getTargetIntent(),
getReferrerPackageName(),
mLaunchedFromUid,
userHandle);
userHandle,
queryIntentsUser);
}
/**
@@ -2170,16 +2238,10 @@ public class ResolverActivity extends Activity implements
public boolean useLayoutWithDefault() {
// We only use the default app layout when the profile of the active user has a
// filtered item. We always show the same default app even in the inactive user profile.
boolean currentUserAdapterHasFilteredItem;
if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
== UserHandle.myUserId()) {
currentUserAdapterHasFilteredItem =
mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem();
} else {
currentUserAdapterHasFilteredItem =
mMultiProfilePagerAdapter.getInactiveListAdapter().hasFilteredItem();
}
return mSupportsAlwaysUseOption && currentUserAdapterHasFilteredItem;
boolean adapterForCurrentUserHasFilteredItem =
mMultiProfilePagerAdapter.getListAdapterForUserHandle(
getTabOwnerUserHandleForLaunch()).hasFilteredItem();
return mSupportsAlwaysUseOption && adapterForCurrentUserHasFilteredItem;
}
/**
@@ -2198,7 +2260,14 @@ public class ResolverActivity extends Activity implements
return lhs == null ? rhs == null
: lhs.activityInfo == null ? rhs.activityInfo == null
: Objects.equals(lhs.activityInfo.name, rhs.activityInfo.name)
&& Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName);
&& Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName)
// Comparing against resolveInfo.userHandle in case cloned apps are present,
// as they will have the same activityInfo.
&& Objects.equals(
getResolveInfoUserHandle(lhs,
mMultiProfilePagerAdapter.getActiveListAdapter().getUserHandle()),
getResolveInfoUserHandle(rhs,
mMultiProfilePagerAdapter.getActiveListAdapter().getUserHandle()));
}
protected String getMetricsCategory() {
@@ -2439,4 +2508,30 @@ public class ResolverActivity extends Activity implements
}
protected void maybeLogProfileChange() {}
/**
* Returns the {@link UserHandle} to use when querying resolutions for intents in a
* {@link ResolverListController} configured for the provided {@code userHandle}.
*/
protected final UserHandle getQueryIntentsUser(UserHandle userHandle) {
// In case launching app is in clonedProfile, and we are building the personal tab, intent
// resolution will be attempted as clonedUser instead of user 0. This is because intent
// resolution from user 0 and clonedUser is not guaranteed to return same results.
// We do not care about the case when personal adapter is started with non-root user
// (secondary user case), as clone profile is guaranteed to be non-active in that case.
UserHandle queryIntentsUser = userHandle;
if (isLaunchedAsCloneProfile() && userHandle.equals(getPersonalProfileUserHandle())) {
queryIntentsUser = getCloneProfileUserHandle();
}
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;
}
}

View File

@@ -440,6 +440,7 @@ public class ResolverListAdapter extends BaseAdapter {
ri.nonLocalizedLabel = li.getNonLocalizedLabel();
ri.icon = li.getIconResource();
ri.iconResourceId = ri.icon;
ri.userHandle = getUserHandle();
}
if (userManager.isManagedProfile()) {
ri.noResourceId = true;
@@ -737,8 +738,10 @@ public class ResolverListAdapter extends BaseAdapter {
}
Drawable loadIconForResolveInfo(ResolveInfo ri) {
// Load icons based on the current process. If in work profile icons should be badged.
return makePresentationGetter(ri).getIcon(getUserHandle());
// Load icons based on userHandle from ResolveInfo. If in work profile/clone profile, icons
// should be badged.
return makePresentationGetter(ri)
.getIcon(ResolverActivity.getResolveInfoUserHandle(ri, getUserHandle()));
}
void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {

View File

@@ -60,6 +60,7 @@ public class ResolverListController {
private AbstractResolverComparator mResolverComparator;
private boolean isComputed = false;
private final UserHandle mQueryIntentsAsUser;
public ResolverListController(
Context context,
@@ -67,10 +68,11 @@ public class ResolverListController {
Intent targetIntent,
String referrerPackage,
int launchedFromUid,
UserHandle userHandle) {
UserHandle userHandle,
UserHandle queryIntentsAsUser) {
this(context, pm, targetIntent, referrerPackage, launchedFromUid, userHandle,
new ResolverRankerServiceResolverComparator(
context, targetIntent, referrerPackage, null, null));
context, targetIntent, referrerPackage, null, null), queryIntentsAsUser);
}
public ResolverListController(
@@ -80,7 +82,8 @@ public class ResolverListController {
String referrerPackage,
int launchedFromUid,
UserHandle userHandle,
AbstractResolverComparator resolverComparator) {
AbstractResolverComparator resolverComparator,
UserHandle queryIntentsAsUser) {
mContext = context;
mpm = pm;
mLaunchedFromUid = launchedFromUid;
@@ -88,6 +91,7 @@ public class ResolverListController {
mReferrerPackage = referrerPackage;
mUserHandle = userHandle;
mResolverComparator = resolverComparator;
mQueryIntentsAsUser = queryIntentsAsUser;
}
@VisibleForTesting
@@ -113,7 +117,7 @@ public class ResolverListController {
boolean shouldGetOnlyDefaultActivities,
List<Intent> intents) {
return getResolversForIntentAsUser(shouldGetResolvedFilter, shouldGetActivityMetadata,
shouldGetOnlyDefaultActivities, intents, mUserHandle);
shouldGetOnlyDefaultActivities, intents, mQueryIntentsAsUser);
}
public List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUser(
@@ -171,6 +175,10 @@ public class ResolverListController {
final int intoCount = into.size();
for (int i = 0; i < fromCount; i++) {
final ResolveInfo newInfo = from.get(i);
if (newInfo.userHandle == null) {
Log.w(TAG, "Skipping ResolveInfo with no userHandle: " + newInfo);
continue;
}
boolean found = false;
// Only loop to the end of into as it was before we started; no dupes in from.
for (int j = 0; j < intoCount; j++) {

View File

@@ -41,9 +41,10 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
ResolverListAdapter adapter,
EmptyStateProvider emptyStateProvider,
QuietModeManager quietModeManager,
UserHandle workProfileUserHandle) {
UserHandle workProfileUserHandle,
UserHandle cloneUserHandle) {
super(context, /* currentPage */ 0, emptyStateProvider, quietModeManager,
workProfileUserHandle);
workProfileUserHandle, cloneUserHandle);
mItems = new ResolverProfileDescriptor[] {
createProfileDescriptor(adapter)
};
@@ -55,9 +56,10 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
EmptyStateProvider emptyStateProvider,
QuietModeManager quietModeManager,
@Profile int defaultProfile,
UserHandle workProfileUserHandle) {
UserHandle workProfileUserHandle,
UserHandle cloneUserHandle) {
super(context, /* currentPage */ defaultProfile, emptyStateProvider, quietModeManager,
workProfileUserHandle);
workProfileUserHandle, cloneUserHandle);
mItems = new ResolverProfileDescriptor[] {
createProfileDescriptor(personalAdapter),
createProfileDescriptor(workAdapter)
@@ -107,11 +109,12 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
@Override
@Nullable
ResolverListAdapter 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;
}

View File

@@ -29,7 +29,6 @@ import android.os.UserHandle;
import android.util.Pair;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager;
import com.android.internal.app.chooser.TargetInfo;
import com.android.internal.logging.MetricsLogger;
@@ -71,13 +70,14 @@ public class ChooserActivityOverrideData {
public int alternateProfileSetting;
public Resources resources;
public UserHandle workProfileUserHandle;
public UserHandle cloneProfileUserHandle;
public UserHandle tabOwnerUserHandleForLaunch;
public boolean hasCrossProfileIntents;
public boolean isQuietModeEnabled;
public boolean isWorkProfileUserRunning;
public boolean isWorkProfileUserUnlocked;
public Integer myUserId;
public QuietModeManager mQuietModeManager;
public MyUserIdProvider mMyUserIdProvider;
public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
public PackageManager packageManager;
@@ -98,6 +98,8 @@ public class ChooserActivityOverrideData {
alternateProfileSetting = 0;
resources = null;
workProfileUserHandle = null;
cloneProfileUserHandle = null;
tabOwnerUserHandleForLaunch = null;
hasCrossProfileIntents = true;
isQuietModeEnabled = false;
isWorkProfileUserRunning = true;
@@ -126,13 +128,6 @@ public class ChooserActivityOverrideData {
}
};
mMyUserIdProvider = new MyUserIdProvider() {
@Override
public int getMyUserId() {
return myUserId != null ? myUserId : UserHandle.myUserId();
}
};
mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class);
when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt()))
.thenAnswer(invocation -> hasCrossProfileIntents);

View File

@@ -143,7 +143,8 @@ public class ChooserActivityTest {
* `Parameterized` runner.
* --------
*/
private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
.getInstrumentation().getTargetContext().getUser();
private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm;
private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM =
pm -> {
@@ -472,7 +473,7 @@ public class ChooserActivityTest {
List<ResolvedComponentInfo> infosToStack = new ArrayList<>();
for (int i = 0; i < 4; i++) {
ResolveInfo resolveInfo = ResolverDataProvider.createResolveInfo(i,
UserHandle.USER_CURRENT);
UserHandle.USER_CURRENT, PERSONAL_USER_HANDLE);
resolveInfo.activityInfo.applicationInfo.name = appName;
resolveInfo.activityInfo.applicationInfo.packageName = packageName;
resolveInfo.activityInfo.packageName = packageName;
@@ -1329,7 +1330,11 @@ public class ChooserActivityTest {
final DisplayResolveInfo testDri =
activity.createTestDisplayResolveInfo(sendIntent,
ResolverDataProvider.createResolveInfo(3, 0), "testLabel", "testInfo", sendIntent,
ResolverDataProvider.createResolveInfo(
3, 0, PERSONAL_USER_HANDLE),
"testLabel",
"testInfo",
sendIntent,
/* resolveInfoPresentationGetter */ null);
final ChooserListAdapter adapter = activity.getAdapter();
@@ -1450,7 +1455,8 @@ public class ChooserActivityTest {
ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1, "");
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
PERSONAL_USER_HANDLE);
// Start activity
final IChooserWrapper activity = (IChooserWrapper)
@@ -1528,7 +1534,8 @@ public class ChooserActivityTest {
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
PERSONAL_USER_HANDLE);
// Start activity
final IChooserWrapper activity = (IChooserWrapper)
@@ -1606,7 +1613,8 @@ public class ChooserActivityTest {
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
PERSONAL_USER_HANDLE);
// Start activity
final ChooserActivity activity =
@@ -1679,7 +1687,8 @@ public class ChooserActivityTest {
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(2,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
PERSONAL_USER_HANDLE);
// Start activity
final ChooserActivity activity =
@@ -1791,7 +1800,8 @@ public class ChooserActivityTest {
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
resolvedComponentInfos.get(14).getResolveInfoAt(0).activityInfo.packageName);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0,
PERSONAL_USER_HANDLE);
// Start activity
final IChooserWrapper activity = (IChooserWrapper)
@@ -2187,7 +2197,8 @@ public class ChooserActivityTest {
// Create direct share target
List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0,
PERSONAL_USER_HANDLE);
ChooserActivityOverrideData
.getInstance()
@@ -2721,7 +2732,7 @@ public class ChooserActivityTest {
new Intent[] {new Intent("action.fake")});
ChooserActivityOverrideData.getInstance().packageManager = mock(PackageManager.class);
ResolveInfo ri = ResolverDataProvider.createResolveInfo(0,
UserHandle.USER_CURRENT);
UserHandle.USER_CURRENT, PERSONAL_USER_HANDLE);
when(
ChooserActivityOverrideData
.getInstance()
@@ -2886,6 +2897,53 @@ public class ChooserActivityTest {
assertEquals(3, wrapper.getWorkListAdapter().getCount());
}
@Test
public void testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile() {
// enable cloneProfile
markCloneProfileUserAvailable();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
3,
PERSONAL_USER_HANDLE,
ChooserActivityOverrideData.getInstance().cloneProfileUserHandle);
when(ChooserActivityOverrideData.getInstance().resolverListController.getResolversForIntent(
Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.isA(List.class)))
.thenReturn(new ArrayList<>(resolvedComponentInfos));
Intent sendIntent = createSendTextIntent();
final IChooserWrapper activity = (IChooserWrapper) mActivityRule
.launchActivity(Intent.createChooser(sendIntent, "personalProfileTest"));
waitForIdle();
assertThat(activity.getPersonalListAdapter().getUserHandle(), is(PERSONAL_USER_HANDLE));
assertThat(activity.getAdapter().getCount(), is(3));
}
@Test
public void testClonedProfilePresent_personalTabUsesExpectedAdapter() {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
markCloneProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(3);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(
4);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendTextIntent();
sendIntent.setType(TEST_MIME_TYPE);
final IChooserWrapper activity = (IChooserWrapper)
mActivityRule.launchActivity(Intent.createChooser(sendIntent, "multi tab test"));
waitForIdle();
assertThat(activity.getCurrentUserHandle(), is(PERSONAL_USER_HANDLE));
}
private Intent createChooserIntent(Intent intent, Intent[] initialIntents) {
Intent chooserIntent = new Intent();
chooserIntent.setAction(Intent.ACTION_CHOOSER);
@@ -2906,6 +2964,7 @@ public class ChooserActivityTest {
ri.activityInfo.packageName = "fake.package.name";
ri.activityInfo.applicationInfo = new ApplicationInfo();
ri.activityInfo.applicationInfo.packageName = "fake.package.name";
ri.userHandle = UserHandle.CURRENT;
return ri;
}
@@ -2967,7 +3026,23 @@ public class ChooserActivityTest {
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, PERSONAL_USER_HANDLE));
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsWithCloneProfileForTest(
int numberOfResults,
UserHandle resolvedForPersonalUser,
UserHandle resolvedForClonedUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < 1; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
resolvedForPersonalUser));
}
for (int i = 1; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
resolvedForClonedUser));
}
return infoList;
}
@@ -2977,9 +3052,11 @@ public class ChooserActivityTest {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i,
PERSONAL_USER_HANDLE));
} else {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
PERSONAL_USER_HANDLE));
}
}
return infoList;
@@ -2991,9 +3068,11 @@ public class ChooserActivityTest {
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
infoList.add(
ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
PERSONAL_USER_HANDLE));
} else {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
PERSONAL_USER_HANDLE));
}
}
return infoList;
@@ -3003,7 +3082,8 @@ public class ChooserActivityTest {
int numberOfResults, int userId) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
PERSONAL_USER_HANDLE));
}
return infoList;
}
@@ -3097,6 +3177,10 @@ public class ChooserActivityTest {
ChooserActivityOverrideData.getInstance().workProfileUserHandle = UserHandle.of(10);
}
private void markCloneProfileUserAvailable() {
ChooserActivityOverrideData.getInstance().cloneProfileUserHandle = UserHandle.of(11);
}
private void setupResolverControllers(
List<ResolvedComponentInfo> personalResolvedComponentInfos,
List<ResolvedComponentInfo> workResolvedComponentInfos) {

View File

@@ -49,8 +49,8 @@ import androidx.test.espresso.NoMatchingViewException;
import androidx.test.rule.ActivityTestRule;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.app.ChooserActivityWorkProfileTest.TestCase.Tab;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import junit.framework.AssertionFailedError;
@@ -93,7 +93,7 @@ public class ChooserActivityWorkProfileTest {
public void testBlocker() {
setUpPersonalAndWorkComponentInfos();
sOverrides.hasCrossProfileIntents = mTestCase.hasCrossProfileIntents();
sOverrides.myUserId = mTestCase.getMyUserHandle().getIdentifier();
sOverrides.tabOwnerUserHandleForLaunch = mTestCase.getMyUserHandle();
launchActivity(mTestCase.getIsSendAction());
switchToTab(mTestCase.getTab());
@@ -238,19 +238,21 @@ public class ChooserActivityWorkProfileTest {
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
int numberOfResults, int userId) {
int numberOfResults, int userId, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(
ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
ResolverDataProvider
.createResolvedComponentInfoWithOtherId(i, userId, resolvedForUser));
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
return infoList;
}
@@ -262,9 +264,9 @@ public class ChooserActivityWorkProfileTest {
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3,
/* userId */ WORK_USER_HANDLE.getIdentifier());
/* userId */ WORK_USER_HANDLE.getIdentifier(), PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
createResolvedComponentsForTest(workProfileTargets, WORK_USER_HANDLE);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
}

View File

@@ -16,10 +16,6 @@
package com.android.internal.app;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.annotation.Nullable;
@@ -34,12 +30,12 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.util.Pair;
import android.util.Size;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
import com.android.internal.app.chooser.DisplayResolveInfo;
import com.android.internal.app.chooser.TargetInfo;
@@ -131,14 +127,6 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW
return super.isVoiceInteraction();
}
@Override
protected MyUserIdProvider createMyUserIdProvider() {
if (sOverrides.mMyUserIdProvider != null) {
return sOverrides.mMyUserIdProvider;
}
return super.createMyUserIdProvider();
}
@Override
protected CrossProfileIntentsChecker createCrossProfileIntentsChecker() {
if (sOverrides.mCrossProfileIntentsChecker != null) {
@@ -155,13 +143,15 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW
return super.createQuietModeManager();
}
// TODO: Remove this and override safelyStartActivityInternal() instead.
@Override
public void safelyStartActivity(com.android.internal.app.chooser.TargetInfo cti) {
public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user,
@Nullable Bundle options) {
if (sOverrides.onSafelyStartCallback != null &&
sOverrides.onSafelyStartCallback.apply(cti)) {
return;
}
super.safelyStartActivity(cti);
super.safelyStartActivityAsUser(cti, user, options);
}
@Override
@@ -252,6 +242,14 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW
return mMultiProfilePagerAdapter.getCurrentUserHandle();
}
@Override
protected UserHandle getTabOwnerUserHandleForLaunch() {
if (sOverrides.tabOwnerUserHandleForLaunch == null) {
return super.getTabOwnerUserHandleForLaunch();
}
return sOverrides.tabOwnerUserHandleForLaunch;
}
@Override
public Context createContextAsUser(UserHandle user, int flags) {
// return the current context as a work profile doesn't really exist in these tests

View File

@@ -79,6 +79,9 @@ import java.util.List;
*/
@RunWith(AndroidJUnit4.class)
public class ResolverActivityTest {
private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
.getInstrumentation().getTargetContext().getUser();
@Rule
public ActivityTestRule<ResolverWrapperActivity> mActivityRule =
new ActivityTestRule<>(ResolverWrapperActivity.class, false,
@@ -92,7 +95,8 @@ public class ResolverActivityTest {
@Test
public void twoOptionsAndUserSelectsOne() throws InterruptedException {
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -124,7 +128,8 @@ public class ResolverActivityTest {
@Test
public void setMaxHeight() throws Exception {
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -169,7 +174,8 @@ public class ResolverActivityTest {
@Test
public void setShowAtTopToTrue() throws Exception {
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -201,7 +207,8 @@ public class ResolverActivityTest {
@Test
public void hasLastChosenActivity() throws Exception {
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2,
PERSONAL_USER_HANDLE);
ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -234,10 +241,12 @@ public class ResolverActivityTest {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
PERSONAL_USER_HANDLE);
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
ResolveInfo toChoose = personalResolvedComponentInfos.get(1).getResolveInfoAt(0);
Intent sendIntent = createSendImageIntent();
@@ -255,7 +264,8 @@ public class ResolverActivityTest {
};
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10);
createResolvedComponentsForTestWithOtherProfile(2, /* userId= */ 10,
PERSONAL_USER_HANDLE);
// We pick the first one as there is another one in the work profile side
onView(first(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name)))
.perform(click());
@@ -272,7 +282,7 @@ public class ResolverActivityTest {
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3);
createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -298,7 +308,7 @@ public class ResolverActivityTest {
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2);
createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
.perform(click());
@@ -317,7 +327,7 @@ public class ResolverActivityTest {
// chosen activity.
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3);
createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
@@ -345,7 +355,7 @@ public class ResolverActivityTest {
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2);
createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
.perform(click());
@@ -428,12 +438,14 @@ public class ResolverActivityTest {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId = */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(3, /* userId = */ 10,
PERSONAL_USER_HANDLE);
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos,
new ArrayList<>(workResolvedComponentInfos));
Intent sendIntent = createSendImageIntent();
markWorkProfileUserAvailable();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
@@ -448,11 +460,13 @@ public class ResolverActivityTest {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
PERSONAL_USER_HANDLE);
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
markWorkProfileUserAvailable();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
@@ -467,11 +481,12 @@ public class ResolverActivityTest {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(3, PERSONAL_USER_HANDLE);
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
markWorkProfileUserAvailable();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
@@ -487,8 +502,10 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -507,8 +524,10 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
ResolveInfo[] chosen = new ResolveInfo[1];
@@ -539,8 +558,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(1);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -559,8 +579,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(1);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createOpenWebsiteIntent();
@@ -578,8 +599,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(1);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(1, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createOpenWebsiteIntent();
@@ -605,8 +627,10 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId= */ 10);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
createResolvedComponentsForTestWithOtherProfile(3, /* userId= */ 10,
PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
ResolveInfo[] chosen = new ResolveInfo[1];
@@ -639,9 +663,11 @@ public class ResolverActivityTest {
markWorkProfileUserAvailable();
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
createResolvedComponentsForTest(workProfileTargets,
sOverrides.workProfileUserHandle);
sOverrides.hasCrossProfileIntents = false;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -665,9 +691,11 @@ public class ResolverActivityTest {
markWorkProfileUserAvailable();
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10);
createResolvedComponentsForTestWithOtherProfile(3, /* userId */ 10,
PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
createResolvedComponentsForTest(workProfileTargets,
sOverrides.workProfileUserHandle);
sOverrides.isQuietModeEnabled = true;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -690,9 +718,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(3);
createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(0);
createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -714,9 +742,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(3);
createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(0);
createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -739,9 +767,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(1);
createResolvedComponentsForTest(1, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(1);
createResolvedComponentsForTest(1, sOverrides.workProfileUserHandle);
// Personal profile only has a browser
personalResolvedComponentInfos.get(0).getResolveInfoAt(0).handleAllWebDataURI = true;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
@@ -758,9 +786,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(0);
createResolvedComponentsForTest(0, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(1);
createResolvedComponentsForTest(1, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -787,9 +815,9 @@ public class ResolverActivityTest {
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(3);
createResolvedComponentsForTest(3, PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(0);
createResolvedComponentsForTest(0, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
@@ -810,7 +838,8 @@ public class ResolverActivityTest {
public void testAutolaunch_singleTarget_withWorkProfileAndTabbedViewOff_noAutolaunch() {
ResolverActivity.ENABLE_TABBED_VIEW = false;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -835,7 +864,7 @@ public class ResolverActivityTest {
public void testAutolaunch_singleTarget_noWorkProfile_autolaunch() {
ResolverActivity.ENABLE_TABBED_VIEW = false;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTest(1);
createResolvedComponentsForTest(1, PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -863,9 +892,11 @@ public class ResolverActivityTest {
markWorkProfileUserAvailable();
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10);
createResolvedComponentsForTestWithOtherProfile(2, /* userId */ 10,
PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
createResolvedComponentsForTest(workProfileTargets,
sOverrides.workProfileUserHandle);
sOverrides.hasCrossProfileIntents = false;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
@@ -892,7 +923,7 @@ public class ResolverActivityTest {
// chosen activity.
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsForTest(2);
createResolvedComponentsForTest(2, PERSONAL_USER_HANDLE);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
@@ -911,6 +942,193 @@ public class ResolverActivityTest {
assertThat(activity.getAdapter().getPlaceholderCount(), is(2));
}
@Test
public void testClonedProfilePresent_personalAdapterIsSetWithPersonalProfile() {
// enable cloneProfile
markCloneProfileUserAvailable();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
3,
PERSONAL_USER_HANDLE,
sOverrides.cloneProfileUserHandle);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
assertThat(activity.getCurrentUserHandle(), is(activity.getPersonalProfileUserHandle()));
assertThat(activity.getAdapter().getCount(), is(3));
}
@Test
public void testClonedProfilePresent_personalTabUsesExpectedAdapter() {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
// enable cloneProfile
markCloneProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
3,
PERSONAL_USER_HANDLE,
sOverrides.cloneProfileUserHandle);
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4,
sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
assertThat(activity.getCurrentUserHandle(), is(activity.getPersonalProfileUserHandle()));
assertThat(activity.getAdapter().getCount(), is(3));
}
@Test
public void testClonedProfilePresent_layoutWithDefault_neverShown() throws Exception {
// enable cloneProfile
markCloneProfileUserAvailable();
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
2,
PERSONAL_USER_HANDLE,
sOverrides.cloneProfileUserHandle);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
when(sOverrides.resolverListController.getLastChosen())
.thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
waitForIdle();
assertThat(activity.getAdapter().hasFilteredItem(), is(false));
assertThat(activity.getAdapter().getCount(), is(2));
assertThat(activity.getAdapter().getPlaceholderCount(), is(2));
}
@Test
public void testClonedProfilePresent_alwaysButtonDisabled() throws Exception {
// enable cloneProfile
markCloneProfileUserAvailable();
Intent sendIntent = createSendImageIntent();
List<ResolvedComponentInfo> resolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
3,
PERSONAL_USER_HANDLE,
sOverrides.cloneProfileUserHandle);
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.anyBoolean(),
Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
when(sOverrides.resolverListController.getLastChosen())
.thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
// Confirm that the button bar is disabled by default
onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
onView(withId(R.id.button_always)).check(matches(not(isEnabled())));
// Make a stable copy of the components as the original list may be modified
List<ResolvedComponentInfo> stableCopy =
createResolvedComponentsForTestWithOtherProfile(2, PERSONAL_USER_HANDLE);
onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
.perform(click());
onView(withId(R.id.button_once)).check(matches(isEnabled()));
onView(withId(R.id.button_always)).check(matches(not(isEnabled())));
}
@Test
public void testClonedProfilePresent_personalProfileActivityIsStartedInCorrectUser()
throws Exception {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
// enable cloneProfile
markCloneProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
3,
PERSONAL_USER_HANDLE,
sOverrides.cloneProfileUserHandle);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(3, sOverrides.workProfileUserHandle);
sOverrides.hasCrossProfileIntents = false;
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
sOverrides.onSafelyStartInternalCallback = userHandle -> {
selectedActivityUserHandle[0] = userHandle;
return true;
};
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
onView(first(allOf(withText(personalResolvedComponentInfos.get(0)
.getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
.perform(click());
onView(withId(R.id.button_once))
.perform(click());
waitForIdle();
assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
}
@Test
public void testClonedProfilePresent_workProfileActivityIsStartedInCorrectUser()
throws Exception {
// enable the work tab feature flag
ResolverActivity.ENABLE_TABBED_VIEW = true;
markWorkProfileUserAvailable();
// enable cloneProfile
markCloneProfileUserAvailable();
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsWithCloneProfileForTest(
3,
PERSONAL_USER_HANDLE,
sOverrides.cloneProfileUserHandle);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(3, sOverrides.workProfileUserHandle);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
Intent sendIntent = createSendImageIntent();
sendIntent.setType("TestType");
final UserHandle[] selectedActivityUserHandle = new UserHandle[1];
sOverrides.onSafelyStartInternalCallback = userHandle -> {
selectedActivityUserHandle[0] = userHandle;
return true;
};
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
waitForIdle();
onView(withText(R.string.resolver_work_tab))
.perform(click());
waitForIdle();
onView(first(allOf(withText(workResolvedComponentInfos.get(0)
.getResolveInfoAt(0).activityInfo.applicationInfo.name), isCompletelyDisplayed())))
.perform(click());
onView(withId(R.id.button_once))
.perform(click());
waitForIdle();
assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle()));
}
private Intent createSendImageIntent() {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
@@ -926,36 +1144,55 @@ public class ResolverActivityTest {
return sendIntent;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsWithCloneProfileForTest(
int numberOfResults,
UserHandle resolvedForPersonalUser,
UserHandle resolvedForClonedUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < 1; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
resolvedForPersonalUser));
}
for (int i = 1; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i,
resolvedForClonedUser));
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
int numberOfResults) {
int numberOfResults, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i,
resolvedForUser));
} else {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
int numberOfResults, int userId) {
int numberOfResults, int userId, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
if (i == 0) {
infoList.add(
ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId,
resolvedForUser));
} else {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
}
return infoList;
@@ -969,6 +1206,10 @@ public class ResolverActivityTest {
ResolverWrapperActivity.sOverrides.workProfileUserHandle = UserHandle.of(10);
}
private void markCloneProfileUserAvailable() {
ResolverWrapperActivity.sOverrides.cloneProfileUserHandle = UserHandle.of(11);
}
private void setupResolverControllers(
List<ResolvedComponentInfo> personalResolvedComponentInfos,
List<ResolvedComponentInfo> workResolvedComponentInfos) {

View File

@@ -92,7 +92,7 @@ public class ResolverActivityWorkProfileTest {
public void testBlocker() {
setUpPersonalAndWorkComponentInfos();
sOverrides.hasCrossProfileIntents = mTestCase.hasCrossProfileIntents();
sOverrides.myUserId = mTestCase.getMyUserHandle().getIdentifier();
sOverrides.tabOwnerUserHandleForLaunch = mTestCase.getMyUserHandle();
launchActivity(/* callingUser= */ mTestCase.getExtraCallingUser());
switchToTab(mTestCase.getTab());
@@ -230,19 +230,21 @@ public class ResolverActivityWorkProfileTest {
}
private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
int numberOfResults, int userId) {
int numberOfResults, int userId, UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(
ResolverDataProvider.createResolvedComponentInfoWithOtherId(i, userId));
ResolverDataProvider
.createResolvedComponentInfoWithOtherId(i, userId, resolvedForUser));
}
return infoList;
}
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults,
UserHandle resolvedForUser) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, resolvedForUser));
}
return infoList;
}
@@ -254,9 +256,9 @@ public class ResolverActivityWorkProfileTest {
int workProfileTargets = 4;
List<ResolvedComponentInfo> personalResolvedComponentInfos =
createResolvedComponentsForTestWithOtherProfile(3,
/* userId */ WORK_USER_HANDLE.getIdentifier());
/* userId */ WORK_USER_HANDLE.getIdentifier(), PERSONAL_USER_HANDLE);
List<ResolvedComponentInfo> workResolvedComponentInfos =
createResolvedComponentsForTest(workProfileTargets);
createResolvedComponentsForTest(workProfileTargets, WORK_USER_HANDLE);
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
}

View File

@@ -36,20 +36,24 @@ class ResolverDataProvider {
static private int USER_SOMEONE_ELSE = 10;
static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfo(int i) {
return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
createResolverIntent(i), createResolveInfo(i, UserHandle.USER_CURRENT));
}
static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i) {
return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
createResolverIntent(i), createResolveInfo(i, USER_SOMEONE_ELSE));
static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfo(int i,
UserHandle resolvedForUser) {
return new ResolverActivity.ResolvedComponentInfo(
createComponentName(i),
createResolverIntent(i),
createResolveInfo(i, UserHandle.USER_CURRENT, resolvedForUser));
}
static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i,
int userId) {
UserHandle resolvedForUser) {
return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
createResolverIntent(i), createResolveInfo(i, userId));
createResolverIntent(i), createResolveInfo(i, USER_SOMEONE_ELSE, resolvedForUser));
}
static ResolverActivity.ResolvedComponentInfo createResolvedComponentInfoWithOtherId(int i,
int userId, UserHandle resolvedForUser) {
return new ResolverActivity.ResolvedComponentInfo(createComponentName(i),
createResolverIntent(i), createResolveInfo(i, userId, resolvedForUser));
}
static ComponentName createComponentName(int i) {
@@ -57,10 +61,11 @@ class ResolverDataProvider {
return new ComponentName("foo.bar." + name, name);
}
static ResolveInfo createResolveInfo(int i, int userId) {
static ResolveInfo createResolveInfo(int i, int userId, UserHandle resolvedForUser) {
final ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.activityInfo = createActivityInfo(i);
resolveInfo.targetUserId = userId;
resolveInfo.userHandle = resolvedForUser;
return resolveInfo;
}

View File

@@ -44,6 +44,7 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArrayMap;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
@@ -75,6 +76,8 @@ public class ResolverListControllerTest {
private ResolverListController mController;
private UsageStatsManager mUsm;
private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
.getInstrumentation().getTargetContext().getUser();
@Before
public void setUp() throws Exception {
@@ -119,7 +122,8 @@ public class ResolverListControllerTest {
anyString(), anyInt(), anyString(), any(), anyString());
when(mMockContext.getOpPackageName()).thenReturn(refererPackage);
mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM);
refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM,
UserHandle.SYSTEM);
mController.sort(new ArrayList<ResolvedComponentInfo>());
long beforeReport = getCount(mUsm, packageName, action, annotation);
mController.updateChooserCounts(packageName, UserHandle.USER_CURRENT, action);
@@ -134,7 +138,8 @@ public class ResolverListControllerTest {
String refererPackage = "test_referer_package";
List<ResolvedComponentInfo> resolvedComponents = createResolvedComponentsForTest(10);
mController = new ResolverListController(mMockContext, mMockPackageManager, sendIntent,
refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM);
refererPackage, UserHandle.USER_CURRENT, /* userHandle */ UserHandle.SYSTEM,
UserHandle.SYSTEM);
List<ResolvedComponentInfo> topKList = new ArrayList<>(resolvedComponents);
mController.topK(topKList, 5);
List<ResolvedComponentInfo> sortList = new ArrayList<>(topKList);
@@ -157,12 +162,13 @@ public class ResolverListControllerTest {
public void getResolversForIntent_usesResultsFromPackageManager() {
mockStats();
List<ResolveInfo> infos = new ArrayList<>();
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT));
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
PERSONAL_USER_HANDLE));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
/* userHandle= */ UserHandle.SYSTEM);
/* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
@@ -181,12 +187,13 @@ public class ResolverListControllerTest {
public void getResolversForIntent_shouldGetOnlyDefaultActivitiesTrue_addsFlag() {
mockStats();
List<ResolveInfo> infos = new ArrayList<>();
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT));
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
PERSONAL_USER_HANDLE));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
/* userHandle= */ UserHandle.SYSTEM);
/* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
@@ -205,12 +212,13 @@ public class ResolverListControllerTest {
public void getResolversForIntent_shouldGetOnlyDefaultActivitiesFalse_doesNotAddFlag() {
mockStats();
List<ResolveInfo> infos = new ArrayList<>();
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT));
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
PERSONAL_USER_HANDLE));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
/* userHandle= */ UserHandle.SYSTEM);
/* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
@@ -225,6 +233,32 @@ public class ResolverListControllerTest {
doesNotContainFlag(PackageManager.MATCH_DEFAULT_ONLY), any());
}
@Test
public void testResolveInfoWithNoUserHandle_isNotAddedToResults()
throws Exception {
List<ResolveInfo> infos = new ArrayList<>();
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT,
PERSONAL_USER_HANDLE));
infos.add(ResolverDataProvider.createResolveInfo(0, UserHandle.USER_CURRENT, null));
when(mMockPackageManager.queryIntentActivitiesAsUser(any(), anyInt(),
any(UserHandle.class))).thenReturn(infos);
mController = new ResolverListController(mMockContext, mMockPackageManager,
createSendImageIntent("test"), null, UserHandle.USER_CURRENT,
/* userHandle= */ UserHandle.SYSTEM, UserHandle.SYSTEM);
List<Intent> intents = new ArrayList<>();
intents.add(createActionMainIntent());
List<ResolverActivity.ResolvedComponentInfo> result = mController
.getResolversForIntent(
/* shouldGetResolvedFilter= */ true,
/* shouldGetActivityMetadata= */ true,
/* shouldGetOnlyDefaultActivities= */ false,
intents);
assertThat(result.size(), is(1));
}
private int containsFlag(int flag) {
return intThat(new FlagMatcher(flag, /* contains= */ true));
}
@@ -308,7 +342,7 @@ public class ResolverListControllerTest {
private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
for (int i = 0; i < numberOfResults; i++) {
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
infoList.add(ResolverDataProvider.createResolvedComponentInfo(i, PERSONAL_USER_HANDLE));
}
return infoList;
}

View File

@@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.annotation.Nullable;
import android.app.usage.UsageStatsManager;
import android.content.Context;
import android.content.Intent;
@@ -30,7 +31,6 @@ import android.os.Bundle;
import android.os.UserHandle;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider;
import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager;
import com.android.internal.app.chooser.TargetInfo;
@@ -56,14 +56,6 @@ public class ResolverWrapperActivity extends ResolverActivity {
filterLastUsed, createListController(userHandle), this);
}
@Override
protected MyUserIdProvider createMyUserIdProvider() {
if (sOverrides.mMyUserIdProvider != null) {
return sOverrides.mMyUserIdProvider;
}
return super.createMyUserIdProvider();
}
@Override
protected CrossProfileIntentsChecker createCrossProfileIntentsChecker() {
if (sOverrides.mCrossProfileIntentsChecker != null) {
@@ -103,13 +95,25 @@ public class ResolverWrapperActivity extends ResolverActivity {
return super.isVoiceInteraction();
}
// TODO: Remove this and override safelyStartActivityInternal() instead.
@Override
public void safelyStartActivity(TargetInfo cti) {
public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user,
@Nullable Bundle options) {
if (sOverrides.onSafelyStartCallback != null &&
sOverrides.onSafelyStartCallback.apply(cti)) {
return;
}
super.safelyStartActivity(cti);
super.safelyStartActivityAsUser(cti, user, options);
}
@Override
public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
@Nullable Bundle options) {
if (sOverrides.onSafelyStartInternalCallback != null
&& sOverrides.onSafelyStartInternalCallback.apply(user)) {
return;
}
super.safelyStartActivityInternal(cti, user, options);
}
@Override
@@ -134,11 +138,29 @@ public class ResolverWrapperActivity extends ResolverActivity {
return mMultiProfilePagerAdapter.getCurrentUserHandle();
}
@Override
protected UserHandle getPersonalProfileUserHandle() {
return super.getPersonalProfileUserHandle();
}
@Override
protected UserHandle getWorkProfileUserHandle() {
return sOverrides.workProfileUserHandle;
}
@Override
protected UserHandle getCloneProfileUserHandle() {
return sOverrides.cloneProfileUserHandle;
}
@Override
protected UserHandle getTabOwnerUserHandleForLaunch() {
if (sOverrides.tabOwnerUserHandleForLaunch == null) {
return super.getTabOwnerUserHandleForLaunch();
}
return sOverrides.tabOwnerUserHandleForLaunch;
}
@Override
public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
super.startActivityAsUser(intent, options, user);
@@ -153,24 +175,29 @@ public class ResolverWrapperActivity extends ResolverActivity {
@SuppressWarnings("Since15")
public Function<PackageManager, PackageManager> createPackageManager;
public Function<TargetInfo, Boolean> onSafelyStartCallback;
public Function<UserHandle, Boolean> onSafelyStartInternalCallback;
public ResolverListController resolverListController;
public ResolverListController workResolverListController;
public Boolean isVoiceInteraction;
public UserHandle workProfileUserHandle;
public UserHandle cloneProfileUserHandle;
public UserHandle tabOwnerUserHandleForLaunch;
public Integer myUserId;
public boolean hasCrossProfileIntents;
public boolean isQuietModeEnabled;
public QuietModeManager mQuietModeManager;
public MyUserIdProvider mMyUserIdProvider;
public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
public void reset() {
onSafelyStartCallback = null;
onSafelyStartInternalCallback = null;
isVoiceInteraction = null;
createPackageManager = null;
resolverListController = mock(ResolverListController.class);
workResolverListController = mock(ResolverListController.class);
workProfileUserHandle = null;
cloneProfileUserHandle = null;
tabOwnerUserHandleForLaunch = null;
myUserId = null;
hasCrossProfileIntents = true;
isQuietModeEnabled = false;
@@ -197,13 +224,6 @@ public class ResolverWrapperActivity extends ResolverActivity {
}
};
mMyUserIdProvider = new MyUserIdProvider() {
@Override
public int getMyUserId() {
return myUserId != null ? myUserId : UserHandle.myUserId();
}
};
mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class);
when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt()))
.thenAnswer(invocation -> hasCrossProfileIntents);