Revert "DO NOT MERGE Backport of limited jank-tracking metrics"

This reverts commit 2614bd225f84f7a23e6b30fc6b47bede153e5f4c.

Change-Id: I344b4cbaa0bb0caf50bceb806d1446ee27ea52d8
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4a8714c..8353d54 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1083,7 +1083,7 @@
         @Override
         public void dumpGfxInfo(FileDescriptor fd, String[] args) {
             dumpGraphicsInfo(fd);
-            WindowManagerGlobal.getInstance().dumpGfxInfo(fd, args);
+            WindowManagerGlobal.getInstance().dumpGfxInfo(fd);
         }
 
         @Override
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index c8149d9..f41afcf 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -141,19 +141,6 @@
     private long mFrameIntervalNanos;
 
     /**
-     * Contains information about the current frame for jank-tracking,
-     * mainly timings of key events along with a bit of metadata about
-     * view tree state
-     *
-     * TODO: Is there a better home for this? Currently Choreographer
-     * is the only one with CALLBACK_ANIMATION start time, hence why this
-     * resides here.
-     *
-     * @hide
-     */
-    FrameInfo mFrameInfo = new FrameInfo();
-
-    /**
      * Callback type: Input callback.  Runs first.
      * @hide
      */
@@ -526,7 +513,6 @@
                 return; // no work to do
             }
 
-            long intendedFrameTimeNanos = frameTimeNanos;
             startNanos = System.nanoTime();
             final long jitterNanos = startNanos - frameTimeNanos;
             if (jitterNanos >= mFrameIntervalNanos) {
@@ -555,18 +541,12 @@
                 return;
             }
 
-            mFrameInfo.setVsync(intendedFrameTimeNanos, frameTimeNanos);
             mFrameScheduled = false;
             mLastFrameTimeNanos = frameTimeNanos;
         }
 
-        mFrameInfo.markInputHandlingStart();
         doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
-
-        mFrameInfo.markAnimationsStart();
         doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
