OSDN Git Service

Delay pruning direct share targets.
authorDan Sandler <dsandler@android.com>
Tue, 5 Jun 2018 02:13:40 +0000 (22:13 -0400)
committerDan Sandler <dsandler@android.com>
Tue, 5 Jun 2018 19:31:46 +0000 (15:31 -0400)
Pruning was intended to remove targets corresponding to
now-missing packages, but in practice causes the list to
briefly disappear any time packages change:

    PACKAGE_CHANGED ->
ResolverActivity.rebuildList() ->
    ChooserActivity.onListRebuilt() with an empty
    ResolverActivity.mDisplayList

In practice package changes happen all the time, so this
jank happens fairly often. (It contributed to b/67622422 as
well, since all this list rebuilding started animations that
locked out user input.)

This CL removes the old pruning process (comparing targets
against mDisplayList). Instead, we note that mDisplayList
got emptied, and lazily empty our own mServiceTargets once
we start getting responses back from all the services we
just re-queried.

The long-term fix here is to just rebuild all of this stuff.

Test: (1) share from Chrome
      (2) toggle the enable state of some random package
          to trigger PACKAGE_CHANGED, e.g.
          adb shell pm (enable|disable) com.android.egg
      (3) watch for jank
Bug: 109676071

Change-Id: Ie9d59b8f4b8cc8343beb40cbad6b8d52e5639082

core/java/com/android/internal/app/ChooserActivity.java

index 4f567d2..c31f17a 100644 (file)
@@ -934,7 +934,7 @@ public class ChooserActivity extends ResolverActivity {
         public static final int TARGET_STANDARD = 2;
 
         private static final int MAX_SERVICE_TARGETS = 4;
-        private static final int MAX_TARGETS_PER_SERVICE = 4;
+        private static final int MAX_TARGETS_PER_SERVICE = 2;
 
         private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
         private final List<TargetInfo> mCallerTargets = new ArrayList<>();
@@ -942,6 +942,8 @@ public class ChooserActivity extends ResolverActivity {
 
         private float mLateFee = 1.f;
 
+        private boolean mTargetsNeedPruning = false;
+
         private final BaseChooserTargetComparator mBaseTargetComparator
                 = new BaseChooserTargetComparator();
 
@@ -1030,7 +1032,13 @@ public class ChooserActivity extends ResolverActivity {
             }
 
             if (mServiceTargets != null) {
-                pruneServiceTargets();
+                if (getDisplayInfoCount() == 0) {
+                    // b/109676071: When packages change, onListRebuilt() is called before
+                    // ResolverActivity.mDisplayList is re-populated; pruning now would cause the
+                    // list to disappear briefly, so instead we detect this case (the
+                    // set of targets suddenly dropping to zero) and remember to prune later.
+                    mTargetsNeedPruning = true;
+                }
             }
             if (DEBUG) Log.d(TAG, "List built querying services");
             queryTargetServices(this);
@@ -1117,6 +1125,14 @@ public class ChooserActivity extends ResolverActivity {
         public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets) {
             if (DEBUG) Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size()
                     + " targets");
+
+            if (mTargetsNeedPruning && targets.size() > 0) {
+                // First proper update since we got an onListRebuilt() with (transient) 0 items.
+                // Clear out the target list and rebuild.
+                mServiceTargets.clear();
+                mTargetsNeedPruning = false;
+            }
+
             final float parentScore = getScore(origTarget);
             Collections.sort(targets, mBaseTargetComparator);
             float lastScore = 0;
@@ -1169,17 +1185,6 @@ public class ChooserActivity extends ResolverActivity {
             }
             mServiceTargets.add(chooserTargetInfo);
         }
-
-        private void pruneServiceTargets() {
-            if (DEBUG) Log.d(TAG, "pruneServiceTargets");
-            for (int i = mServiceTargets.size() - 1; i >= 0; i--) {
-                final ChooserTargetInfo cti = mServiceTargets.get(i);
-                if (!hasResolvedTarget(cti.getResolveInfo())) {
-                    if (DEBUG) Log.d(TAG, " => " + i + " " + cti);
-                    mServiceTargets.remove(i);
-                }
-            }
-        }
     }
 
     static class BaseChooserTargetComparator implements Comparator<ChooserTarget> {