From b8362e906fcb77d80fb408313dd760ea6b3eda85 Mon Sep 17 00:00:00 2001 From: Himanshu Gupta Date: Tue, 24 Jan 2023 18:01:39 +0000 Subject: [PATCH] App Cloning fixes for Sharesheet This Cl adds the following: 1. Fixes a bug where if a cloned app has initialIntents and launches sharesheet, initialIntents would always resolve in user 0 (personalProfileHandle) instead of clonedProfileHandle 2. TODOs mentioned in ag/20982903 addressed. 3. Test cases added. Test: atest ChooserActivityTest, atest ResolverActivityTest Change-Id: Iedb24d8775d08319b136d96d7ffff1665a1b0748 --- .../android/internal/app/ChooserActivity.java | 17 +++-- .../internal/app/ChooserListAdapter.java | 15 +++- .../internal/app/ResolverActivity.java | 43 +++++++---- .../internal/app/ResolverListAdapter.java | 12 ++- .../app/ChooserActivityOverrideData.java | 4 +- .../internal/app/ChooserActivityTest.java | 26 +++---- .../internal/app/ChooserListAdapterTest.kt | 8 +- .../internal/app/ChooserWrapperActivity.java | 15 ++-- .../internal/app/ResolverActivityTest.java | 75 +++++++++++++------ .../internal/app/ResolverWrapperActivity.java | 26 +++---- .../internal/app/ResolverWrapperAdapter.java | 6 +- 11 files changed, 154 insertions(+), 93 deletions(-) diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index f257f1c9b7cec..7c237e69256f7 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -2525,8 +2525,7 @@ public class ChooserActivity extends ResolverActivity implements List payloadIntents, Intent[] initialIntents, List rList, boolean filterLastUsed, UserHandle userHandle) { ChooserListAdapter chooserListAdapter = createChooserListAdapter(context, payloadIntents, - initialIntents, rList, filterLastUsed, - createListController(userHandle)); + initialIntents, rList, filterLastUsed, userHandle); AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter); AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback); chooserListAdapter.setAppPredictor(appPredictor); @@ -2536,12 +2535,18 @@ public class ChooserActivity extends ResolverActivity implements @VisibleForTesting public ChooserListAdapter createChooserListAdapter(Context context, - List payloadIntents, Intent[] initialIntents, List rList, - boolean filterLastUsed, ResolverListController resolverListController) { + List payloadIntents, + Intent[] initialIntents, + List rList, + boolean filterLastUsed, + UserHandle userHandle) { + UserHandle initialIntentsUserSpace = isLaunchedAsCloneProfile() + && userHandle.equals(getPersonalProfileUserHandle()) + ? getCloneProfileUserHandle() : userHandle; return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, - filterLastUsed, resolverListController, this, + filterLastUsed, createListController(userHandle), this, this, context.getPackageManager(), - getChooserActivityLogger()); + getChooserActivityLogger(), initialIntentsUserSpace); } @VisibleForTesting diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index e0568cfe65608..681bc7a0a03fa 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -105,6 +105,9 @@ public class ChooserListAdapter extends ResolverListAdapter { private AppPredictor mAppPredictor; private AppPredictor.Callback mAppPredictorCallback; + // Represents the UserSpace in which the Initial Intents should be resolved. + private final UserHandle mInitialIntentsUserSpace; + // For pinned direct share labels, if the text spans multiple lines, the TextView will consume // the full width, even if the characters actually take up less than that. Measure the actual // line widths and constrain the View's width based upon that so that the pin doesn't end up @@ -142,11 +145,12 @@ public class ChooserListAdapter extends ResolverListAdapter { ChooserListCommunicator chooserListCommunicator, SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator, PackageManager packageManager, - ChooserActivityLogger chooserActivityLogger) { + ChooserActivityLogger chooserActivityLogger, + UserHandle initialIntentsUserSpace) { // Don't send the initial intents through the shared ResolverActivity path, // we want to separate them into a different section. super(context, payloadIntents, null, rList, filterLastUsed, - resolverListController, chooserListCommunicator, false); + resolverListController, chooserListCommunicator, false, initialIntentsUserSpace); mMaxShortcutTargetsPerApp = context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp); @@ -154,6 +158,7 @@ public class ChooserListAdapter extends ResolverListAdapter { createPlaceHolders(); mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator; mChooserActivityLogger = chooserActivityLogger; + mInitialIntentsUserSpace = initialIntentsUserSpace; if (initialIntents != null) { for (int i = 0; i < initialIntents.length; i++) { @@ -197,7 +202,7 @@ public class ChooserListAdapter extends ResolverListAdapter { ri.nonLocalizedLabel = li.getNonLocalizedLabel(); ri.icon = li.getIconResource(); ri.iconResourceId = ri.icon; - ri.userHandle = getUserHandle(); + ri.userHandle = mInitialIntentsUserSpace; } if (userManager.isManagedProfile()) { ri.noResourceId = true; @@ -351,6 +356,10 @@ public class ChooserListAdapter extends ResolverListAdapter { // Consolidate multiple targets from same app. Map consolidated = new HashMap<>(); for (DisplayResolveInfo info : allTargets) { + if (info.getResolveInfo().userHandle == null) { + Log.e(TAG, "ResolveInfo with null UserHandle found: " + + info.getResolveInfo()); + } String resolvedTarget = info.getResolvedComponentName().getPackageName() + '#' + info.getDisplayLabel() + '#' + ResolverActivity.getResolveInfoUserHandle( diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 992e243060fc4..d6a515ae2da29 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -33,6 +33,8 @@ import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_S import static android.stats.devicepolicy.nano.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PROTECTED; + import android.annotation.Nullable; import android.annotation.StringRes; import android.annotation.UiThread; @@ -780,7 +782,7 @@ public class ResolverActivity extends Activity implements return getCloneProfileUserHandle() != null; } - private boolean isLaunchedAsCloneProfile() { + protected final boolean isLaunchedAsCloneProfile() { return hasCloneProfile() && (UserHandle.myUserId() == getCloneProfileUserHandle().getIdentifier()); } @@ -1517,9 +1519,7 @@ public class ResolverActivity extends Activity implements safelyStartActivityAsUser(cti, user, null); } - // TODO: Make method public final. - @VisibleForTesting - protected void safelyStartActivityAsUser( + protected final void safelyStartActivityAsUser( TargetInfo cti, UserHandle user, @Nullable Bundle options) { // We're dispatching intents that might be coming from legacy apps, so // don't kill ourselves. @@ -1609,9 +1609,12 @@ public class ResolverActivity extends Activity implements Intent startIntent = getIntent(); boolean isAudioCaptureDevice = startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false); + UserHandle initialIntentsUserSpace = isLaunchedAsCloneProfile() + && userHandle.equals(getPersonalProfileUserHandle()) + ? getCloneProfileUserHandle() : userHandle; return new ResolverListAdapter(context, payloadIntents, initialIntents, rList, filterLastUsed, createListController(userHandle), this, - isAudioCaptureDevice); + isAudioCaptureDevice, initialIntentsUserSpace); } @VisibleForTesting @@ -2535,20 +2538,18 @@ public class ResolverActivity extends Activity implements return queryIntentsUser; } - /** - * This function is temporary in nature, and its usages will be replaced with just - * resolveInfo.userHandle, once it is available, once sharesheet is stable. - */ - public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo, - UserHandle predictedHandle) { - return resolveInfo.userHandle; - } - /** * Returns the {@link List} of {@link UserHandle} to pass on to the * {@link ResolverRankerServiceResolverComparator} as per the provided {@code userHandle}. */ - protected final List getResolverRankerServiceUserHandleList(UserHandle userHandle) { + @VisibleForTesting(visibility = PROTECTED) + public final List getResolverRankerServiceUserHandleList(UserHandle userHandle) { + return getResolverRankerServiceUserHandleListInternal(userHandle); + } + + @VisibleForTesting + protected List getResolverRankerServiceUserHandleListInternal(UserHandle + userHandle) { List userList = new ArrayList<>(); userList.add(userHandle); // Add clonedProfileUserHandle to the list only if we are: @@ -2560,4 +2561,16 @@ public class ResolverActivity extends Activity implements } return userList; } + + /** + * This function is temporary in nature, and its usages will be replaced with just + * resolveInfo.userHandle, once it is available, once sharesheet is stable. + */ + public static UserHandle getResolveInfoUserHandle(ResolveInfo resolveInfo, + UserHandle predictedHandle) { + if (resolveInfo.userHandle == null) { + Log.e(TAG, "ResolveInfo with null UserHandle found: " + resolveInfo); + } + return resolveInfo.userHandle; + } } diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 2df2b2bec2f80..0ea60a7ddbfe2 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -91,13 +91,16 @@ public class ResolverListAdapter extends BaseAdapter { private boolean mIsTabLoaded; private final Map mIconLoaders = new HashMap<>(); private final Map mLabelLoaders = new HashMap<>(); + // Represents the UserSpace in which the Initial Intents should be resolved. + private final UserHandle mInitialIntentsUserSpace; public ResolverListAdapter(Context context, List payloadIntents, Intent[] initialIntents, List rList, boolean filterLastUsed, ResolverListController resolverListController, ResolverListCommunicator resolverListCommunicator, - boolean isAudioCaptureDevice) { + boolean isAudioCaptureDevice, + UserHandle initialIntentsUserSpace) { mContext = context; mIntents = payloadIntents; mInitialIntents = initialIntents; @@ -111,6 +114,11 @@ public class ResolverListAdapter extends BaseAdapter { mIsAudioCaptureDevice = isAudioCaptureDevice; final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE); mIconDpi = am.getLauncherLargeIconDensity(); + mInitialIntentsUserSpace = initialIntentsUserSpace; + } + + public ResolverListController getResolverListController() { + return mResolverListController; } public void handlePackagesChanged() { @@ -439,7 +447,7 @@ public class ResolverListAdapter extends BaseAdapter { ri.nonLocalizedLabel = li.getNonLocalizedLabel(); ri.icon = li.getIconResource(); ri.iconResourceId = ri.icon; - ri.userHandle = getUserHandle(); + ri.userHandle = mInitialIntentsUserSpace; } if (userManager.isManagedProfile()) { ri.noResourceId = true; diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java index 5469843f3f9a6..7d2d6e07a88c1 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityOverrideData.java @@ -53,7 +53,7 @@ public class ChooserActivityOverrideData { @SuppressWarnings("Since15") public Function createPackageManager; - public Function onSafelyStartCallback; + public Function onSafelyStartInternalCallback; public Function onQueryDirectShareTargets; public BiFunction< IChooserWrapper, ChooserListAdapter, Pair> @@ -82,7 +82,7 @@ public class ChooserActivityOverrideData { public PackageManager packageManager; public void reset() { - onSafelyStartCallback = null; + onSafelyStartInternalCallback = null; onQueryDirectShareTargets = null; directShareTargets = null; isVoiceInteraction = null; diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java index c06df9455e07f..9f398ecf5492a 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java @@ -446,7 +446,7 @@ public class ChooserActivityTest { onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist()); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -501,7 +501,7 @@ public class ChooserActivityTest { assertThat(activity.getAdapter().getCount(), is(6)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -541,7 +541,7 @@ public class ChooserActivityTest { verify(ChooserActivityOverrideData.getInstance().resolverListController, times(1)) .topK(any(List.class), anyInt()); assertThat(activity.getIsSelected(), is(false)); - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { return true; }; ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0); @@ -592,7 +592,7 @@ public class ChooserActivityTest { @Test public void autoLaunchSingleResult() throws InterruptedException { ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -638,7 +638,7 @@ public class ChooserActivityTest { assertThat(activity.getAdapter().getCount(), is(1)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -681,7 +681,7 @@ public class ChooserActivityTest { assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -719,7 +719,7 @@ public class ChooserActivityTest { assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -1949,7 +1949,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2127,7 +2127,7 @@ public class ChooserActivityTest { onView(withIdFromRuntimeResource("profile_button")).check(doesNotExist()); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2513,7 +2513,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2543,7 +2543,7 @@ public class ChooserActivityTest { Intent sendIntent = createSendTextIntent(); sendIntent.setType(TEST_MIME_TYPE); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2569,7 +2569,7 @@ public class ChooserActivityTest { setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendTextIntent(); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; @@ -2597,7 +2597,7 @@ public class ChooserActivityTest { Intent chooserIntent = createChooserIntent(createSendTextIntent(), new Intent[] {new Intent("action.fake")}); ResolveInfo[] chosen = new ResolveInfo[1]; - ChooserActivityOverrideData.getInstance().onSafelyStartCallback = targetInfo -> { + ChooserActivityOverrideData.getInstance().onSafelyStartInternalCallback = targetInfo -> { chosen[0] = targetInfo.getResolveInfo(); return true; }; diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt index 8218b9869b5d1..2eeaf53ef1468 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt +++ b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt @@ -22,6 +22,7 @@ import android.content.Intent import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.os.Bundle +import android.os.UserHandle import android.service.chooser.ChooserTarget import android.view.View import android.widget.FrameLayout @@ -73,7 +74,8 @@ class ChooserListAdapterTest { selectableTargetInfoCommunicator, packageManager, chooserActivityLogger, - taskProvider + null, + taskProvider, ) @Test @@ -160,6 +162,7 @@ private class ChooserListAdapterOverride( selectableTargetInfoCommunicator: SelectableTargetInfoCommunicator?, packageManager: PackageManager?, chooserActivityLogger: ChooserActivityLogger?, + initialIntentsUserHandle: UserHandle?, private val taskProvider: (SelectableTargetInfo?) -> LoadDirectShareIconTask ) : ChooserListAdapter( context, @@ -171,7 +174,8 @@ private class ChooserListAdapterOverride( chooserListCommunicator, selectableTargetInfoCommunicator, packageManager, - chooserActivityLogger + chooserActivityLogger, + initialIntentsUserHandle, ) { override fun createLoadDirectShareIconTask( info: SelectableTargetInfo? diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java index d7a8b3a5c1d9b..dcea9120e2a5c 100644 --- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java @@ -64,14 +64,14 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW @Override public ChooserListAdapter createChooserListAdapter(Context context, List payloadIntents, Intent[] initialIntents, List rList, boolean filterLastUsed, - ResolverListController resolverListController) { + UserHandle userHandle) { PackageManager packageManager = sOverrides.packageManager == null ? context.getPackageManager() : sOverrides.packageManager; return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, - filterLastUsed, resolverListController, + filterLastUsed, createListController(userHandle), this, this, packageManager, - getChooserActivityLogger()); + getChooserActivityLogger(), userHandle); } @Override @@ -143,15 +143,14 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW return super.createQuietModeManager(); } - // TODO: Remove this and override safelyStartActivityInternal() instead. @Override - public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user, + public void safelyStartActivityInternal(TargetInfo cti, UserHandle user, @Nullable Bundle options) { - if (sOverrides.onSafelyStartCallback != null && - sOverrides.onSafelyStartCallback.apply(cti)) { + if (sOverrides.onSafelyStartInternalCallback != null + && sOverrides.onSafelyStartInternalCallback.apply(cti)) { return; } - super.safelyStartActivityAsUser(cti, user, options); + super.safelyStartActivityInternal(cti, user, options); } @Override diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java index b82bc163bb40c..b6813ffba3120 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java @@ -64,6 +64,8 @@ import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGett import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter; import com.android.internal.widget.ResolverDrawerLayout; +import com.google.android.collect.Lists; + import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; @@ -110,8 +112,8 @@ public class ResolverActivityTest { assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -226,8 +228,8 @@ public class ResolverActivityTest { assertThat(activity.getAdapter().getPlaceholderCount(), is(1)); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -258,8 +260,8 @@ public class ResolverActivityTest { assertThat(activity.getAdapter().getCount(), is(1)); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; // Make a stable copy of the components as the original list may be modified @@ -298,8 +300,8 @@ public class ResolverActivityTest { assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -345,8 +347,8 @@ public class ResolverActivityTest { assertThat(activity.getAdapter().getCount(), is(2)); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -531,8 +533,8 @@ public class ResolverActivityTest { setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendImageIntent(); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -634,8 +636,8 @@ public class ResolverActivityTest { setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos); Intent sendIntent = createSendImageIntent(); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -848,8 +850,8 @@ public class ResolverActivityTest { Intent sendIntent = createSendImageIntent(); sendIntent.setType("TestType"); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; waitForIdle(); @@ -873,8 +875,8 @@ public class ResolverActivityTest { Intent sendIntent = createSendImageIntent(); sendIntent.setType("TestType"); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; waitForIdle(); @@ -902,8 +904,8 @@ public class ResolverActivityTest { Intent sendIntent = createSendImageIntent(); sendIntent.setType("TestType"); ResolveInfo[] chosen = new ResolveInfo[1]; - sOverrides.onSafelyStartCallback = targetInfo -> { - chosen[0] = targetInfo.getResolveInfo(); + sOverrides.onSafelyStartInternalCallback = result -> { + chosen[0] = result.first.getResolveInfo(); return true; }; @@ -1072,8 +1074,8 @@ public class ResolverActivityTest { Intent sendIntent = createSendImageIntent(); sendIntent.setType("TestType"); final UserHandle[] selectedActivityUserHandle = new UserHandle[1]; - sOverrides.onSafelyStartInternalCallback = userHandle -> { - selectedActivityUserHandle[0] = userHandle; + sOverrides.onSafelyStartInternalCallback = result -> { + selectedActivityUserHandle[0] = result.second; return true; }; @@ -1109,8 +1111,8 @@ public class ResolverActivityTest { Intent sendIntent = createSendImageIntent(); sendIntent.setType("TestType"); final UserHandle[] selectedActivityUserHandle = new UserHandle[1]; - sOverrides.onSafelyStartInternalCallback = userHandle -> { - selectedActivityUserHandle[0] = userHandle; + sOverrides.onSafelyStartInternalCallback = result -> { + selectedActivityUserHandle[0] = result.second; return true; }; @@ -1129,6 +1131,31 @@ public class ResolverActivityTest { assertThat(selectedActivityUserHandle[0], is(activity.getAdapter().getUserHandle())); } + @Test + public void testClonedProfilePresent_personalProfileResolverComparatorHasCorrectUsers() + throws Exception { + // enable cloneProfile + markCloneProfileUserAvailable(); + List 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(); + List result = activity + .getResolverRankerServiceUserHandleList(PERSONAL_USER_HANDLE); + + assertTrue(result.containsAll(Lists.newArrayList(PERSONAL_USER_HANDLE, + sOverrides.cloneProfileUserHandle))); + } + private Intent createSendImageIntent() { Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java index 8f6f29d24ab94..e193de0a3b20e 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperActivity.java @@ -29,6 +29,7 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; import android.os.UserHandle; +import android.util.Pair; import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker; import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager; @@ -53,7 +54,7 @@ public class ResolverWrapperActivity extends ResolverActivity { List payloadIntents, Intent[] initialIntents, List rList, boolean filterLastUsed, UserHandle userHandle) { return new ResolverWrapperAdapter(context, payloadIntents, initialIntents, rList, - filterLastUsed, createListController(userHandle), this); + filterLastUsed, createListController(userHandle), this, userHandle); } @Override @@ -95,22 +96,11 @@ public class ResolverWrapperActivity extends ResolverActivity { return super.isVoiceInteraction(); } - // TODO: Remove this and override safelyStartActivityInternal() instead. - @Override - public void safelyStartActivityAsUser(TargetInfo cti, UserHandle user, - @Nullable Bundle options) { - if (sOverrides.onSafelyStartCallback != null && - sOverrides.onSafelyStartCallback.apply(cti)) { - return; - } - super.safelyStartActivityAsUser(cti, user, options); - } - @Override public void safelyStartActivityInternal(TargetInfo cti, UserHandle user, @Nullable Bundle options) { if (sOverrides.onSafelyStartInternalCallback != null - && sOverrides.onSafelyStartInternalCallback.apply(user)) { + && sOverrides.onSafelyStartInternalCallback.apply(new Pair<>(cti, user))) { return; } super.safelyStartActivityInternal(cti, user, options); @@ -166,6 +156,12 @@ public class ResolverWrapperActivity extends ResolverActivity { super.startActivityAsUser(intent, options, user); } + @Override + protected List getResolverRankerServiceUserHandleListInternal(UserHandle + userHandle) { + return super.getResolverRankerServiceUserHandleListInternal(userHandle); + } + /** * We cannot directly mock the activity created since instrumentation creates it. *

@@ -174,8 +170,7 @@ public class ResolverWrapperActivity extends ResolverActivity { static class OverrideData { @SuppressWarnings("Since15") public Function createPackageManager; - public Function onSafelyStartCallback; - public Function onSafelyStartInternalCallback; + public Function, Boolean> onSafelyStartInternalCallback; public ResolverListController resolverListController; public ResolverListController workResolverListController; public Boolean isVoiceInteraction; @@ -189,7 +184,6 @@ public class ResolverWrapperActivity extends ResolverActivity { public CrossProfileIntentsChecker mCrossProfileIntentsChecker; public void reset() { - onSafelyStartCallback = null; onSafelyStartInternalCallback = null; isVoiceInteraction = null; createPackageManager = null; diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java index 2861428ece4dd..32bef7560a81e 100644 --- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java +++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java @@ -19,6 +19,7 @@ package com.android.internal.app; import android.content.Context; import android.content.Intent; import android.content.pm.ResolveInfo; +import android.os.UserHandle; import androidx.test.espresso.idling.CountingIdlingResource; @@ -36,9 +37,10 @@ public class ResolverWrapperAdapter extends ResolverListAdapter { Intent[] initialIntents, List rList, boolean filterLastUsed, ResolverListController resolverListController, - ResolverListCommunicator resolverListCommunicator) { + ResolverListCommunicator resolverListCommunicator, + UserHandle initialIntentsUserHandle) { super(context, payloadIntents, initialIntents, rList, filterLastUsed, - resolverListController, resolverListCommunicator, false); + resolverListController, resolverListCommunicator, false, initialIntentsUserHandle); } public CountingIdlingResource getLabelIdlingResource() {