-
-        mFrameInfo.markPerformTraversalsStart();
         doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
 
         if (DEBUG) {
diff --git a/core/java/android/view/FrameInfo.java b/core/java/android/view/FrameInfo.java
deleted file mode 100644
index c79547c..0000000
--- a/core/java/android/view/FrameInfo.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2015 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.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Class that contains all the timing information for the current frame. This
- * is used in conjunction with the hardware renderer to provide
- * continous-monitoring jank events
- *
- * All times in nanoseconds from CLOCK_MONOTONIC/System.nanoTime()
- *
- * To minimize overhead from System.nanoTime() calls we infer durations of
- * things by knowing the ordering of the events. For example, to know how
- * long layout & measure took it's displayListRecordStart - performTraversalsStart.
- *
- * These constants must be kept in sync with FrameInfo.h in libhwui and are
- * used for indexing into AttachInfo's mFrameInfo long[], which is intended
- * to be quick to pass down to native via JNI, hence a pre-packed format
- *
- * @hide
- */
-final class FrameInfo {
-
-    long[] mFrameInfo = new long[9];
-
-    // Various flags set to provide extra metadata about the current frame
-    private static final int FLAGS = 0;
-
-    // Is this the first-draw following a window layout?
-    public static final long FLAG_WINDOW_LAYOUT_CHANGED = 1;
-
-    @IntDef(flag = true, value = {
-            FLAG_WINDOW_LAYOUT_CHANGED })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface FrameInfoFlags {}
-
-    // The intended vsync time, unadjusted by jitter
-    private static final int INTENDED_VSYNC = 1;
-
-    // Jitter-adjusted vsync time, this is what was used as input into the
-    // animation & drawing system
-    private static final int VSYNC = 2;
-
-    // The time of the oldest input event
-    private static final int OLDEST_INPUT_EVENT = 3;
-
-    // The time of the newest input event
-    private static final int NEWEST_INPUT_EVENT = 4;
-
-    // When input event handling started
-    private static final int HANDLE_INPUT_START = 5;
-
-    // When animation evaluations started
-    private static final int ANIMATION_START = 6;
-
-    // When ViewRootImpl#performTraversals() started
-    private static final int PERFORM_TRAVERSALS_START = 7;
-
-    // When View:draw() started
-    private static final int DRAW_START = 8;
-
-    public void setVsync(long intendedVsync, long usedVsync) {
-        mFrameInfo[INTENDED_VSYNC] = intendedVsync;
-        mFrameInfo[VSYNC] = usedVsync;
-        mFrameInfo[OLDEST_INPUT_EVENT] = Long.MAX_VALUE;
-        mFrameInfo[NEWEST_INPUT_EVENT] = 0;
-        mFrameInfo[FLAGS] = 0;
-    }
-
-    public void updateInputEventTime(long inputEventTime, long inputEventOldestTime) {
-        if (inputEventOldestTime < mFrameInfo[OLDEST_INPUT_EVENT]) {
-            mFrameInfo[OLDEST_INPUT_EVENT] = inputEventOldestTime;
-        }
-        if (inputEventTime > mFrameInfo[NEWEST_INPUT_EVENT]) {
-            mFrameInfo[NEWEST_INPUT_EVENT] = inputEventTime;
-        }
-    }
-
-    public void markInputHandlingStart() {
-        mFrameInfo[HANDLE_INPUT_START] = System.nanoTime();
-    }
-
-    public void markAnimationsStart() {
-        mFrameInfo[ANIMATION_START] = System.nanoTime();
-    }
-
-    public void markPerformTraversalsStart() {
-        mFrameInfo[PERFORM_TRAVERSALS_START] = System.nanoTime();
-    }
-
-    public void markDrawStart() {
-        mFrameInfo[DRAW_START] = System.nanoTime();
-    }
-
-    public void addFlags(@FrameInfoFlags long flags) {
-        mFrameInfo[FLAGS] |= flags;
-    }
-
-}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index aa61885..c5c3f83 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -278,7 +278,7 @@
     /**
      * Outputs extra debugging information in the specified file descriptor.
      */
-    abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args);
+    abstract void dumpGfxInfo(PrintWriter pw, FileDescriptor fd);
 
     /**
      * Loads system properties used by the renderer. This method is invoked
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index df0838f..ad4a048 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -16,7 +16,8 @@
 
 package android.view;
 
-import android.annotation.IntDef;
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -26,18 +27,16 @@
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
 import android.os.Trace;
 import android.util.Log;
 import android.util.LongSparseArray;
+import android.util.TimeUtils;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
 
-import com.android.internal.R;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.HashSet;
 
@@ -75,14 +74,6 @@
         PROFILE_PROPERTY_VISUALIZE_BARS,
     };
 
-    private static final int FLAG_DUMP_FRAMESTATS   = 1 << 0;
-    private static final int FLAG_DUMP_RESET        = 1 << 1;
-
-    @IntDef(flag = true, value = {
-            FLAG_DUMP_FRAMESTATS, FLAG_DUMP_RESET })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface DumpFlags {}
-
     // Size of the rendered content.
     private int mWidth, mHeight;
 
@@ -102,12 +93,12 @@
     private final float mLightRadius;
     private final int mAmbientShadowAlpha;
     private final int mSpotShadowAlpha;
-    private final float mDensity;
 
     private long mNativeProxy;
     private boolean mInitialized = false;
     private RenderNode mRootNode;
     private Choreographer mChoreographer;
+    private boolean mProfilingEnabled;
     private boolean mRootNodeNeedsUpdate;
 
     ThreadedRenderer(Context context, boolean translucent) {
@@ -119,7 +110,6 @@
                 (int) (255 * a.getFloat(R.styleable.Lighting_ambientShadowAlpha, 0) + 0.5f);
         mSpotShadowAlpha = (int) (255 * a.getFloat(R.styleable.Lighting_spotShadowAlpha, 0) + 0.5f);
         a.recycle();
-        mDensity = context.getResources().getDisplayMetrics().density;
 
         long rootNodePtr = nCreateRootRenderNode();
         mRootNode = RenderNode.adopt(rootNodePtr);
@@ -224,7 +214,7 @@
         mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
         nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight,
                 lightX, mLightY, mLightZ, mLightRadius,
-                mAmbientShadowAlpha, mSpotShadowAlpha, mDensity);
+                mAmbientShadowAlpha, mSpotShadowAlpha);
     }
 
     @Override
@@ -243,25 +233,32 @@
     }
 
     @Override
-    void dumpGfxInfo(PrintWriter pw, FileDescriptor fd, String[] args) {
+    void dumpGfxInfo(PrintWriter pw, FileDescriptor fd) {
         pw.flush();
-        int flags = 0;
-        for (int i = 0; i < args.length; i++) {
-            switch (args[i]) {
-                case "framestats":
-                    flags |= FLAG_DUMP_FRAMESTATS;
-                    break;
-                case "reset":
-                    flags |= FLAG_DUMP_RESET;
-                    break;
-            }
+        nDumpProfileInfo(mNativeProxy, fd);
+    }
+
+    private static int search(String[] values, String value) {
+        for (int i = 0; i < values.length; i++) {
+            if (values[i].equals(value)) return i;
         }
-        nDumpProfileInfo(mNativeProxy, fd, flags);
+        return -1;
+    }
+
+    private static boolean checkIfProfilingRequested() {
+        String profiling = SystemProperties.get(HardwareRenderer.PROFILE_PROPERTY);
+        int graphType = search(VISUALIZERS, profiling);
+        return (graphType >= 0) || Boolean.parseBoolean(profiling);
     }
 
     @Override
     boolean loadSystemProperties() {
         boolean changed = nLoadSystemProperties(mNativeProxy);
+        boolean wantProfiling = checkIfProfilingRequested();
+        if (wantProfiling != mProfilingEnabled) {
+            mProfilingEnabled = wantProfiling;
+            changed = true;
+        }
         if (changed) {
             invalidateRoot();
         }
@@ -310,12 +307,20 @@
     @Override
     void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
         attachInfo.mIgnoreDirtyState = true;
+        long frameTimeNanos = mChoreographer.getFrameTimeNanos();
+        attachInfo.mDrawingTime = frameTimeNanos / TimeUtils.NANOS_PER_MS;
 
-        final Choreographer choreographer = attachInfo.mViewRootImpl.mChoreographer;
-        choreographer.mFrameInfo.markDrawStart();
+        long recordDuration = 0;
+        if (mProfilingEnabled) {
+            recordDuration = System.nanoTime();
+        }
 
         updateRootDisplayList(view, callbacks);
 
+        if (mProfilingEnabled) {
+            recordDuration = System.nanoTime() - recordDuration;
+        }
+
         attachInfo.mIgnoreDirtyState = false;
 
         // register animating rendernodes which started animating prior to renderer
@@ -332,8 +337,8 @@
             attachInfo.mPendingAnimatingRenderNodes = null;
         }
 
-        final long[] frameInfo = choreographer.mFrameInfo.mFrameInfo;
-        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameInfo, frameInfo.length);
+        int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos,
+                recordDuration, view.getResources().getDisplayMetrics().density);
         if ((syncResult & SYNC_LOST_SURFACE_REWARD_IF_FOUND) != 0) {
             setEnabled(false);
             attachInfo.mViewRootImpl.mSurface.release();
@@ -495,9 +500,10 @@
     private static native boolean nPauseSurface(long nativeProxy, Surface window);
     private static native void nSetup(long nativeProxy, int width, int height,
             float lightX, float lightY, float lightZ, float lightRadius,
-            int ambientShadowAlpha, int spotShadowAlpha, float density);
+            int ambientShadowAlpha, int spotShadowAlpha);
     private static native void nSetOpaque(long nativeProxy, boolean opaque);
-    private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
+    private static native int nSyncAndDrawFrame(long nativeProxy,
+            long frameTimeNanos, long recordDuration, float density);
     private static native void nDestroy(long nativeProxy);
     private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode);
 
@@ -517,6 +523,5 @@
     private static native void nStopDrawing(long nativeProxy);
     private static native void nNotifyFramePending(long nativeProxy);
 
-    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd,
-            @DumpFlags int dumpFlags);
+    private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd);
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3566140..e4d82b1 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -56,7 +56,6 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Slog;
-import android.util.TimeUtils;
 import android.util.TypedValue;
 import android.view.Surface.OutOfResourcesException;
 import android.view.View.AttachInfo;
@@ -1503,7 +1502,6 @@
                         // to resume them
                         mDirty.set(0, 0, mWidth, mHeight);
                     }
-                    mChoreographer.mFrameInfo.addFlags(FrameInfo.FLAG_WINDOW_LAYOUT_CHANGED);
                 }
                 final int surfaceGenerationId = mSurface.getGenerationId();
                 relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
@@ -2507,9 +2505,6 @@
             }
         }
 
-        mAttachInfo.mDrawingTime =
-                mChoreographer.getFrameTimeNanos() / TimeUtils.NANOS_PER_MS;
-
         if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
             if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
                 // If accessibility focus moved, always invalidate the root.
@@ -2629,6 +2624,7 @@
 
             dirty.setEmpty();
             mIsAnimating = false;
+            attachInfo.mDrawingTime = SystemClock.uptimeMillis();
             mView.mPrivateFlags |= View.PFLAG_DRAWN;
 
             if (DEBUG_DRAW) {
@@ -5782,16 +5778,6 @@
             Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
                     mPendingInputEventCount);
 
-            long eventTime = q.mEvent.getEventTimeNano();
-            long oldestEventTime = eventTime;
-            if (q.mEvent instanceof MotionEvent) {
-                MotionEvent me = (MotionEvent)q.mEvent;
-                if (me.getHistorySize() > 0) {
-                    oldestEventTime = me.getHistoricalEventTimeNano(0);
-                }
-            }
-            mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
-
             deliverInputEvent(q);
         }
 
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 643340a..a14c766 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -459,7 +459,7 @@
         }
     }
 
-    public void dumpGfxInfo(FileDescriptor fd, String[] args) {
+    public void dumpGfxInfo(FileDescriptor fd) {
         FileOutputStream fout = new FileOutputStream(fd);
         PrintWriter pw = new FastPrintWriter(fout);
         try {
@@ -476,7 +476,7 @@
                     HardwareRenderer renderer =
                             root.getView().mAttachInfo.mHardwareRenderer;
                     if (renderer != null) {
-                        renderer.dumpGfxInfo(pw, fd, args);
+                        renderer.dumpGfxInfo(pw, fd);
                     }
                 }
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 8590aca..a39ff8e 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -49,7 +49,6 @@
 
 #include <AnimationContext.h>
 #include <DisplayListRenderer.h>
-#include <FrameInfo.h>
 #include <RenderNode.h>
 #include <renderthread/RenderProxy.h>
 
@@ -395,7 +394,7 @@
     proxy->initialize(surface);
     // Shadows can't be used via this interface, so just set the light source
     // to all 0s. (and width & height are unused, TODO remove them)
-    proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0, 1.0f);
+    proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0);
     return (jlong) proxy;
 }
 
@@ -407,11 +406,8 @@
 
 static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
-    nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
-    UiFrameInfoBuilder(proxy->frameInfo())
-            .setVsync(vsync, vsync)
-            .addFlag(FrameInfoFlags::kSurfaceCanvas);
-    proxy->syncAndDrawFrame();
+    nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
+    proxy->syncAndDrawFrame(frameTimeNs, 0, 1.0f);
 }
 
 static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 00d7fc8..b9d849c 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -283,10 +283,10 @@
 static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr,
         jint width, jint height,
         jfloat lightX, jfloat lightY, jfloat lightZ, jfloat lightRadius,
-        jint ambientShadowAlpha, jint spotShadowAlpha, jfloat density) {
+        jint ambientShadowAlpha, jint spotShadowAlpha) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     proxy->setup(width, height, (Vector3){lightX, lightY, lightZ}, lightRadius,
-            ambientShadowAlpha, spotShadowAlpha, density);
+            ambientShadowAlpha, spotShadowAlpha);
 }
 
 static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
@@ -296,13 +296,9 @@
 }
 
 static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
-    LOG_ALWAYS_FATAL_IF(frameInfoSize != UI_THREAD_FRAME_INFO_SIZE,
-            "Mismatched size expectations, given %d expected %d",
-            frameInfoSize, UI_THREAD_FRAME_INFO_SIZE);
+        jlong proxyPtr, jlong frameTimeNanos, jlong recordDuration, jfloat density) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
-    return proxy->syncAndDrawFrame();
+    return proxy->syncAndDrawFrame(frameTimeNanos, recordDuration, density);
 }
 
 static void android_view_ThreadedRenderer_destroy(JNIEnv* env, jobject clazz,
@@ -397,10 +393,10 @@
 }
 
 static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jobject javaFileDescriptor, jint dumpFlags) {
+        jlong proxyPtr, jobject javaFileDescriptor) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
     int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
-    proxy->dumpProfileInfo(fd, dumpFlags);
+    proxy->dumpProfileInfo(fd);
 }
 
 #endif
@@ -434,9 +430,9 @@
     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
     { "nPauseSurface", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_pauseSurface },
-    { "nSetup", "(JIIFFFFIIF)V", (void*) android_view_ThreadedRenderer_setup },
+    { "nSetup", "(JIIFFFFII)V", (void*) android_view_ThreadedRenderer_setup },
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
-    { "nSyncAndDrawFrame", "(J[JI)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+    { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
     { "nDestroy", "(J)V", (void*) android_view_ThreadedRenderer_destroy },
     { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode },
     { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
@@ -451,7 +447,7 @@
     { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
     { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
-    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;I)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
+    { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
 #endif
     { "setupShadersDiskCache", "(Ljava/lang/String;)V",
                 (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 507472a..49560ff 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -18,7 +18,6 @@
 		AssetAtlas.cpp \
 		DamageAccumulator.cpp \
 		FontRenderer.cpp \
-		FrameInfo.cpp \
 		GammaFontRenderer.cpp \
 		Caches.cpp \
 		DisplayList.cpp \
@@ -33,7 +32,6 @@
 		GradientCache.cpp \
 		Image.cpp \
 		Interpolator.cpp \
-		JankTracker.cpp \
 		Layer.cpp \
 		LayerCache.cpp \
 		LayerRenderer.cpp \
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
deleted file mode 100644
index 6da1fa8..0000000
--- a/libs/hwui/FrameInfo.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#include "FrameInfo.h"
-
-#include <cstring>
-
-namespace android {
-namespace uirenderer {
-
-void FrameInfo::importUiThreadInfo(int64_t* info) {
-    memcpy(mFrameInfo, info, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
deleted file mode 100644
index 3c31677..0000000
--- a/libs/hwui/FrameInfo.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef FRAMEINFO_H_
-#define FRAMEINFO_H_
-
-#include "utils/Macros.h"
-
-#include <cutils/compiler.h>
-#include <utils/Timers.h>
-
-#include <memory.h>
-
-namespace android {
-namespace uirenderer {
-
-#define UI_THREAD_FRAME_INFO_SIZE 9
-
-HWUI_ENUM(FrameInfoIndex,
-    kFlags = 0,
-    kIntendedVsync,
-    kVsync,
-    kOldestInputEvent,
-    kNewestInputEvent,
-    kHandleInputStart,
-    kAnimationStart,
-    kPerformTraversalsStart,
-    kDrawStart,
-    // End of UI frame info
-
-    kSyncStart,
-    kIssueDrawCommandsStart,
-    kSwapBuffers,
-    kFrameCompleted,
-
-    // Must be the last value!
-    kNumIndexes
-);
-
-HWUI_ENUM(FrameInfoFlags,
-    kWindowLayoutChanged = 1 << 0,
-    kRTAnimation = 1 << 1,
-    kSurfaceCanvas = 1 << 2,
-);
-
-class ANDROID_API UiFrameInfoBuilder {
-public:
-    UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
-        memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
-    }
-
-    UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
-        mBuffer[FrameInfoIndex::kVsync] = vsyncTime;
-        mBuffer[FrameInfoIndex::kIntendedVsync] = intendedVsync;
-        return *this;
-    }
-
-    UiFrameInfoBuilder& addFlag(FrameInfoFlagsEnum flag) {
-        mBuffer[FrameInfoIndex::kFlags] |= static_cast<uint64_t>(flag);
-        return *this;
-    }
-
-private:
-    int64_t* mBuffer;
-};
-
-class FrameInfo {
-public:
-    void importUiThreadInfo(int64_t* info);
-
-    void markSyncStart() {
-        mFrameInfo[FrameInfoIndex::kSyncStart] = systemTime(CLOCK_MONOTONIC);
-    }
-
-    void markIssueDrawCommandsStart() {
-        mFrameInfo[FrameInfoIndex::kIssueDrawCommandsStart] = systemTime(CLOCK_MONOTONIC);
-    }
-
-    void markSwapBuffers() {
-        mFrameInfo[FrameInfoIndex::kSwapBuffers] = systemTime(CLOCK_MONOTONIC);
-    }
-
-    void markFrameCompleted() {
-        mFrameInfo[FrameInfoIndex::kFrameCompleted] = systemTime(CLOCK_MONOTONIC);
-    }
-
-    int64_t operator[](FrameInfoIndexEnum index) const {
-        if (index == FrameInfoIndex::kNumIndexes) return 0;
-        return mFrameInfo[static_cast<int>(index)];
-    }
-
-    int64_t operator[](int index) const {
-        if (index < 0 || index >= FrameInfoIndex::kNumIndexes) return 0;
-        return mFrameInfo[static_cast<int>(index)];
-    }
-
-private:
-    int64_t mFrameInfo[FrameInfoIndex::kNumIndexes];
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* FRAMEINFO_H_ */
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
deleted file mode 100644
index f7c8195..0000000
--- a/libs/hwui/JankTracker.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#include "JankTracker.h"
-
-#include <algorithm>
-#include <cstdio>
-#include <inttypes.h>
-
-namespace android {
-namespace uirenderer {
-
-static const char* JANK_TYPE_NAMES[] = {
-        "Missed Vsync",
-        "High input latency",
-        "Slow UI thread",
-        "Slow bitmap uploads",
-        "Slow draw",
-};
-
-struct Comparison {
-    FrameInfoIndexEnum start;
-    FrameInfoIndexEnum end;
-};
-
-static const Comparison COMPARISONS[] = {
-        {FrameInfoIndex::kIntendedVsync, FrameInfoIndex::kVsync},
-        {FrameInfoIndex::kOldestInputEvent, FrameInfoIndex::kVsync},
-        {FrameInfoIndex::kVsync, FrameInfoIndex::kSyncStart},
-        {FrameInfoIndex::kSyncStart, FrameInfoIndex::kIssueDrawCommandsStart},
-        {FrameInfoIndex::kIssueDrawCommandsStart, FrameInfoIndex::kFrameCompleted},
-};
-
-// If the event exceeds 10 seconds throw it away, this isn't a jank event
-// it's an ANR and will be handled as such
-static const int64_t IGNORE_EXCEEDING = seconds_to_nanoseconds(10);
-
-/*
- * Frames that are exempt from jank metrics.
- * First-draw frames, for example, are expected to
- * be slow, this is hidden from the user with window animations and
- * other tricks
- *
- * Similarly, we don't track direct-drawing via Surface:lockHardwareCanvas()
- * for now
- *
- * TODO: kSurfaceCanvas can negatively impact other drawing by using up
- * time on the RenderThread, figure out how to attribute that as a jank-causer
- */
-static const int64_t EXEMPT_FRAMES_FLAGS
-        = FrameInfoFlags::kWindowLayoutChanged
-        | FrameInfoFlags::kSurfaceCanvas;
-
-JankTracker::JankTracker(nsecs_t frameIntervalNanos) {
-    reset();
-    setFrameInterval(frameIntervalNanos);
-}
-
-void JankTracker::setFrameInterval(nsecs_t frameInterval) {
-    mFrameInterval = frameInterval;
-    mThresholds[kMissedVsync] = 1;
-    /*
-     * Due to interpolation and sample rate differences between the touch
-     * panel and the display (example, 85hz touch panel driving a 60hz display)
-     * we call high latency 1.5 * frameinterval
-     *
-     * NOTE: Be careful when tuning this! A theoretical 1,000hz touch panel
-     * on a 60hz display will show kOldestInputEvent - kIntendedVsync of being 15ms
-     * Thus this must always be larger than frameInterval, or it will fail
-     */
-    mThresholds[kHighInputLatency] = static_cast<int64_t>(1.5 * frameInterval);
-
-    // Note that these do not add up to 1. This is intentional. It's to deal
-    // with variance in values, and should be sort of an upper-bound on what
-    // is reasonable to expect.
-    mThresholds[kSlowUI] = static_cast<int64_t>(.5 * frameInterval);
-    mThresholds[kSlowSync] = static_cast<int64_t>(.2 * frameInterval);
-    mThresholds[kSlowRT] = static_cast<int64_t>(.75 * frameInterval);
-
-}
-
-void JankTracker::addFrame(const FrameInfo& frame) {
-    using namespace FrameInfoIndex;
-    mTotalFrameCount++;
-    // Fast-path for jank-free frames
-    int64_t totalDuration = frame[kFrameCompleted] - frame[kIntendedVsync];
-    uint32_t framebucket = std::min(
-            static_cast<typeof sizeof(mFrameCounts)>(ns2ms(totalDuration)),
-            sizeof(mFrameCounts) / sizeof(mFrameCounts[0]));
-    // Keep the fast path as fast as possible.
-    if (CC_LIKELY(totalDuration < mFrameInterval)) {
-        mFrameCounts[framebucket]++;
-        return;
-    }
-
-    if (frame[kFlags] & EXEMPT_FRAMES_FLAGS) {
-        return;
-    }
-
-    mFrameCounts[framebucket]++;
-    mJankFrameCount++;
-
-    for (int i = 0; i < NUM_BUCKETS; i++) {
-        int64_t delta = frame[COMPARISONS[i].end] - frame[COMPARISONS[i].start];
-        if (delta >= mThresholds[i] && delta < IGNORE_EXCEEDING) {
-            mBuckets[i].count++;
-        }
-    }
-}
-
-void JankTracker::dump(int fd) {
-    FILE* file = fdopen(fd, "a");
-    fprintf(file, "\nFrame stats:");
-    fprintf(file, "\n  Total frames rendered: %u", mTotalFrameCount);
-    fprintf(file, "\n  Janky frames: %u (%.2f%%)", mJankFrameCount,
-            (float) mJankFrameCount / (float) mTotalFrameCount * 100.0f);
-    fprintf(file, "\n  90th percentile: %ums", findPercentile(90));
-    fprintf(file, "\n  95th percentile: %ums", findPercentile(95));
-    fprintf(file, "\n  99th percentile: %ums", findPercentile(99));
-    for (int i = 0; i < NUM_BUCKETS; i++) {
-        fprintf(file, "\n   Number %s: %u", JANK_TYPE_NAMES[i], mBuckets[i].count);
-    }
-    fprintf(file, "\n");
-    fflush(file);
-}
-
-void JankTracker::reset() {
-    memset(mBuckets, 0, sizeof(mBuckets));
-    memset(mFrameCounts, 0, sizeof(mFrameCounts));
-    mTotalFrameCount = 0;
-    mJankFrameCount = 0;
-}
-
-uint32_t JankTracker::findPercentile(int percentile) {
-    int pos = percentile * mTotalFrameCount / 100;
-    int remaining = mTotalFrameCount - pos;
-    for (int i = sizeof(mFrameCounts) / sizeof(mFrameCounts[0]) - 1; i >= 0; i--) {
-        remaining -= mFrameCounts[i];
-        if (remaining <= 0) {
-            return i;
-        }
-    }
-    return 0;
-}
-
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/JankTracker.h b/libs/hwui/JankTracker.h
deleted file mode 100644
index 3d4929b..0000000
--- a/libs/hwui/JankTracker.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef JANKTRACKER_H_
-#define JANKTRACKER_H_
-
-#include "FrameInfo.h"
-#include "renderthread/TimeLord.h"
-#include "utils/RingBuffer.h"
-
-#include <memory>
-
-namespace android {
-namespace uirenderer {
-
-enum JankType {
-    kMissedVsync = 0,
-    kHighInputLatency,
-    kSlowUI,
-    kSlowSync,
-    kSlowRT,
-
-    // must be last
-    NUM_BUCKETS,
-};
-
-struct JankBucket {
-    // Number of frames that hit this bucket
-    uint32_t count;
-};
-
-// TODO: Replace DrawProfiler with this
-class JankTracker {
-public:
-    JankTracker(nsecs_t frameIntervalNanos);
-
-    void setFrameInterval(nsecs_t frameIntervalNanos);
-
-    void addFrame(const FrameInfo& frame);
-
-    void dump(int fd);
-    void reset();
-
-private:
-    uint32_t findPercentile(int p);
-
-    JankBucket mBuckets[NUM_BUCKETS];
-    int64_t mThresholds[NUM_BUCKETS];
-    uint32_t mFrameCounts[128];
-
-    int64_t mFrameInterval;
-    uint32_t mTotalFrameCount;
-    uint32_t mJankFrameCount;
-};
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* JANKTRACKER_H_ */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2eaa771..75bd067 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -47,8 +47,7 @@
         , mOpaque(!translucent)
         , mCanvas(NULL)
         , mHaveNewSurface(false)
-        , mRootRenderNode(rootRenderNode)
-        , mCurrentFrameInfo(NULL) {
+        , mRootRenderNode(rootRenderNode) {
     mAnimationContext = contextFactory->createAnimationContext(mRenderThread.timeLord());
     mRenderThread.renderState().registerCanvasContext(this);
 }
@@ -153,13 +152,9 @@
     }
 }
 
-void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) {
+void CanvasContext::prepareTree(TreeInfo& info) {
     mRenderThread.removeFrameCallback(this);
 
-    mCurrentFrameInfo = &mFrames.next();
-    mCurrentFrameInfo->importUiThreadInfo(uiFrameInfo);
-    mCurrentFrameInfo->markSyncStart();
-
     info.damageAccumulator = &mDamageAccumulator;
     info.renderer = mCanvas;
     if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
@@ -209,7 +204,6 @@
             "drawRenderNode called on a context with no canvas or surface!");
 
     profiler().markPlaybackStart();
-    mCurrentFrameInfo->markIssueDrawCommandsStart();
 
     SkRect dirty;
     mDamageAccumulator.finish(&dirty);
@@ -247,19 +241,12 @@
 
     profiler().markPlaybackEnd();
 
-    // Even if we decided to cancel the frame, from the perspective of jank
-    // metrics the frame was swapped at this point
-    mCurrentFrameInfo->markSwapBuffers();
-
     if (status & DrawGlInfo::kStatusDrew) {
         swapBuffers();
     } else {
         mEglManager.cancelFrame();
     }
 
-    // TODO: Use a fence for real completion?
-    mCurrentFrameInfo->markFrameCompleted();
-    mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo);
     profiler().finishFrame();
 }
 
@@ -272,14 +259,9 @@
     ATRACE_CALL();
 
     profiler().startFrame();
-    int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
-    UiFrameInfoBuilder(frameInfo)
-        .addFlag(FrameInfoFlags::kRTAnimation)
-        .setVsync(mRenderThread.timeLord().computeFrameTimeNanos(),
-                mRenderThread.timeLord().latestVsync());
 
     TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
-    prepareTree(info, frameInfo);
+    prepareTree(info);
     if (info.out.canDrawThisFrame) {
         draw();
     }
@@ -392,28 +374,6 @@
     thread.eglManager().setTextureAtlas(buffer, map, mapSize);
 }
 
