private static final boolean DEBUG = false;
private static final String TAG = "AbstractResolverComp";
- private AfterCompute mAfterCompute;
+ protected AfterCompute mAfterCompute;
protected final PackageManager mPm;
protected final UsageStatsManager mUsm;
protected String[] mAnnotations;
Log.d(TAG, "RANKER_SERVICE_RESULT");
}
if (mHandler.hasMessages(RANKER_RESULT_TIMEOUT)) {
- if (msg.obj != null) {
- handleResultMessage(msg);
- } else {
- Log.e(TAG, "Receiving null prediction results.");
- }
+ handleResultMessage(msg);
mHandler.removeMessages(RANKER_RESULT_TIMEOUT);
afterCompute();
}
mHttp = "http".equals(scheme) || "https".equals(scheme);
mContentType = intent.getType();
getContentAnnotations(intent);
-
mPm = context.getPackageManager();
mUsm = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
mDefaultBrowserPackageName = mHttp
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
+import android.os.Handler;
import android.os.Message;
import android.os.UserHandle;
-import android.view.textclassifier.Log;
+import android.util.Log;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import java.util.Map;
/**
- * Uses an {@link AppPredictor} to sort Resolver targets.
+ * Uses an {@link AppPredictor} to sort Resolver targets. If the AppPredictionService appears to be
+ * disabled by returning an empty sorted target list, {@link AppPredictionServiceResolverComparator}
+ * will fallback to using a {@link ResolverRankerServiceResolverComparator}.
*/
class AppPredictionServiceResolverComparator extends AbstractResolverComparator {
private static final String TAG = "APSResolverComparator";
+ private static final long DELAY_COMPUTE_WHEN_DEFAULTING_TO_RESOLVER_MILLIS = 200;
private final AppPredictor mAppPredictor;
private final Context mContext;
private final Map<ComponentName, Integer> mTargetRanks = new HashMap<>();
private final UserHandle mUser;
+ private final Intent mIntent;
+ private final String mReferrerPackage;
+ // If this is non-null (and this is not destroyed), it means APS is disabled and we should fall
+ // back to using the ResolverRankerService.
+ private ResolverRankerServiceResolverComparator mResolverRankerService;
AppPredictionServiceResolverComparator(
- Context context, Intent intent, AppPredictor appPredictor, UserHandle user) {
+ Context context,
+ Intent intent,
+ String referrerPackage,
+ AppPredictor appPredictor,
+ UserHandle user) {
super(context, intent);
mContext = context;
+ mIntent = intent;
mAppPredictor = appPredictor;
mUser = user;
+ mReferrerPackage = referrerPackage;
}
@Override
int compare(ResolveInfo lhs, ResolveInfo rhs) {
+ if (mResolverRankerService != null) {
+ return mResolverRankerService.compare(lhs, rhs);
+ }
Integer lhsRank = mTargetRanks.get(new ComponentName(lhs.activityInfo.packageName,
lhs.activityInfo.name));
Integer rhsRank = mTargetRanks.get(new ComponentName(rhs.activityInfo.packageName,
@Override
void doCompute(List<ResolvedComponentInfo> targets) {
+ if (targets.isEmpty()) {
+ mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT);
+ return;
+ }
List<AppTarget> appTargets = new ArrayList<>();
for (ResolvedComponentInfo target : targets) {
appTargets.add(new AppTarget.Builder(new AppTargetId(target.name.flattenToString()))
}
mAppPredictor.sortTargets(appTargets, mContext.getMainExecutor(),
sortedAppTargets -> {
- Message msg =
+ if (sortedAppTargets.isEmpty()) {
+ // APS for chooser is disabled. Fallback to resolver.
+ mResolverRankerService =
+ new ResolverRankerServiceResolverComparator(
+ mContext, mIntent, mReferrerPackage,
+ () -> mHandler.sendEmptyMessage(RANKER_SERVICE_RESULT));
+ mResolverRankerService.initRanker(mContext);
+ Handler computeHandler =
+ new Handler(msg -> {
+ mResolverRankerService.compute(targets);
+ return true;
+ });
+ computeHandler.sendEmptyMessageDelayed(
+ 0, DELAY_COMPUTE_WHEN_DEFAULTING_TO_RESOLVER_MILLIS);
+ } else {
+ Message msg =
Message.obtain(mHandler, RANKER_SERVICE_RESULT, sortedAppTargets);
- msg.sendToTarget();
- });
+ msg.sendToTarget();
+ }
+ }
+ );
}
@Override
void handleResultMessage(Message msg) {
- if (msg.what == RANKER_SERVICE_RESULT) {
+ // Null value is okay if we have defaulted to the ResolverRankerService.
+ if (msg.what == RANKER_SERVICE_RESULT && msg.obj != null) {
final List<AppTarget> sortedAppTargets = (List<AppTarget>) msg.obj;
for (int i = 0; i < sortedAppTargets.size(); i++) {
mTargetRanks.put(new ComponentName(sortedAppTargets.get(i).getPackageName(),
sortedAppTargets.get(i).getClassName()), i);
}
+ } else if (msg.obj == null && mResolverRankerService == null) {
+ Log.e(TAG, "Unexpected null result");
}
}
@Override
float getScore(ComponentName name) {
+ if (mResolverRankerService != null) {
+ return mResolverRankerService.getScore(name);
+ }
Integer rank = mTargetRanks.get(name);
if (rank == null) {
Log.w(TAG, "Score requested for unknown component.");
@Override
void updateModel(ComponentName componentName) {
+ if (mResolverRankerService != null) {
+ mResolverRankerService.updateModel(componentName);
+ return;
+ }
mAppPredictor.notifyAppTargetEvent(
new AppTargetEvent.Builder(
new AppTarget.Builder(
.setClassName(componentName.getClassName()).build(),
ACTION_LAUNCH).build());
}
+
+ @Override
+ void destroy() {
+ if (mResolverRankerService != null) {
+ mResolverRankerService.destroy();
+ mResolverRankerService = null;
+ }
+ }
}
if (mChooserListAdapter == null) {
return;
}
+ if (resultList.isEmpty()) {
+ // APS may be disabled, so try querying targets ourselves.
+ queryDirectShareTargets(mChooserListAdapter, true);
+ return;
+ }
final List<DisplayResolveInfo> driList =
getDisplayResolveInfos(mChooserListAdapter);
final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
return driList;
}
- private void queryDirectShareTargets(ChooserListAdapter adapter) {
- AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
- if (appPredictor != null) {
- appPredictor.requestPredictionUpdate();
- return;
+ private void queryDirectShareTargets(
+ ChooserListAdapter adapter, boolean skipAppPredictionService) {
+ if (!skipAppPredictionService) {
+ AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
+ if (appPredictor != null) {
+ appPredictor.requestPredictionUpdate();
+ return;
+ }
}
// Default to just querying ShortcutManager if AppPredictor not present.
final IntentFilter filter = getTargetIntentFilter();
AbstractResolverComparator resolverComparator;
if (appPredictor != null) {
resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
- appPredictor, getUser());
+ getReferrerPackageName(), appPredictor, getUser());
} else {
resolverComparator =
new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
Log.d(TAG, "querying direct share targets from ShortcutManager");
}
- queryDirectShareTargets(this);
+ queryDirectShareTargets(this, false);
}
if (USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS) {
if (DEBUG) {