summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Reck <jreck@google.com>2015-05-13 21:42:28 +0000
committerThe Android Automerger <android-build@google.com>2015-05-28 10:27:17 -0700
commit0e40462e11d27eb859b829b112cecb8c6f0d7afb (patch)
treef46cb14c8476bb83200680cb6580f7188ace6c1d
parentd5a4a1aac980c304d6f46f07f15bfc5c94d8f9d0 (diff)
downloadbase-0e40462e11d27eb859b829b112cecb8c6f0d7afb.tar.gz
Revert "DO NOT MERGE Backport of limited jank-tracking metrics"android-cts-5.1_r2android-5.1.1_r6
This reverts commit 2614bd225f84f7a23e6b30fc6b47bede153e5f4c. Change-Id: I344b4cbaa0bb0caf50bceb806d1446ee27ea52d8
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/view/Choreographer.java20
-rw-r--r--core/java/android/view/FrameInfo.java118
-rw-r--r--core/java/android/view/HardwareRenderer.java2
-rw-r--r--core/java/android/view/ThreadedRenderer.java77
-rw-r--r--core/java/android/view/ViewRootImpl.java16
-rw-r--r--core/java/android/view/WindowManagerGlobal.java4
-rw-r--r--core/jni/android_view_Surface.cpp10
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp22
-rw-r--r--libs/hwui/Android.mk2
-rw-r--r--libs/hwui/FrameInfo.cpp28
-rw-r--r--libs/hwui/FrameInfo.h116
-rw-r--r--libs/hwui/JankTracker.cpp159
-rw-r--r--libs/hwui/JankTracker.h71
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp46
-rw-r--r--libs/hwui/renderthread/CanvasContext.h26
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp16
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h9
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp52
-rw-r--r--libs/hwui/renderthread/RenderProxy.h8
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp9
-rw-r--r--libs/hwui/renderthread/RenderThread.h12
-rw-r--r--libs/hwui/renderthread/TimeLord.cpp8
-rw-r--r--libs/hwui/renderthread/TimeLord.h4
-rw-r--r--libs/hwui/tests/main.cpp5
-rw-r--r--libs/hwui/utils/Macros.h8
-rw-r--r--libs/hwui/utils/RingBuffer.h71
27 files changed, 116 insertions, 805 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4a8714c55a91..8353d5472b8e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1083,7 +1083,7 @@ public final class ActivityThread {
@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 c8149d9346f8..f41afcff0304 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -141,19 +141,6 @@ public final class Choreographer {
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 @@ public final class Choreographer {
return; // no work to do
}
- long intendedFrameTimeNanos = frameTimeNanos;
startNanos = System.nanoTime();
final long jitterNanos = startNanos - frameTimeNanos;
if (jitterNanos >= mFrameIntervalNanos) {
@@ -555,18 +541,12 @@ public final class Choreographer {
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 c79547c8313e..000000000000
--- 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 aa6188543fc1..c5c3f830fe3e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -278,7 +278,7 @@ public abstract class HardwareRenderer {
/**
* 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 df0838f6a643..ad4a048808c3 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.graphics.drawable.Drawable;
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
(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 @@ public class ThreadedRenderer extends HardwareRenderer {
mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight,
lightX, mLightY, mLightZ, mLightRadius,
- mAmbientShadowAlpha, mSpotShadowAlpha, mDensity);
+ mAmbientShadowAlpha, mSpotShadowAlpha);
}
@Override
@@ -243,25 +233,32 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@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 @@ public class ThreadedRenderer extends HardwareRenderer {
@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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 @@ public class ThreadedRenderer extends HardwareRenderer {
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 356614014f1d..e4d82b16d185 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -56,7 +56,6 @@ import android.util.AndroidRuntimeException;
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 @@ public final class ViewRootImpl implements ViewParent,
// 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 @@ public final class ViewRootImpl implements ViewParent,
}
}
- 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 @@ public final class ViewRootImpl implements ViewParent,
dirty.setEmpty();
mIsAnimating = false;
+ attachInfo.mDrawingTime = SystemClock.uptimeMillis();
mView.mPrivateFlags |= View.PFLAG_DRAWN;
if (DEBUG_DRAW) {
@@ -5782,16 +5778,6 @@ public final class ViewRootImpl implements ViewParent,
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 643340ab0b00..a14c7661fb45 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -459,7 +459,7 @@ public final class WindowManagerGlobal {
}
}
- 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 @@ public final class WindowManagerGlobal {
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 8590acaf2436..a39ff8eb6511 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 @@ static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfaceP
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 setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfa
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 00d7fc833170..b9d849c72ebb 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -283,10 +283,10 @@ static jboolean android_view_ThreadedRenderer_pauseSurface(JNIEnv* env, jobject
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 void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
}
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_notifyFramePending(JNIEnv* env, jobjec
}
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 @@ static JNINativeMethod gMethods[] = {
{ "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 @@ static JNINativeMethod gMethods[] = {
{ "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 507472aa61a8..49560ffdd628 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -18,7 +18,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
AssetAtlas.cpp \
DamageAccumulator.cpp \
FontRenderer.cpp \
- FrameInfo.cpp \
GammaFontRenderer.cpp \
Caches.cpp \
DisplayList.cpp \
@@ -33,7 +32,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
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 6da1fa808d0a..000000000000
--- 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 3c3167721d2b..000000000000
--- 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 f7c81953b67b..000000000000
--- 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 3d4929b215c6..000000000000
--- 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 2eaa7719227c..75bd0676d70a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -47,8 +47,7 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent,
, 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::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
}
}
-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 @@ void CanvasContext::draw() {
"drawRenderNode called on a context with no canvas or surface!");
profiler().markPlaybackStart();
- mCurrentFrameInfo->markIssueDrawCommandsStart();
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -247,19 +241,12 @@ void CanvasContext::draw() {
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 @@ void CanvasContext::doFrame() {
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 @@ void CanvasContext::setTextureAtlas(RenderThread& thread,
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 0e8be9d9ed59..0cc2c7c2811a 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 @@ public:
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 @@ public:
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 @@ private:
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 23a020233f27..97b31a95f278 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -34,6 +34,8 @@ namespace renderthread {
DrawFrameTask::DrawFrameTask()
: mRenderThread(NULL)
, mContext(NULL)
+ , mFrameTimeNanos(0)
+ , mRecordDurationNanos(0)
, mDensity(1.0f) // safe enough default
, mSyncResult(kSync_OK) {
}
@@ -66,12 +68,18 @@ void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) {
}
}
-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 @@ void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
mContext->profiler().setDensity(mDensity);
- mContext->profiler().startFrame();
+ mContext->profiler().startFrame(mRecordDurationNanos);
bool canUnblockUiThread;
bool canDrawThisFrame;
@@ -114,7 +122,7 @@ void DrawFrameTask::run() {
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 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
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 eccb87f29383..28f6cb26fb57 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 @@ public:
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 @@ private:
/*********************************************
* 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 088c65b939ef..6d063a4b0ce0 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 @@ namespace renderthread {
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 @@ void RenderProxy::destroyContext() {
}
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 @@ CREATE_BRIDGE7(setup, CanvasContext* context, int width, int height,
}
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 @@ void RenderProxy::setOpaque(bool opaque) {
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 @@ void RenderProxy::notifyFramePending() {
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 @@ CREATE_BRIDGE2(outputLogBuffer, int fd, RenderThread* thread) {
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 d86f1fca466f..fd1fe05ffbdb 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -71,10 +71,10 @@ public:
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 @@ public:
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 7a8c3cee088d..84826b7a3bff 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -143,8 +143,7 @@ RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
, 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 @@ RenderThread::~RenderThread() {
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 @@ void RenderThread::initThreadLocals() {
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 8a28a35aabc2..99c2e1527ea2 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 @@ public:
// 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 @@ private:
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 f846d6a44473..f18749317ab6 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -32,7 +32,7 @@ bool TimeLord::vsyncReceived(nsecs_t vsync) {
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 TimeLord::computeFrameTimeNanos() {
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 5464399234fb..7c155d28feef 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -29,13 +29,9 @@ class RenderThread;
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 33b8103cdb84..2d99e9f7686c 100644
--- a/libs/hwui/tests/main.cpp
+++ b/libs/hwui/tests/main.cpp
@@ -88,7 +88,7 @@ int main(int argc, char* argv[]) {
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 @@ int main(int argc, char* argv[]) {
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 068b32b3fe68..5b7c87ceef8f 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 62b22fdcef42..000000000000
--- 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_ */