-void CanvasContext::dumpFrames(int fd) {
-    FILE* file = fdopen(fd, "a");
-    fprintf(file, "\n\n---PROFILEDATA---");
-    for (size_t i = 0; i < mFrames.size(); i++) {
-        FrameInfo& frame = mFrames[i];
-        if (frame[FrameInfoIndex::kSyncStart] == 0) {
-            continue;
-        }
-        fprintf(file, "\n");
-        for (int i = 0; i < FrameInfoIndex::kNumIndexes; i++) {
-            fprintf(file, "%" PRId64 ",", frame[i]);
-        }
-    }
-    fprintf(file, "\n---PROFILEDATA---\n\n");
-    fflush(file);
-}
-
-void CanvasContext::resetFrameStats() {
-    mFrames.clear();
-    mRenderThread.jankTracker().reset();
-}
-
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0e8be9d..0cc2c7c 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -17,14 +17,7 @@
 #ifndef CANVASCONTEXT_H_
 #define CANVASCONTEXT_H_
 
-#include "DamageAccumulator.h"
-#include "DrawProfiler.h"
-#include "IContextFactory.h"
-#include "FrameInfo.h"
-#include "RenderNode.h"
-#include "utils/RingBuffer.h"
-#include "renderthread/RenderTask.h"
-#include "renderthread/RenderThread.h"
+#include <set>
 
 #include <cutils/compiler.h>
 #include <EGL/egl.h>
