diff options
27 files changed, 116 insertions, 805 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index f2b89e1..850bc1f 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1082,7 +1082,7 @@ public final class ActivityThread { @Override public void dumpGfxInfo(FileDescriptor fd, String[] args) { dumpGraphicsInfo(fd); - WindowManagerGlobal.getInstance().dumpGfxInfo(fd, args); + WindowManagerGlobal.getInstance().dumpGfxInfo(fd); } private void dumpDatabaseInfo(FileDescriptor fd, String[] args) { 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 @@ 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 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 @@ 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 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.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 397cbb8..113ad8d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -55,7 +55,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; @@ -1516,7 +1515,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); @@ -2520,9 +2518,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. @@ -2642,6 +2637,7 @@ public final class ViewRootImpl implements ViewParent, dirty.setEmpty(); mIsAnimating = false; + attachInfo.mDrawingTime = SystemClock.uptimeMillis(); mView.mPrivateFlags |= View.PFLAG_DRAWN; if (DEBUG_DRAW) { @@ -5790,16 +5786,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 643340a..a14c766 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 bfa0534..7f6c50f 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 7224f17..9b06293 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 4d38d9f..d0b9d82 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -25,7 +25,6 @@ ifeq ($(USE_OPENGL_RENDERER),true) AssetAtlas.cpp \ DamageAccumulator.cpp \ FontRenderer.cpp \ - FrameInfo.cpp \ GammaFontRenderer.cpp \ Caches.cpp \ DisplayList.cpp \ @@ -40,7 +39,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 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 4e7e73e..b7e1752 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 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 @@ 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 23a0202..97b31a9 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 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 @@ 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 20138c3..1f61b23 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) { @@ -385,28 +377,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; } @@ -415,7 +398,6 @@ void RenderProxy::outputLogBuffer(int fd) { if (!RenderThread::hasInstance()) return; 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 @@ 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 64278d6..37e11d8 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -141,8 +141,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"); @@ -152,11 +151,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(); @@ -173,7 +167,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 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 @@ 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 f846d6a..f187493 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 5464399..7c155d2 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 d92ad62..d847d13 100644 --- a/libs/hwui/tests/main.cpp +++ b/libs/hwui/tests/main.cpp @@ -88,7 +88,7 @@ int main() { 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() { 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_ */ |