OSDN Git Service

Default to RankerResolver if AppPredictor is disabled
authorGeorge Hodulik <georgehodulik@google.com>
Fri, 26 Apr 2019 23:17:54 +0000 (16:17 -0700)
committerGeorge Hodulik <georgehodulik@google.com>
Wed, 1 May 2019 22:01:16 +0000 (22:01 +0000)
The AppPredictionServiceResolverComparator will use the ResolverRankerService
if APS appears to be disabled for share activities (returning empty despite
being given a non-empty target list).

For Direct share targets, if the share target list returned is empty, we fall
back on calling the ShortcutManager directly and relying on ChooserTargetService
to rank.

Bug:129014961
Test:Manually tested.
Test: atest frameworks/base/core/tests/coretests/src/com/android/internal/app
Change-Id: I9891a3a4d879e247b84a651408058153ea57c766

core/java/com/android/internal/app/AbstractResolverComparator.java
core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
core/java/com/android/internal/app/ChooserActivity.java
core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java

index 87d80d4..9ac979b 100644 (file)
@@ -43,7 +43,7 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
     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;
@@ -70,11 +70,7 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
                         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();
                     }
@@ -99,7 +95,6 @@ abstract class AbstractResolverComparator implements Comparator<ResolvedComponen
         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
index 3b4e1a0..fb27a2f 100644 (file)
@@ -26,9 +26,10 @@ import android.content.ComponentName;
 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;
 
@@ -38,27 +39,44 @@ import java.util.List;
 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,
@@ -75,6 +93,10 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
 
     @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()))
@@ -83,25 +105,48 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
         }
         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.");
@@ -113,6 +158,10 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
 
     @Override
     void updateModel(ComponentName componentName) {
+        if (mResolverRankerService != null) {
+            mResolverRankerService.updateModel(componentName);
+            return;
+        }
         mAppPredictor.notifyAppTargetEvent(
                 new AppTargetEvent.Builder(
                     new AppTarget.Builder(
@@ -121,4 +170,12 @@ class AppPredictionServiceResolverComparator extends AbstractResolverComparator
                         .setClassName(componentName.getClassName()).build(),
                     ACTION_LAUNCH).build());
     }
+
+    @Override
+    void destroy() {
+        if (mResolverRankerService != null) {
+            mResolverRankerService.destroy();
+            mResolverRankerService = null;
+        }
+    }
 }
index 1eabbd8..0167030 100644 (file)
@@ -453,6 +453,11 @@ public class ChooserActivity extends ResolverActivity {
                 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 =
@@ -1272,11 +1277,14 @@ public class ChooserActivity extends ResolverActivity {
         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();
@@ -1609,7 +1617,7 @@ public class ChooserActivity extends ResolverActivity {
         AbstractResolverComparator resolverComparator;
         if (appPredictor != null) {
             resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
-                    appPredictor, getUser());
+                    getReferrerPackageName(), appPredictor, getUser());
         } else {
             resolverComparator =
                     new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
@@ -2205,7 +2213,7 @@ public class ChooserActivity extends ResolverActivity {
                     Log.d(TAG, "querying direct share targets from ShortcutManager");
                 }
 
-                queryDirectShareTargets(this);
+                queryDirectShareTargets(this, false);
             }
             if (USE_CHOOSER_TARGET_SERVICE_FOR_DIRECT_TARGETS) {
                 if (DEBUG) {
index a781907..d633467 100644 (file)
@@ -66,9 +66,6 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
 
     // timeout for establishing connections with a ResolverRankerService.
     private static final int CONNECTION_COST_TIMEOUT_MILLIS = 200;
-    // timeout for establishing connections with a ResolverRankerService, collecting features and
-    // predicting ranking scores.
-    private static final int WATCHDOG_TIMEOUT_MILLIS = 500;
 
     private final Collator mCollator;
     private final Map<String, UsageStats> mStats;
@@ -106,6 +103,10 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
         if (msg.what != RANKER_SERVICE_RESULT) {
             return;
         }
+        if (msg.obj == null) {
+            Log.e(TAG, "Receiving null prediction results.");
+            return;
+        }
         final List<ResolverTarget> receivedTargets = (List<ResolverTarget>) msg.obj;
         if (receivedTargets != null && mTargets != null
                     && receivedTargets.size() == mTargets.size()) {
@@ -314,7 +315,7 @@ class ResolverRankerServiceResolverComparator extends AbstractResolverComparator
     }
 
     // connect to a ranking service.
-    private void initRanker(Context context) {
+    void initRanker(Context context) {
         synchronized (mLock) {
             if (mConnection != null && mRanker != null) {
                 if (DEBUG) {