@@ -32,7 +25,14 @@
 #include <utils/Functor.h>
 #include <utils/Vector.h>
 
-#include <set>
+#include "../DamageAccumulator.h"
+#include "../DrawProfiler.h"
+#include "../IContextFactory.h"
+#include "../RenderNode.h"
+#include "RenderTask.h"
+#include "RenderThread.h"
+
+#define FUNCTOR_PROCESS_DELAY 4
 
 namespace android {
 namespace uirenderer {
@@ -75,7 +75,7 @@
     void setOpaque(bool opaque);
     void makeCurrent();
     void processLayerUpdate(DeferredLayerUpdater* layerUpdater);
-    void prepareTree(TreeInfo& info, int64_t* uiFrameInfo);
+    void prepareTree(TreeInfo& info);
     void draw();
     void destroy();
 
@@ -103,9 +103,6 @@
 
     DrawProfiler& profiler() { return mProfiler; }
 
-    void dumpFrames(int fd);
-    void resetFrameStats();
-
 private:
     friend class RegisterFrameCallbackTask;
     // TODO: Replace with something better for layer & other GL object
@@ -136,9 +133,6 @@
     const sp<RenderNode> mRootRenderNode;
 
     DrawProfiler mProfiler;
-    FrameInfo* mCurrentFrameInfo;
-    // Ring buffer large enough for 1 second worth of frames
-    RingBuffer<FrameInfo, 60> mFrames;
 
     std::set<RenderNode*> mPrefetechedLayers;
 };
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 23a0202..97b31a9 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -34,6 +34,8 @@
 DrawFrameTask::DrawFrameTask()
         : mRenderThread(NULL)
         , mContext(NULL)
+        , mFrameTimeNanos(0)
+        , mRecordDurationNanos(0)
         , mDensity(1.0f) // safe enough default
         , mSyncResult(kSync_OK) {
 }
@@ -66,12 +68,18 @@
     }
 }
 
