diff options
18 files changed, 371 insertions, 18 deletions
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 33964a0..8f4b710 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -245,6 +245,9 @@ public class TimeUtils { private static final int SECONDS_PER_HOUR = 60 * 60; private static final int SECONDS_PER_DAY = 24 * 60 * 60; + /** @hide */ + public static final long NANOS_PER_MS = 1000000; + private static final Object sFormatSync = new Object(); private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5]; diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java index 0a76075..1066430 100644 --- a/core/java/android/view/Choreographer.java +++ b/core/java/android/view/Choreographer.java @@ -112,8 +112,6 @@ public final class Choreographer { private static final int SKIPPED_FRAME_WARNING_LIMIT = SystemProperties.getInt( "debug.choreographer.skipwarning", 30); - private static final long NANOS_PER_MS = 1000000; - private static final int MSG_DO_FRAME = 0; private static final int MSG_DO_SCHEDULE_VSYNC = 1; private static final int MSG_DO_SCHEDULE_CALLBACK = 2; @@ -263,7 +261,7 @@ public final class Choreographer { * @return The refresh rate as the nanoseconds between frames * @hide */ - long getFrameIntervalNanos() { + public long getFrameIntervalNanos() { return mFrameIntervalNanos; } @@ -456,7 +454,7 @@ public final class Choreographer { * @hide */ public long getFrameTime() { - return getFrameTimeNanos() / NANOS_PER_MS; + return getFrameTimeNanos() / TimeUtils.NANOS_PER_MS; } /** @@ -497,7 +495,7 @@ public final class Choreographer { } } else { final long nextFrameTime = Math.max( - mLastFrameTimeNanos / NANOS_PER_MS + sFrameDelay, now); + mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now); if (DEBUG) { Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms."); } @@ -746,7 +744,7 @@ public final class Choreographer { mFrame = frame; Message msg = Message.obtain(mHandler, this); msg.setAsynchronous(true); - mHandler.sendMessageAtTime(msg, timestampNanos / NANOS_PER_MS); + mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS); } @Override diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index be3b6ce..ec4d560 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -16,12 +16,17 @@ package android.view; +import android.animation.TimeInterpolator; import android.graphics.Canvas; import android.graphics.CanvasProperty; import android.graphics.Paint; import android.util.SparseIntArray; +import android.util.TimeUtils; import com.android.internal.util.VirtualRefBasePtr; +import com.android.internal.view.animation.FallbackLUTInterpolator; +import com.android.internal.view.animation.HasNativeInterpolator; +import com.android.internal.view.animation.NativeInterpolatorFactory; import java.lang.ref.WeakReference; @@ -71,9 +76,12 @@ public final class RenderNodeAnimator { public static final int DELTA_TYPE_ABSOLUTE = 0; public static final int DELTA_TYPE_DELTA = 1; - private RenderNode mTarget; private VirtualRefBasePtr mNativePtr; + private RenderNode mTarget; + private TimeInterpolator mInterpolator; + private boolean mStarted = false; + public int mapViewPropertyToRenderProperty(int viewProperty) { return sViewPropertyAnimatorMap.get(viewProperty); } @@ -100,9 +108,37 @@ public final class RenderNodeAnimator { mNativePtr = new VirtualRefBasePtr(ptr); } - public void start(View target) { - mTarget = target.mRenderNode; + private void checkMutable() { + if (mStarted) { + throw new IllegalStateException("Animator has already started, cannot change it now!"); + } + } + + private void applyInterpolator() { + if (mInterpolator == null) return; + + long ni; + if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) { + ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator(); + } else { + int duration = nGetDuration(mNativePtr.get()); + ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration); + } + nSetInterpolator(mNativePtr.get(), ni); + } + + private void start(RenderNode node) { + if (mStarted) { + throw new IllegalStateException("Already started!"); + } + mStarted = true; + applyInterpolator(); + mTarget = node; mTarget.addAnimator(this); + } + + public void start(View target) { + start(target.mRenderNode); // Kick off a frame to start the process target.invalidateViewProperty(true, false); } @@ -112,8 +148,7 @@ public final class RenderNodeAnimator { throw new IllegalArgumentException("Not a GLES20RecordingCanvas"); } GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas; - mTarget = recordingCanvas.mNode; - mTarget.addAnimator(this); + start(recordingCanvas.mNode); } public void cancel() { @@ -121,9 +156,15 @@ public final class RenderNodeAnimator { } public void setDuration(int duration) { + checkMutable(); nSetDuration(mNativePtr.get(), duration); } + public void setInterpolator(TimeInterpolator interpolator) { + checkMutable(); + mInterpolator = interpolator; + } + long getNativeAnimator() { return mNativePtr.get(); } @@ -147,4 +188,6 @@ public final class RenderNodeAnimator { private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis, long canvasProperty, int paintField, int deltaValueType, float deltaValue); private static native void nSetDuration(long nativePtr, int duration); + private static native int nGetDuration(long nativePtr); + private static native void nSetInterpolator(long animPtr, long interpolatorPtr); } diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 2587ba1..5653066 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.SurfaceTexture; import android.os.Trace; +import android.util.TimeUtils; import android.view.Surface.OutOfResourcesException; import android.view.View.AttachInfo; @@ -51,8 +52,6 @@ public class ThreadedRenderer extends HardwareRenderer { private static final Rect NULL_RECT = new Rect(); - private static final long NANOS_PER_MS = 1000000; - // Keep in sync with DrawFrameTask.h SYNC_* flags // Nothing interesting to report private static final int SYNC_OK = 0x0; @@ -203,7 +202,7 @@ public class ThreadedRenderer extends HardwareRenderer { void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) { attachInfo.mIgnoreDirtyState = true; long frameTimeNanos = mChoreographer.getFrameTimeNanos(); - attachInfo.mDrawingTime = frameTimeNanos / NANOS_PER_MS; + attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS; updateRootDisplayList(view, callbacks); diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java index 158c56e..ed6949a 100644 --- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java +++ b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java @@ -19,12 +19,17 @@ package android.view.animation; import android.content.Context; import android.util.AttributeSet; +import com.android.internal.view.animation.HasNativeInterpolator; +import com.android.internal.view.animation.NativeInterpolatorFactory; +import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; + /** * An interpolator where the rate of change starts and ends slowly but * accelerates through the middle. * */ -public class AccelerateDecelerateInterpolator implements Interpolator { +@HasNativeInterpolator +public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory { public AccelerateDecelerateInterpolator() { } @@ -35,4 +40,10 @@ public class AccelerateDecelerateInterpolator implements Interpolator { public float getInterpolation(float input) { return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } + + /** @hide */ + @Override + public long createNativeInterpolator() { + return NativeInterpolatorFactoryHelper.createAccelerateDecelerateInterpolator(); + } } diff --git a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java new file mode 100644 index 0000000..aec2b7e --- /dev/null +++ b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java @@ -0,0 +1,66 @@ +/* + * 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 com.android.internal.view.animation; + +import android.animation.TimeInterpolator; +import android.util.TimeUtils; +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} + */ +@HasNativeInterpolator +public class FallbackLUTInterpolator implements NativeInterpolatorFactory { + + private final float mLut[]; + + /** + * Used to cache the float[] LUT for use across multiple native + * interpolator creation + */ + public FallbackLUTInterpolator(TimeInterpolator interpolator, int duration) { + mLut = createLUT(interpolator, duration); + } + + private static float[] createLUT(TimeInterpolator interpolator, int duration) { + long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos(); + int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS); + int numAnimFrames = (int) Math.ceil(duration / animIntervalMs); + float values[] = new float[numAnimFrames]; + float lastFrame = numAnimFrames - 1; + for (int i = 0; i < numAnimFrames; i++) { + float inValue = i / lastFrame; + values[i] = interpolator.getInterpolation(inValue); + } + return values; + } + + @Override + public long createNativeInterpolator() { + return NativeInterpolatorFactoryHelper.createLutInterpolator(mLut); + } + + /** + * Used to create a one-shot float[] LUT & native interpolator + */ + public static long createNativeInterpolator(TimeInterpolator interpolator, int duration) { + float[] lut = createLUT(interpolator, duration); + return NativeInterpolatorFactoryHelper.createLutInterpolator(lut); + } +} diff --git a/core/java/com/android/internal/view/animation/HasNativeInterpolator.java b/core/java/com/android/internal/view/animation/HasNativeInterpolator.java new file mode 100644 index 0000000..48ea4da --- /dev/null +++ b/core/java/com/android/internal/view/animation/HasNativeInterpolator.java @@ -0,0 +1,37 @@ +/* + * 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 com.android.internal.view.animation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This is a class annotation that signals that it is safe to create + * a native interpolator counterpart via {@link NativeInterpolatorFactory} + * + * The idea here is to prevent subclasses of interpolators from being treated as a + * NativeInterpolatorFactory, and instead have them fall back to the LUT & LERP + * method like a custom interpolator. + * + * @hide + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE}) +public @interface HasNativeInterpolator { +} diff --git a/core/java/com/android/internal/view/animation/NativeInterpolatorFactory.java b/core/java/com/android/internal/view/animation/NativeInterpolatorFactory.java new file mode 100644 index 0000000..fcacd52 --- /dev/null +++ b/core/java/com/android/internal/view/animation/NativeInterpolatorFactory.java @@ -0,0 +1,21 @@ +/* + * 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 com.android.internal.view.animation; + +public interface NativeInterpolatorFactory { + long createNativeInterpolator(); +} diff --git a/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java b/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java new file mode 100644 index 0000000..2b25280 --- /dev/null +++ b/core/java/com/android/internal/view/animation/NativeInterpolatorFactoryHelper.java @@ -0,0 +1,28 @@ +/* + * 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 com.android.internal.view.animation; + +/** + * Static utility class for constructing native interpolators to keep the + * JNI simpler + */ +public final class NativeInterpolatorFactoryHelper { + private NativeInterpolatorFactoryHelper() {} + + public static native long createAccelerateDecelerateInterpolator(); + public static native long createLutInterpolator(float[] values); +} diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 26f77b5..7dc639d 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -156,7 +156,8 @@ LOCAL_SRC_FILES:= \ android_animation_PropertyValuesHolder.cpp \ com_android_internal_net_NetworkStatsFactory.cpp \ com_android_internal_os_Zygote.cpp \ - com_android_internal_util_VirtualRefBasePtr.cpp + com_android_internal_util_VirtualRefBasePtr.cpp \ + com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 9941cd9..01d8814 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -131,6 +131,7 @@ extern int register_android_view_Surface(JNIEnv* env); extern int register_android_view_SurfaceControl(JNIEnv* env); extern int register_android_view_SurfaceSession(JNIEnv* env); extern int register_android_view_TextureView(JNIEnv* env); +extern int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv *env); extern int register_android_database_CursorWindow(JNIEnv* env); extern int register_android_database_SQLiteConnection(JNIEnv* env); extern int register_android_database_SQLiteGlobal(JNIEnv* env); @@ -1206,6 +1207,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_view_SurfaceControl), REG_JNI(register_android_view_SurfaceSession), REG_JNI(register_android_view_TextureView), + REG_JNI(register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper), REG_JNI(register_com_google_android_gles_jni_EGLImpl), REG_JNI(register_com_google_android_gles_jni_GLImpl), REG_JNI(register_android_opengl_jni_EGL14), diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index 4787d28..5733f60 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -132,6 +132,17 @@ static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint dura animator->setDuration(duration); } +static jint getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) { + BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); + return static_cast<jint>(animator->duration()); +} + +static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) { + BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); + Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); + animator->setInterpolator(interpolator); +} + #endif // ---------------------------------------------------------------------------- @@ -146,6 +157,8 @@ static JNINativeMethod gMethods[] = { { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator }, { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator }, { "nSetDuration", "(JI)V", (void*) setDuration }, + { "nGetDuration", "(J)I", (void*) getDuration }, + { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, #endif }; diff --git a/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp new file mode 100644 index 0000000..c2d3dd1 --- /dev/null +++ b/core/jni/com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#define LOG_TAG "OpenGLRenderer" + +#include "jni.h" +#include <nativehelper/JNIHelp.h> +#include <android_runtime/AndroidRuntime.h> + +#include <Interpolator.h> + +namespace android { + +using namespace uirenderer; + +#ifdef USE_OPENGL_RENDERER + +static jlong createAccelerateDecelerateInterpolator(JNIEnv* env, jobject clazz) { + return reinterpret_cast<jlong>(new AccelerateDecelerateInterpolator()); +} + +static jlong createLutInterpolator(JNIEnv* env, jobject clazz, jfloatArray jlut) { + jsize len = env->GetArrayLength(jlut); + if (len <= 0) { + return 0; + } + float* lut = new float[len]; + env->GetFloatArrayRegion(jlut, 0, len, lut); + return reinterpret_cast<jlong>(new LUTInterpolator(lut, len)); +} + +#endif + +// ---------------------------------------------------------------------------- +// JNI Glue +// ---------------------------------------------------------------------------- + +const char* const kClassPathName = "com/android/internal/view/animation/NativeInterpolatorFactoryHelper"; + +static JNINativeMethod gMethods[] = { +#ifdef USE_OPENGL_RENDERER + { "createAccelerateDecelerateInterpolator", "()J", (void*) createAccelerateDecelerateInterpolator }, + { "createLutInterpolator", "([F)J", (void*) createLutInterpolator }, +#endif +}; + +int register_com_android_internal_view_animation_NativeInterpolatorFactoryHelper(JNIEnv* env) { + return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); +} + + +} // namespace android diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 86fc7c3..52a1807 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -45,6 +45,7 @@ public: ANDROID_API void setInterpolator(Interpolator* interpolator); ANDROID_API void setDuration(nsecs_t durationInMs); + ANDROID_API nsecs_t duration() { return mDuration; } ANDROID_API void setListener(AnimationListener* listener) { mListener = listener; } diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp index 004ddf5..b56648e 100644 --- a/libs/hwui/Interpolator.cpp +++ b/libs/hwui/Interpolator.cpp @@ -13,9 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#define LOG_TAG "Interpolator" + #include "Interpolator.h" #include <math.h> +#include <cutils/log.h> + +#include "utils/MathUtils.h" namespace android { namespace uirenderer { @@ -28,5 +34,34 @@ float AccelerateDecelerateInterpolator::interpolate(float input) { return (float)(cosf((input + 1) * M_PI) / 2.0f) + 0.5f; } +LUTInterpolator::LUTInterpolator(float* values, size_t size) { + mValues = values; + mSize = size; +} + +LUTInterpolator::~LUTInterpolator() { + delete mValues; + mValues = 0; +} + +float LUTInterpolator::interpolate(float input) { + float lutpos = input * mSize; + if (lutpos >= (mSize - 1)) { + return mValues[mSize - 1]; + } + + float ipart, weight; + weight = modff(lutpos, &ipart); + + int i1 = (int) ipart; + int i2 = MathUtils::min(i1 + 1, mSize - 1); + + float v1 = mValues[i1]; + float v2 = mValues[i2]; + + return MathUtils::lerp(v1, v2, weight); +} + + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h index 2cfb60c..44fb37c 100644 --- a/libs/hwui/Interpolator.h +++ b/libs/hwui/Interpolator.h @@ -16,6 +16,10 @@ #ifndef INTERPOLATOR_H #define INTERPOLATOR_H +#include <stddef.h> + +#include <cutils/compiler.h> + namespace android { namespace uirenderer { @@ -31,7 +35,7 @@ protected: Interpolator() {} }; -class AccelerateDecelerateInterpolator : public Interpolator { +class ANDROID_API AccelerateDecelerateInterpolator : public Interpolator { public: AccelerateDecelerateInterpolator() {} virtual ~AccelerateDecelerateInterpolator() {} @@ -39,6 +43,18 @@ public: virtual float interpolate(float input); }; +class ANDROID_API LUTInterpolator : public Interpolator { +public: + LUTInterpolator(float* values, size_t size); + ~LUTInterpolator(); + + virtual float interpolate(float input); + +private: + float* mValues; + size_t mSize; +}; + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h index 8ba44dc..1a7082b 100644 --- a/libs/hwui/utils/MathUtils.h +++ b/libs/hwui/utils/MathUtils.h @@ -33,6 +33,14 @@ public: inline static bool isPositive(float value) { return value >= gNonZeroEpsilon; } + + inline static int min(int a, int b) { + return a < b ? a : b; + } + + inline static float lerp(float v1, float v2, float t) { + return v1 + ((v2 - v1) * t); + } }; // class MathUtils } /* namespace uirenderer */ diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java index 5c273de..1d0a806 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CirclePropActivity.java @@ -16,6 +16,7 @@ package com.android.test.hwui; +import android.animation.TimeInterpolator; import android.app.Activity; import android.content.Context; import android.graphics.Canvas; @@ -27,6 +28,8 @@ import android.os.Trace; import android.view.HardwareCanvas; import android.view.RenderNodeAnimator; import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.OvershootInterpolator; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -122,8 +125,11 @@ public class CirclePropActivity extends Activity { mPaint, RenderNodeAnimator.PAINT_STROKE_WIDTH, RenderNodeAnimator.DELTA_TYPE_ABSOLUTE, mToggle ? 5.0f : 60.0f)); + TimeInterpolator interp = new OvershootInterpolator(3.0f); for (int i = 0; i < mRunningAnimations.size(); i++) { - mRunningAnimations.get(i).start(this); + RenderNodeAnimator anim = mRunningAnimations.get(i); + anim.setInterpolator(interp); + anim.start(this); } if (mToggle) { |