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

Commit 918988c1 authored by John Reck's avatar John Reck
Browse files

Baby steps

 Run ViewPropertyAnimators with no listeners on the RenderThread

Change-Id: I7ff5300db96c7f4b59b09e3fff8a0df173f132dd
parent 3a9f0175
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ public final class RenderNodeAnimator extends Animator {
    public static final int Y = 9;
    public static final int Z = 10;
    public static final int ALPHA = 11;
    // The last value in the enum, used for array size initialization
    public static final int LAST_VALUE = ALPHA;

    // Keep in sync with enum PaintFields in Animator.h
    public static final int PAINT_STROKE_WIDTH = 0;
@@ -86,7 +88,7 @@ public final class RenderNodeAnimator extends Animator {
    private boolean mStarted = false;
    private boolean mFinished = false;

    public int mapViewPropertyToRenderProperty(int viewProperty) {
    public static int mapViewPropertyToRenderProperty(int viewProperty) {
        return sViewPropertyAnimatorMap.get(viewProperty);
    }

@@ -125,11 +127,15 @@ public final class RenderNodeAnimator extends Animator {
        }
    }

    static boolean isNativeInterpolator(TimeInterpolator interpolator) {
        return interpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class);
    }

    private void applyInterpolator() {
        if (mInterpolator == null) return;

        long ni;
        if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) {
        if (isNativeInterpolator(mInterpolator)) {
            ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
        } else {
            long duration = nGetDuration(mNativePtr.get());
+28 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.view;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.animation.TimeInterpolator;
import android.os.Build;

import java.util.ArrayList;
import java.util.HashMap;
@@ -108,6 +109,11 @@ public class ViewPropertyAnimator {
     */
    private ValueAnimator mTempValueAnimator;

    /**
     * A RenderThread-driven backend that may intercept startAnimation
     */
    private ViewPropertyAnimatorRT mRTBackend;

    /**
     * This listener is the mechanism by which the underlying Animator causes changes to the
     * properties currently being animated, as well as the cleanup after an animation is
@@ -227,7 +233,7 @@ public class ViewPropertyAnimator {
     * values are used to calculate the animated value for a given animation fraction
     * during the animation.
     */
    private static class NameValuesHolder {
    static class NameValuesHolder {
        int mNameConstant;
        float mFromValue;
        float mDeltaValue;
@@ -247,6 +253,9 @@ public class ViewPropertyAnimator {
    ViewPropertyAnimator(View view) {
        mView = view;
        view.ensureTransformationInfo();
        if (view.getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
            mRTBackend = new ViewPropertyAnimatorRT(view);
        }
    }

    /**
@@ -371,6 +380,10 @@ public class ViewPropertyAnimator {
        return this;
    }

    Animator.AnimatorListener getListener() {
        return mListener;
    }

    /**
     * Sets a listener for update events in the underlying ValueAnimator that runs
     * the property animations. Note that the underlying animator is animating between
@@ -390,6 +403,10 @@ public class ViewPropertyAnimator {
        return this;
    }

    ValueAnimator.AnimatorUpdateListener getUpdateListener() {
        return mUpdateListener;
    }

    /**
     * Starts the currently pending property animations immediately. Calling <code>start()</code>
     * is optional because all animations start automatically at the next opportunity. However,
@@ -825,12 +842,22 @@ public class ViewPropertyAnimator {
        return this;
    }

    boolean hasActions() {
        return mPendingSetupAction != null
                || mPendingCleanupAction != null
                || mPendingOnStartAction != null
                || mPendingOnEndAction != null;
    }

    /**
     * Starts the underlying Animator for a set of properties. We use a single animator that
     * simply runs from 0 to 1, and then use that fractional value to set each property
     * value accordingly.
     */
    private void startAnimation() {
        if (mRTBackend != null && mRTBackend.startAnimation(this)) {
            return;
        }
        mView.setHasTransientState(true);
        ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
        ArrayList<NameValuesHolder> nameValueList =
+118 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view;

import android.animation.TimeInterpolator;
import android.view.ViewPropertyAnimator.NameValuesHolder;

import com.android.internal.view.animation.FallbackLUTInterpolator;

import java.util.ArrayList;


/**
 * This is a RenderThread driven backend for ViewPropertyAnimator.
 */
class ViewPropertyAnimatorRT {

    private final View mView;

    private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1];

    ViewPropertyAnimatorRT(View view) {
        mView = view;
    }

    /**
     * @return true if ViewPropertyAnimatorRT handled the animation,
     *         false if ViewPropertyAnimator needs to handle it
     */
    public boolean startAnimation(ViewPropertyAnimator parent) {
        cancelAnimators(parent.mPendingAnimations);
        if (!canHandleAnimator(parent)) {
            return false;
        }
        doStartAnimation(parent);
        return true;
    }

    private void doStartAnimation(ViewPropertyAnimator parent) {
        int size = parent.mPendingAnimations.size();

        long startDelay = parent.getStartDelay();
        long duration = parent.getDuration();
        TimeInterpolator interpolator = parent.getInterpolator();
        if (!RenderNodeAnimator.isNativeInterpolator(interpolator)) {
            interpolator = new FallbackLUTInterpolator(interpolator, duration);
        }
        for (int i = 0; i < size; i++) {
            NameValuesHolder holder = parent.mPendingAnimations.get(i);
            int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);

            RenderNodeAnimator animator = new RenderNodeAnimator(property, holder.mFromValue + holder.mDeltaValue);
            animator.setStartDelay(startDelay);
            animator.setDuration(duration);
            animator.setInterpolator(interpolator);
            animator.setTarget(mView);
            animator.start();
        }

        parent.mPendingAnimations.clear();
    }

    private boolean canHandleAnimator(ViewPropertyAnimator parent) {
        // TODO: Can we eliminate this entirely?
        // If RenderNode.animatorProperties() can be toggled to point at staging
        // instead then RNA can be used as the animators for software as well
        // as the updateListener fallback paths. If this can be toggled
        // at the top level somehow, combined with requiresUiRedraw, we could
        // ensure that RT does not self-animate, allowing for safe driving of
        // the animators from the UI thread using the same mechanisms
        // ViewPropertyAnimator does, just with everything sitting on a single
        // animator subsystem instead of multiple.

        if (parent.getUpdateListener() != null) {
            return false;
        }
        if (parent.getListener() != null) {
            // TODO support
            return false;
        }
        if (!mView.isHardwareAccelerated()) {
            // TODO handle this maybe?
            return false;
        }
        if (parent.hasActions()) {
            return false;
        }
        // Here goes nothing...
        return true;
    }

    private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) {
        int size = mPendingAnimations.size();
        for (int i = 0; i < size; i++) {
            NameValuesHolder holder = mPendingAnimations.get(i);
            int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant);
            if (mAnimators[property] != null) {
                mAnimators[property].cancel();
                mAnimators[property] = null;
            }
        }
    }

}
+10 −1
Original line number Diff line number Diff line
@@ -24,10 +24,13 @@ import android.view.Choreographer;
 * Interpolator that builds a lookup table to use. This is a fallback for
 * building a native interpolator from a TimeInterpolator that is not marked
 * with {@link HasNativeInterpolator}
 *
 * This implements TimeInterpolator to allow for easier interop with Animators
 */
@HasNativeInterpolator
public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator {

    private TimeInterpolator mSourceInterpolator;
    private final float mLut[];

    /**
@@ -35,6 +38,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
     * interpolator creation
     */
    public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) {
        mSourceInterpolator = interpolator;
        mLut = createLUT(interpolator, duration);
    }

@@ -63,4 +67,9 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory {
        float[] lut = createLUT(interpolator, duration);
        return NativeInterpolatorFactoryHelper.createLutInterpolator(lut);
    }

    @Override
    public float getInterpolation(float input) {
        return mSourceInterpolator.getInterpolation(input);
    }
}
+1 −1
Original line number Diff line number Diff line
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := tests

# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
Loading