-int DrawFrameTask::drawFrame() {
+int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) {
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
     mSyncResult = kSync_OK;
+    mFrameTimeNanos = frameTimeNanos;
+    mRecordDurationNanos = recordDurationNanos;
     postAndWait();
 
+    // Reset the single-frame data
+    mFrameTimeNanos = 0;
+    mRecordDurationNanos = 0;
+
     return mSyncResult;
 }
 
@@ -85,7 +93,7 @@
     ATRACE_NAME("DrawFrame");
 
     mContext->profiler().setDensity(mDensity);
-    mContext->profiler().startFrame();
+    mContext->profiler().startFrame(mRecordDurationNanos);
 
     bool canUnblockUiThread;
     bool canDrawThisFrame;
@@ -114,7 +122,7 @@
 
 bool DrawFrameTask::syncFrameState(TreeInfo& info) {
     ATRACE_CALL();
-    mRenderThread->timeLord().vsyncReceived(mFrameInfo[FrameInfoIndex::kVsync]);
+    mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
     mContext->makeCurrent();
     Caches::getInstance().textureCache.resetMarkInUse();
 
@@ -122,7 +130,7 @@
         mContext->processLayerUpdate(mLayers[i].get());
     }
     mLayers.clear();
-    mContext->prepareTree(info, mFrameInfo);
+    mContext->prepareTree(info);
 
     // This is after the prepareTree so that any pending operations
     // (RenderNode tree state, prefetched layers, etc...) will be flushed.
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index eccb87f..28f6cb2 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -25,7 +25,6 @@
 #include "RenderTask.h"
 
 #include "../Rect.h"
