Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 62aad00c authored by Dan Sandler's avatar Dan Sandler Committed by Daniel Sandler
Browse files

Remove direct-share target row animations and limit to one row.

The animation---which was responsible for causing relayouts
that would in turn bind views, which involved package
manager roundtrips---would lock out interaction with the rest of
the share sheet for at least 400ms while the animation ran
(often much longer if services were slow to start or respond).

Now the main UI is never blocked, and direct share targets
can take as long as they like (up to 2sec) before appearing.

It's really fast now, basically.

Bug: 67622422
Bug: 63521992
Test: atest com.android.internal.app.ChooserActivityTest
Change-Id: I21826e282226f2b2ce6d3d1b5862dbfc449f5918
parent 8997b7e4
Loading
Loading
Loading
Loading
+6 −138
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ import android.widget.Space;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.app.ResolverActivity.TargetInfo;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -932,7 +933,7 @@ public class ChooserActivity extends ResolverActivity {
        public static final int TARGET_SERVICE = 1;
        public static final int TARGET_STANDARD = 2;

        private static final int MAX_SERVICE_TARGETS = 8;
        private static final int MAX_SERVICE_TARGETS = 4;
        private static final int MAX_TARGETS_PER_SERVICE = 4;

        private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
@@ -1189,123 +1190,20 @@ public class ChooserActivity extends ResolverActivity {
        }
    }

    static class RowScale {
        private static final int DURATION = 400;

        float mScale;
        ChooserRowAdapter mAdapter;
        private final ObjectAnimator mAnimator;

        public static final FloatProperty<RowScale> PROPERTY =
                new FloatProperty<RowScale>("scale") {
            @Override
            public void setValue(RowScale object, float value) {
                object.mScale = value;
                object.mAdapter.notifyDataSetChanged();
            }

            @Override
            public Float get(RowScale object) {
                return object.mScale;
            }
        };

        public RowScale(@NonNull ChooserRowAdapter adapter, float from, float to) {
            mAdapter = adapter;
            mScale = from;
            if (from == to) {
                mAnimator = null;
                return;
            }

            mAnimator = ObjectAnimator.ofFloat(this, PROPERTY, from, to)
                .setDuration(DURATION);
            mAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    mAdapter.onAnimationStart();
                }
                @Override
                public void onAnimationEnd(Animator animation) {
                    mAdapter.onAnimationEnd();
                }
            });
        }

        public RowScale setInterpolator(Interpolator interpolator) {
            if (mAnimator != null) {
                mAnimator.setInterpolator(interpolator);
            }
            return this;
        }

        public float get() {
            return mScale;
        }

        public void startAnimation() {
            if (mAnimator != null) {
                mAnimator.start();
            }
        }

        public void cancelAnimation() {
            if (mAnimator != null) {
                mAnimator.cancel();
            }
        }
    }

    class ChooserRowAdapter extends BaseAdapter {
        private ChooserListAdapter mChooserListAdapter;
        private final LayoutInflater mLayoutInflater;
        private final int mColumnCount = 4;
        private RowScale[] mServiceTargetScale;
        private final Interpolator mInterpolator;
        private int mAnimationCount = 0;

        public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
            mChooserListAdapter = wrappedAdapter;
            mLayoutInflater = LayoutInflater.from(ChooserActivity.this);

            mInterpolator = AnimationUtils.loadInterpolator(ChooserActivity.this,
                    android.R.interpolator.decelerate_quint);

            wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
                @Override
                public void onChanged() {
                    super.onChanged();
                    final int rcount = getServiceTargetRowCount();
                    if (mServiceTargetScale == null
                            || mServiceTargetScale.length != rcount) {
                        RowScale[] old = mServiceTargetScale;
                        int oldRCount = old != null ? old.length : 0;
                        mServiceTargetScale = new RowScale[rcount];
                        if (old != null && rcount > 0) {
                            System.arraycopy(old, 0, mServiceTargetScale, 0,
                                    Math.min(old.length, rcount));
                        }

                        for (int i = rcount; i < oldRCount; i++) {
                            old[i].cancelAnimation();
                        }

                        for (int i = oldRCount; i < rcount; i++) {
                            final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f)
                                    .setInterpolator(mInterpolator);
                            mServiceTargetScale[i] = rs;
                        }

                        // Start the animations in a separate loop.
                        // The process of starting animations will result in
                        // binding views to set up initial values, and we must
                        // have ALL of the new RowScale objects created above before
                        // we get started.
                        for (int i = oldRCount; i < rcount; i++) {
                            mServiceTargetScale[i].startAnimation();
                        }
                    }

                    notifyDataSetChanged();
                }

@@ -1313,39 +1211,10 @@ public class ChooserActivity extends ResolverActivity {
                public void onInvalidated() {
                    super.onInvalidated();
                    notifyDataSetInvalidated();
                    if (mServiceTargetScale != null) {
                        for (RowScale rs : mServiceTargetScale) {
                            rs.cancelAnimation();
                        }
                    }
                }
            });
        }

        private float getRowScale(int rowPosition) {
            final int start = getCallerTargetRowCount();
            final int end = start + getServiceTargetRowCount();
            if (rowPosition >= start && rowPosition < end) {
                return mServiceTargetScale[rowPosition - start].get();
            }
            return 1.f;
        }

        public void onAnimationStart() {
            final boolean lock = mAnimationCount == 0;
            mAnimationCount++;
            if (lock) {
                mResolverDrawerLayout.setDismissLocked(true);
            }
        }

        public void onAnimationEnd() {
            mAnimationCount--;
            if (mAnimationCount == 0) {
                mResolverDrawerLayout.setDismissLocked(false);
            }
        }

        @Override
        public int getCount() {
            return (int) (
@@ -1360,9 +1229,9 @@ public class ChooserActivity extends ResolverActivity {
                    (float) mChooserListAdapter.getCallerTargetCount() / mColumnCount);
        }

        // There can be at most one row of service targets.
        public int getServiceTargetRowCount() {
            return (int) Math.ceil(
                    (float) mChooserListAdapter.getServiceTargetCount() / mColumnCount);
            return (int) mChooserListAdapter.getServiceTargetCount() == 0 ? 0 : 1;
        }

        @Override
@@ -1485,8 +1354,7 @@ public class ChooserActivity extends ResolverActivity {
            }

            final int oldHeight = holder.row.getLayoutParams().height;
            holder.row.getLayoutParams().height = Math.max(1,
                    (int) (holder.measuredRowHeight * getRowScale(rowPosition)));
            holder.row.getLayoutParams().height = Math.max(1, holder.measuredRowHeight);
            if (holder.row.getLayoutParams().height != oldHeight) {
                holder.row.requestLayout();
            }
@@ -1728,7 +1596,7 @@ public class ChooserActivity extends ResolverActivity {
                final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView);
                int height = ((RowViewHolder) (v.getTag())).measuredRowHeight;

                offset += (int) (height * mChooserRowAdapter.getRowScale(pos));
                offset += (int) (height);

                if (vt >= 0) {
                    mCachedViewType = vt;