Merge "Only perform autolaunch if list has completely rebuilt" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8862ee3891
@@ -301,7 +301,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
|
||||
private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) {
|
||||
if (shouldShowNoCrossProfileIntentsEmptyState(activeListAdapter)) {
|
||||
activeListAdapter.postListReadyRunnable(doPostProcessing);
|
||||
activeListAdapter.postListReadyRunnable(doPostProcessing, /* rebuildCompleted */ true);
|
||||
return false;
|
||||
}
|
||||
return activeListAdapter.rebuildList(doPostProcessing);
|
||||
|
||||
@@ -2404,10 +2404,9 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
public ChooserGridAdapter createChooserGridAdapter(Context context,
|
||||
List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
|
||||
boolean filterLastUsed, boolean useLayoutForBrowsables, UserHandle userHandle) {
|
||||
ChooserListAdapter chooserListAdapter = new ChooserListAdapter(context, payloadIntents,
|
||||
initialIntents, rList,
|
||||
filterLastUsed, createListController(userHandle), useLayoutForBrowsables,
|
||||
this, this);
|
||||
ChooserListAdapter chooserListAdapter = createChooserListAdapter(context, payloadIntents,
|
||||
initialIntents, rList, filterLastUsed,
|
||||
useLayoutForBrowsables, createListController(userHandle));
|
||||
AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
|
||||
AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
|
||||
chooserListAdapter.setAppPredictor(appPredictor);
|
||||
@@ -2415,6 +2414,16 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
return new ChooserGridAdapter(chooserListAdapter);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public ChooserListAdapter createChooserListAdapter(Context context,
|
||||
List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
|
||||
boolean filterLastUsed, boolean useLayoutForBrowsables,
|
||||
ResolverListController resolverListController) {
|
||||
return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
|
||||
filterLastUsed, resolverListController, useLayoutForBrowsables,
|
||||
this, this, context.getPackageManager());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected ResolverListController createListController(UserHandle userHandle) {
|
||||
AppPredictor appPredictor = getAppPredictorForShareActivitiesIfEnabled(userHandle);
|
||||
|
||||
@@ -88,7 +88,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
private final int mMaxShortcutTargetsPerApp;
|
||||
private final ChooserListCommunicator mChooserListCommunicator;
|
||||
private final SelectableTargetInfo.SelectableTargetInfoCommunicator
|
||||
mSelectableTargetInfoComunicator;
|
||||
mSelectableTargetInfoCommunicator;
|
||||
|
||||
private int mNumShortcutResults = 0;
|
||||
|
||||
@@ -117,7 +117,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
boolean filterLastUsed, ResolverListController resolverListController,
|
||||
boolean useLayoutForBrowsables,
|
||||
ChooserListCommunicator chooserListCommunicator,
|
||||
SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoComunicator) {
|
||||
SelectableTargetInfo.SelectableTargetInfoCommunicator selectableTargetInfoCommunicator,
|
||||
PackageManager packageManager) {
|
||||
// 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,
|
||||
@@ -128,10 +129,9 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
mMaxShortcutTargetsPerApp =
|
||||
context.getResources().getInteger(R.integer.config_maxShortcutTargetsPerApp);
|
||||
mChooserListCommunicator = chooserListCommunicator;
|
||||
mSelectableTargetInfoComunicator = selectableTargetInfoComunicator;
|
||||
mSelectableTargetInfoCommunicator = selectableTargetInfoCommunicator;
|
||||
|
||||
if (initialIntents != null) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
for (int i = 0; i < initialIntents.length; i++) {
|
||||
final Intent ii = initialIntents[i];
|
||||
if (ii == null) {
|
||||
@@ -147,7 +147,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
final ComponentName cn = ii.getComponent();
|
||||
if (cn != null) {
|
||||
try {
|
||||
ai = pm.getActivityInfo(ii.getComponent(), 0);
|
||||
ai = packageManager.getActivityInfo(ii.getComponent(), 0);
|
||||
ri = new ResolveInfo();
|
||||
ri.activityInfo = ai;
|
||||
} catch (PackageManager.NameNotFoundException ignored) {
|
||||
@@ -155,7 +155,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
}
|
||||
}
|
||||
if (ai == null) {
|
||||
ri = pm.resolveActivity(ii, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
ri = packageManager.resolveActivity(ii, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
ai = ri != null ? ri.activityInfo : null;
|
||||
}
|
||||
if (ai == null) {
|
||||
@@ -455,7 +455,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
UserHandle userHandle = getUserHandle();
|
||||
Context contextAsUser = mContext.createContextAsUser(userHandle, 0 /* flags */);
|
||||
boolean isInserted = insertServiceTarget(new SelectableTargetInfo(contextAsUser,
|
||||
origTarget, target, targetScore, mSelectableTargetInfoComunicator,
|
||||
origTarget, target, targetScore, mSelectableTargetInfoCommunicator,
|
||||
(isShortcutResult ? directShareToShortcutInfos.get(target) : null)));
|
||||
|
||||
if (isInserted && isShortcutResult) {
|
||||
@@ -507,7 +507,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
.map(target ->
|
||||
new SelectableTargetInfo(
|
||||
contextAsUser, origTarget, target, target.getScore(),
|
||||
mSelectableTargetInfoComunicator,
|
||||
mSelectableTargetInfoCommunicator,
|
||||
(isShortcutResult ? directShareToShortcutInfos.get(target)
|
||||
: null))
|
||||
)
|
||||
|
||||
@@ -1026,7 +1026,8 @@ public class ResolverActivity extends Activity implements
|
||||
}
|
||||
|
||||
@Override // ResolverListCommunicator
|
||||
public final void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing) {
|
||||
public final void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing,
|
||||
boolean rebuildCompleted) {
|
||||
if (isAutolaunching()) {
|
||||
return;
|
||||
}
|
||||
@@ -1041,7 +1042,7 @@ public class ResolverActivity extends Activity implements
|
||||
}
|
||||
// showEmptyResolverListEmptyState can mark the tab as loaded,
|
||||
// which is a precondition for auto launching
|
||||
if (maybeAutolaunchActivity()) {
|
||||
if (rebuildCompleted && maybeAutolaunchActivity()) {
|
||||
return;
|
||||
}
|
||||
if (doPostProcessing) {
|
||||
|
||||
@@ -282,7 +282,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
}
|
||||
setPlaceholderCount(placeholderCount);
|
||||
createSortingTask(doPostProcessing).execute(currentResolveList);
|
||||
postListReadyRunnable(doPostProcessing);
|
||||
postListReadyRunnable(doPostProcessing, /* rebuildCompleted */ false);
|
||||
return false;
|
||||
} else {
|
||||
processSortedList(currentResolveList, doPostProcessing);
|
||||
@@ -370,7 +370,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
mResolverListCommunicator.sendVoiceChoicesIfNeeded();
|
||||
postListReadyRunnable(doPostProcessing);
|
||||
postListReadyRunnable(doPostProcessing, /* rebuildCompleted */ true);
|
||||
mIsTabLoaded = true;
|
||||
}
|
||||
|
||||
@@ -380,14 +380,15 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
* handler thread to update after the current task is finished.
|
||||
* @param doPostProcessing Whether to update the UI and load additional direct share targets
|
||||
* after the list has been rebuilt
|
||||
* @param rebuildCompleted Whether the list has been completely rebuilt
|
||||
*/
|
||||
void postListReadyRunnable(boolean doPostProcessing) {
|
||||
void postListReadyRunnable(boolean doPostProcessing, boolean rebuildCompleted) {
|
||||
if (mPostListReadyRunnable == null) {
|
||||
mPostListReadyRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mResolverListCommunicator.onPostListReady(ResolverListAdapter.this,
|
||||
doPostProcessing);
|
||||
doPostProcessing, rebuildCompleted);
|
||||
mPostListReadyRunnable = null;
|
||||
}
|
||||
};
|
||||
@@ -649,7 +650,8 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
|
||||
Intent getReplacementIntent(ActivityInfo activityInfo, Intent defIntent);
|
||||
|
||||
void onPostListReady(ResolverListAdapter listAdapter, boolean updateUi);
|
||||
void onPostListReady(ResolverListAdapter listAdapter, boolean updateUi,
|
||||
boolean rebuildCompleted);
|
||||
|
||||
void sendVoiceChoicesIfNeeded();
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import static com.android.internal.app.ChooserListAdapter.SHORTCUT_TARGET_SCORE_
|
||||
import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
|
||||
import static com.android.internal.app.MatcherUtils.first;
|
||||
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
@@ -41,6 +42,8 @@ import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.atLeastOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
@@ -55,6 +58,8 @@ import android.content.ClipboardManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
@@ -302,7 +307,7 @@ public class ChooserActivityTest {
|
||||
waitForIdle();
|
||||
UsageStatsManager usm = activity.getUsageStatsManager();
|
||||
verify(sOverrides.resolverListController, times(1))
|
||||
.topK(Mockito.any(List.class), Mockito.anyInt());
|
||||
.topK(any(List.class), anyInt());
|
||||
assertThat(activity.getIsSelected(), is(false));
|
||||
sOverrides.onSafelyStartCallback = targetInfo -> {
|
||||
return true;
|
||||
@@ -312,7 +317,7 @@ public class ChooserActivityTest {
|
||||
.perform(click());
|
||||
waitForIdle();
|
||||
verify(sOverrides.resolverListController, times(1))
|
||||
.updateChooserCounts(Mockito.anyString(), Mockito.anyInt(), Mockito.anyString());
|
||||
.updateChooserCounts(Mockito.anyString(), anyInt(), Mockito.anyString());
|
||||
verify(sOverrides.resolverListController, times(1))
|
||||
.updateModel(toChoose.activityInfo.getComponentName());
|
||||
assertThat(activity.getIsSelected(), is(true));
|
||||
@@ -1750,6 +1755,54 @@ public class ChooserActivityTest {
|
||||
assertThat(chosen[0], is(personalResolvedComponentInfos.get(1).getResolveInfoAt(0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneInitialIntent_noAutolaunch() {
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(1);
|
||||
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class)))
|
||||
.thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
Intent chooserIntent = createChooserIntent(new Intent[] {new Intent("action.fake")});
|
||||
ResolveInfo[] chosen = new ResolveInfo[1];
|
||||
sOverrides.onSafelyStartCallback = targetInfo -> {
|
||||
chosen[0] = targetInfo.getResolveInfo();
|
||||
return true;
|
||||
};
|
||||
sOverrides.packageManager = mock(PackageManager.class);
|
||||
ResolveInfo ri = createFakeResolveInfo();
|
||||
when(sOverrides.packageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(ri);
|
||||
waitForIdle();
|
||||
|
||||
mActivityRule.launchActivity(chooserIntent);
|
||||
waitForIdle();
|
||||
|
||||
assertNull(chosen[0]);
|
||||
}
|
||||
|
||||
private Intent createChooserIntent(Intent[] initialIntents) {
|
||||
Intent chooserIntent = new Intent();
|
||||
chooserIntent.setAction(Intent.ACTION_CHOOSER);
|
||||
chooserIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
|
||||
chooserIntent.putExtra(Intent.EXTRA_TITLE, "some title");
|
||||
chooserIntent.putExtra(Intent.EXTRA_INTENT, createSendTextIntent());
|
||||
chooserIntent.setType("text/plain");
|
||||
if (initialIntents != null) {
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, initialIntents);
|
||||
}
|
||||
return chooserIntent;
|
||||
}
|
||||
|
||||
private ResolveInfo createFakeResolveInfo() {
|
||||
ResolveInfo ri = new ResolveInfo();
|
||||
ri.activityInfo = new ActivityInfo();
|
||||
ri.activityInfo.name = "FakeActivityName";
|
||||
ri.activityInfo.packageName = "fake.package.name";
|
||||
ri.activityInfo.applicationInfo = new ApplicationInfo();
|
||||
ri.activityInfo.applicationInfo.packageName = "fake.package.name";
|
||||
return ri;
|
||||
}
|
||||
|
||||
private Intent createSendTextIntent() {
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
|
||||
@@ -58,6 +58,18 @@ public class ChooserWrapperActivity extends ChooserActivity {
|
||||
return multiProfilePagerAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents,
|
||||
Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed,
|
||||
boolean useLayoutForBrowsables, ResolverListController resolverListController) {
|
||||
PackageManager packageManager =
|
||||
sOverrides.packageManager == null ? context.getPackageManager()
|
||||
: sOverrides.packageManager;
|
||||
return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
|
||||
filterLastUsed, resolverListController, useLayoutForBrowsables,
|
||||
this, this, packageManager);
|
||||
}
|
||||
|
||||
ChooserListAdapter getAdapter() {
|
||||
return mChooserMultiProfilePagerAdapter.getActiveListAdapter();
|
||||
}
|
||||
@@ -217,6 +229,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
|
||||
public boolean hasCrossProfileIntents;
|
||||
public boolean isQuietModeEnabled;
|
||||
public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector;
|
||||
public PackageManager packageManager;
|
||||
|
||||
public void reset() {
|
||||
onSafelyStartCallback = null;
|
||||
@@ -235,6 +248,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
|
||||
workProfileUserHandle = null;
|
||||
hasCrossProfileIntents = true;
|
||||
isQuietModeEnabled = false;
|
||||
packageManager = null;
|
||||
multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() {
|
||||
@Override
|
||||
public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
|
||||
|
||||
Reference in New Issue
Block a user