-#include "../FrameInfo.h"
 #include "../TreeInfo.h"
 
 namespace android {
@@ -63,9 +62,7 @@
     void removeLayerUpdate(DeferredLayerUpdater* layer);
 
     void setDensity(float density) { mDensity = density; }
-    int drawFrame();
-
-    int64_t* frameInfo() { return mFrameInfo; }
+    int drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos);
 
     virtual void run();
 
@@ -83,12 +80,12 @@
     /*********************************************
      *  Single frame data
      *********************************************/
+    nsecs_t mFrameTimeNanos;
+    nsecs_t mRecordDurationNanos;
     float mDensity;
     std::vector< sp<DeferredLayerUpdater> > mLayers;
 
     int mSyncResult;
-
-    int64_t mFrameInfo[UI_THREAD_FRAME_INFO_SIZE];
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 088c65b..6d063a4 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,14 +16,14 @@
 
 #include "RenderProxy.h"
 
-#include "DeferredLayerUpdater.h"
-#include "DisplayList.h"
-#include "LayerRenderer.h"
-#include "Rect.h"
-#include "renderthread/CanvasContext.h"
-#include "renderthread/RenderTask.h"
-#include "renderthread/RenderThread.h"
-#include "utils/Macros.h"
+#include "CanvasContext.h"
+#include "RenderTask.h"
+#include "RenderThread.h"
+
+#include "../DeferredLayerUpdater.h"
+#include "../DisplayList.h"
+#include "../LayerRenderer.h"
+#include "../Rect.h"
 
 namespace android {
 namespace uirenderer {
@@ -52,11 +52,6 @@
     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
     ARGS(method) *args = (ARGS(method) *) task->payload()
 
-HWUI_ENUM(DumpFlags,
-        kFrameStats = 1 << 0,
-        kReset      = 1 << 1,
-);
-
 CREATE_BRIDGE4(createContext, RenderThread* thread, bool translucent,
         RenderNode* rootRenderNode, IContextFactory* contextFactory) {
     return new CanvasContext(*args->thread, args->translucent,
@@ -97,7 +92,7 @@
 }
 
 CREATE_BRIDGE2(setFrameInterval, RenderThread* thread, nsecs_t frameIntervalNanos) {
-    args->thread->setFrameInterval(args->frameIntervalNanos);
+    args->thread->timeLord().setFrameInterval(args->frameIntervalNanos);
     return NULL;
 }
 
@@ -180,8 +175,7 @@
 }
 
 void RenderProxy::setup(int width, int height, const Vector3& lightCenter, float lightRadius,
-        uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density) {
-    mDrawFrameTask.setDensity(density);
+        uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
     SETUP_TASK(setup);
     args->context = mContext;
     args->width = width;
@@ -205,12 +199,10 @@
     post(task);
 }
 
-int64_t* RenderProxy::frameInfo() {
-    return mDrawFrameTask.frameInfo();
-}
-
-int RenderProxy::syncAndDrawFrame() {
-    return mDrawFrameTask.drawFrame();
+int RenderProxy::syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
+        float density) {
+    mDrawFrameTask.setDensity(density);
+    return mDrawFrameTask.drawFrame(frameTimeNanos, recordDurationNanos);
 }
 
 CREATE_BRIDGE1(destroy, CanvasContext* context) {
@@ -379,28 +371,19 @@
     mRenderThread.queueAtFront(task);
 }
 
-CREATE_BRIDGE3(dumpProfileInfo, CanvasContext* context, int fd, int dumpFlags) {
+CREATE_BRIDGE2(dumpProfileInfo, CanvasContext* context, int fd) {
     args->context->profiler().dumpData(args->fd);
-
-    if (args->dumpFlags & DumpFlags::kFrameStats) {
-        args->context->dumpFrames(args->fd);
-    }
-    if (args->dumpFlags & DumpFlags::kReset) {
-        args->context->resetFrameStats();
-    }
     return NULL;
 }
 
-void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
+void RenderProxy::dumpProfileInfo(int fd) {
     SETUP_TASK(dumpProfileInfo);
     args->context = mContext;
     args->fd = fd;
-    args->dumpFlags = dumpFlags;
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(outputLogBuffer, int fd, RenderThread* thread) {
-    args->thread->jankTracker().dump(args->fd);
+CREATE_BRIDGE1(outputLogBuffer, int fd) {
     RenderNode::outputLogBuffer(args->fd);
     return NULL;
 }
@@ -408,7 +391,6 @@
 void RenderProxy::outputLogBuffer(int fd) {
     SETUP_TASK(outputLogBuffer);
     args->fd = fd;
-    args->thread = &RenderThread::getInstance();
     staticPostAndWait(task);
 }
 
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index d86f1fc..fd1fe05 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,10 +71,10 @@
     ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
     ANDROID_API bool pauseSurface(const sp<ANativeWindow>& window);
     ANDROID_API void setup(int width, int height, const Vector3& lightCenter, float lightRadius,
-            uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha, float density);
+            uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
     ANDROID_API void setOpaque(bool opaque);
-    ANDROID_API int64_t* frameInfo();
-    ANDROID_API int syncAndDrawFrame();
+    ANDROID_API int syncAndDrawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos,
+            float density);
     ANDROID_API void destroy();
 
     ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
@@ -95,7 +95,7 @@
     ANDROID_API void stopDrawing();
     ANDROID_API void notifyFramePending();
 
-    ANDROID_API void dumpProfileInfo(int fd, int dumpFlags);
+    ANDROID_API void dumpProfileInfo(int fd);
     ANDROID_API static void outputLogBuffer(int fd);
 
     ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 7a8c3ce..84826b7 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -143,8 +143,7 @@
         , mFrameCallbackTaskPending(false)
         , mFrameCallbackTask(0)
         , mRenderState(NULL)
-        , mEglManager(NULL)
-        , mJankTracker(NULL) {
+        , mEglManager(NULL) {
     mFrameCallbackTask = new DispatchFrameCallbacks(this);
     mLooper = new Looper(false);
     run("RenderThread");
@@ -154,11 +153,6 @@
     LOG_ALWAYS_FATAL("Can't destroy the render thread");
 }
 
-void RenderThread::setFrameInterval(nsecs_t frameInterval) {
-    mTimeLord.setFrameInterval(frameInterval);
-    mJankTracker->setFrameInterval(frameInterval);
-}
-
 void RenderThread::initializeDisplayEventReceiver() {
     LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
     mDisplayEventReceiver = new DisplayEventReceiver();
@@ -175,7 +169,6 @@
     initializeDisplayEventReceiver();
     mEglManager = new EglManager(*this);
     mRenderState = new RenderState(*this);
-    mJankTracker = new JankTracker(mTimeLord.frameIntervalNanos());
 }
 
 int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 8a28a35..99c2e15 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -19,8 +19,8 @@
 
 #include "RenderTask.h"
 
-#include "../JankTracker.h"
-#include "TimeLord.h"
+#include <memory>
+#include <set>
 
 #include <cutils/compiler.h>
 #include <utils/Looper.h>
@@ -28,8 +28,7 @@
 #include <utils/Singleton.h>
 #include <utils/Thread.h>
 
-#include <memory>
-#include <set>
+#include "TimeLord.h"
 
 namespace android {
 
@@ -86,12 +85,9 @@
     // the next vsync. If it is not currently registered this does nothing.
     void pushBackFrameCallback(IFrameCallback* callback);
 
-    void setFrameInterval(nsecs_t frameInterval);
-
     TimeLord& timeLord() { return mTimeLord; }
     RenderState& renderState() { return *mRenderState; }
     EglManager& eglManager() { return *mEglManager; }
-    JankTracker& jankTracker() { return *mJankTracker; }
 
 protected:
     virtual bool threadLoop();
@@ -136,8 +132,6 @@
     TimeLord mTimeLord;
     RenderState* mRenderState;
     EglManager* mEglManager;
-
-    JankTracker* mJankTracker;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index f846d6a..f187493 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -32,7 +32,7 @@
     return false;
 }
 
-nsecs_t TimeLord::computeFrameTimeNanos() {
+nsecs_t TimeLord::computeFrameTimeMs() {
     // Logic copied from Choreographer.java
     nsecs_t now = systemTime(CLOCK_MONOTONIC);
     nsecs_t jitterNanos = now - mFrameTimeNanos;
@@ -40,11 +40,7 @@
         nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
         mFrameTimeNanos = now - lastFrameOffset;
     }
-    return mFrameTimeNanos;
-}
-
-nsecs_t TimeLord::computeFrameTimeMs() {
-    return nanoseconds_to_milliseconds(computeFrameTimeNanos());
+    return nanoseconds_to_milliseconds(mFrameTimeNanos);
 }
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 5464399..7c155d2 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -29,13 +29,9 @@
 class TimeLord {
 public:
     void setFrameInterval(nsecs_t intervalNanos) { mFrameIntervalNanos = intervalNanos; }
-    nsecs_t frameIntervalNanos() const { return mFrameIntervalNanos; }
-
     // returns true if the vsync is newer, false if it was rejected for staleness
     bool vsyncReceived(nsecs_t vsync);
-    nsecs_t latestVsync() { return mFrameTimeNanos; }
     nsecs_t computeFrameTimeMs();
-    nsecs_t computeFrameTimeNanos();
 
 private:
     friend class RenderThread;
diff --git a/libs/hwui/tests/main.cpp b/libs/hwui/tests/main.cpp
index 33b8103..2d99e9f 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -88,7 +88,7 @@
     proxy->initialize(surface);
     float lightX = width / 2.0;
     proxy->setup(width, height, (Vector3){lightX, dp(-200.0f), dp(800.0f)},
-            dp(800.0f), 255 * 0.075, 255 * 0.15, gDisplay.density);
+            dp(800.0f), 255 * 0.075, 255 * 0.15);
 
     android::uirenderer::Rect DUMMY;
 
@@ -116,7 +116,8 @@
             cards[ci]->mutateStagingProperties().setTranslationY(i);
             cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
         }
-        proxy->syncAndDrawFrame();
+        nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
+        proxy->syncAndDrawFrame(frameTimeNs, 0, gDisplay.density);
         usleep(12000);
     }
 
diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h
index 068b32b..5b7c87c 100644
--- a/libs/hwui/utils/Macros.h
+++ b/libs/hwui/utils/Macros.h
@@ -29,12 +29,4 @@
         friend inline int compare_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs); } \
         friend inline hash_t hash_type(const Type& entry) { return entry.hash(); }
 
-#define HWUI_ENUM(name, ...) \
-    namespace name { \
-        enum _##name { \
-            __VA_ARGS__ \
-        }; \
-    } \
-    typedef enum name::_##name name##Enum
-
 #endif /* MACROS_H */
