Merge "Add TimeInterpolator support to RNA"

This commit is contained in:
John Reck
2014-05-12 22:11:00 +00:00
committed by Android (Google) Code Review
18 changed files with 371 additions and 18 deletions

View File

@@ -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];

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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 {
}

View File

@@ -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();
}

View File

@@ -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);
}