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
This commit is contained in:
@@ -2525,8 +2525,7 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> 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<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
|
||||
boolean filterLastUsed, ResolverListController resolverListController) {
|
||||
List<Intent> payloadIntents,
|
||||
Intent[] initialIntents,
|
||||
List<ResolveInfo> 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
|
||||
|
||||
@@ -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<String, DisplayResolveInfo> 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(
|
||||
|
||||
@@ -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<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
|
||||
@VisibleForTesting(visibility = PROTECTED)
|
||||
public final List<UserHandle> getResolverRankerServiceUserHandleList(UserHandle userHandle) {
|
||||
return getResolverRankerServiceUserHandleListInternal(userHandle);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected List<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
|
||||
userHandle) {
|
||||
List<UserHandle> userList = new ArrayList<>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,13 +91,16 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
private boolean mIsTabLoaded;
|
||||
private final Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>();
|
||||
private final Map<DisplayResolveInfo, LoadLabelTask> mLabelLoaders = new HashMap<>();
|
||||
// Represents the UserSpace in which the Initial Intents should be resolved.
|
||||
private final UserHandle mInitialIntentsUserSpace;
|
||||
|
||||
public ResolverListAdapter(Context context, List<Intent> payloadIntents,
|
||||
Intent[] initialIntents, List<ResolveInfo> 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;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ChooserActivityOverrideData {
|
||||
|
||||
@SuppressWarnings("Since15")
|
||||
public Function<PackageManager, PackageManager> createPackageManager;
|
||||
public Function<TargetInfo, Boolean> onSafelyStartCallback;
|
||||
public Function<TargetInfo, Boolean> onSafelyStartInternalCallback;
|
||||
public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
|
||||
public BiFunction<
|
||||
IChooserWrapper, ChooserListAdapter, Pair<Integer, ChooserActivity.ServiceResultInfo[]>>
|
||||
@@ -82,7 +82,7 @@ public class ChooserActivityOverrideData {
|
||||
public PackageManager packageManager;
|
||||
|
||||
public void reset() {
|
||||
onSafelyStartCallback = null;
|
||||
onSafelyStartInternalCallback = null;
|
||||
onQueryDirectShareTargets = null;
|
||||
directShareTargets = null;
|
||||
isVoiceInteraction = null;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -64,14 +64,14 @@ public class ChooserWrapperActivity extends ChooserActivity implements IChooserW
|
||||
@Override
|
||||
public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents,
|
||||
Intent[] initialIntents, List<ResolveInfo> 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
|
||||
|
||||
@@ -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<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();
|
||||
List<UserHandle> 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);
|
||||
|
||||
@@ -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<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> 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<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
|
||||
userHandle) {
|
||||
return super.getResolverRankerServiceUserHandleListInternal(userHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* We cannot directly mock the activity created since instrumentation creates it.
|
||||
* <p>
|
||||
@@ -174,8 +170,7 @@ public class ResolverWrapperActivity extends ResolverActivity {
|
||||
static class OverrideData {
|
||||
@SuppressWarnings("Since15")
|
||||
public Function<PackageManager, PackageManager> createPackageManager;
|
||||
public Function<TargetInfo, Boolean> onSafelyStartCallback;
|
||||
public Function<UserHandle, Boolean> onSafelyStartInternalCallback;
|
||||
public Function<Pair<TargetInfo, UserHandle>, 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;
|
||||
|
||||
@@ -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<ResolveInfo> 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() {
|
||||
|
||||
Reference in New Issue
Block a user