diff --git a/libs/hwui/utils/RingBuffer.h b/libs/hwui/utils/RingBuffer.h
deleted file mode 100644
index 62b22fd..0000000
--- a/libs/hwui/utils/RingBuffer.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2015 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.
- */
-#ifndef RINGBUFFER_H_
-#define RINGBUFFER_H_
-
-#include "utils/Macros.h"
-
-#include <stddef.h>
-
-namespace android {
-namespace uirenderer {
-
-template<class T, size_t SIZE>
-class RingBuffer {
-    PREVENT_COPY_AND_ASSIGN(RingBuffer);
-
-public:
-    RingBuffer() : mHead(-1), mCount(0) {}
-    ~RingBuffer() {}
-
-    size_t capacity() { return SIZE; }
-    size_t size() { return mCount; }
-
-    T& next() {
-        mHead = (mHead + 1) % SIZE;
-        if (mCount < SIZE) {
-            mCount++;
-        }
-        return mBuffer[mHead];
-    }
-
-    T& front() {
-        return this[0];
-    }
-
-    T& back() {
-        return this[size() - 1];
-    }
-
-    T& operator[](size_t index) {
-        return mBuffer[(mHead + index + 1) % mCount];
-    }
-
-    void clear() {
-        mCount = 0;
-        mHead = -1;
-    }
-
-private:
-    T mBuffer[SIZE];
-    int mHead;
-    size_t mCount;
-};
-
-}; // namespace uirenderer
-}; // namespace android
-
-#endif /* RINGBUFFER_H_ */