diff options
author | Chris Craik <ccraik@google.com> | 2014-11-20 17:36:24 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-11-20 17:36:26 +0000 |
commit | 3b2ba44be3699a4e133d7a09cb4ed182405d7ff9 (patch) | |
tree | fcded4723a443028815b3ee7e51fcd30a2fb53e7 | |
parent | bf1960ce9c353267490d65cc1b8beacc7dd85347 (diff) | |
parent | 70850ea258cbf91477efa57a1f1a23cc0044cc93 (diff) | |
download | frameworks_base-3b2ba44be3699a4e133d7a09cb4ed182405d7ff9.zip frameworks_base-3b2ba44be3699a4e133d7a09cb4ed182405d7ff9.tar.gz frameworks_base-3b2ba44be3699a4e133d7a09cb4ed182405d7ff9.tar.bz2 |
Merge "Improve logging around performance critical events" into lmp-mr1-dev
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 2 | ||||
-rw-r--r-- | core/java/android/view/View.java | 259 | ||||
-rw-r--r-- | libs/hwui/Layer.cpp | 18 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 5 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.cpp | 32 | ||||
-rw-r--r-- | libs/hwui/PathCache.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Program.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 3 | ||||
-rw-r--r-- | libs/hwui/font/Font.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/utils/TraceUtils.h | 56 |
11 files changed, 225 insertions, 162 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 5579c13..2c8a499 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -274,7 +274,7 @@ public class ThreadedRenderer extends HardwareRenderer { } private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) { - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList"); + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()"); updateViewTreeDisplayList(view); if (mRootNodeNeedsUpdate || !mRootNode.isValid()) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1d19c9b..b54d462 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -56,6 +56,7 @@ import android.os.Parcelable; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; +import android.os.Trace; import android.text.TextUtils; import android.util.AttributeSet; import android.util.FloatProperty; @@ -14405,143 +14406,158 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public void buildDrawingCache(boolean autoScale) { if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ? mDrawingCache == null : mUnscaledDrawingCache == null)) { - mCachingFailed = false; + if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { + Trace.traceBegin(Trace.TRACE_TAG_VIEW, + "buildDrawingCache/SW Layer for " + getClass().getSimpleName()); + } + try { + buildDrawingCacheImpl(autoScale); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + } + } - int width = mRight - mLeft; - int height = mBottom - mTop; + /** + * private, internal implementation of buildDrawingCache, used to enable tracing + */ + private void buildDrawingCacheImpl(boolean autoScale) { + mCachingFailed = false; - final AttachInfo attachInfo = mAttachInfo; - final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; + int width = mRight - mLeft; + int height = mBottom - mTop; + + final AttachInfo attachInfo = mAttachInfo; + final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired; + + if (autoScale && scalingRequired) { + width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); + height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); + } + + final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; + final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); + final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; - if (autoScale && scalingRequired) { - width = (int) ((width * attachInfo.mApplicationScale) + 0.5f); - height = (int) ((height * attachInfo.mApplicationScale) + 0.5f); + final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); + final long drawingCacheSize = + ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); + if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { + if (width > 0 && height > 0) { + Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs " + + projectedBitmapSize + " bytes, only " + + drawingCacheSize + " available"); } + destroyDrawingCache(); + mCachingFailed = true; + return; + } - final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; - final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); - final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache; + boolean clear = true; + Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; - final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4); - final long drawingCacheSize = - ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize(); - if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) { - if (width > 0 && height > 0) { - Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs " - + projectedBitmapSize + " bytes, only " - + drawingCacheSize + " available"); + if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { + Bitmap.Config quality; + if (!opaque) { + // Never pick ARGB_4444 because it looks awful + // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case + switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { + case DRAWING_CACHE_QUALITY_AUTO: + case DRAWING_CACHE_QUALITY_LOW: + case DRAWING_CACHE_QUALITY_HIGH: + default: + quality = Bitmap.Config.ARGB_8888; + break; } - destroyDrawingCache(); - mCachingFailed = true; - return; + } else { + // Optimization for translucent windows + // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() + quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; } - boolean clear = true; - Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache; + // Try to cleanup memory + if (bitmap != null) bitmap.recycle(); - if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { - Bitmap.Config quality; - if (!opaque) { - // Never pick ARGB_4444 because it looks awful - // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case - switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { - case DRAWING_CACHE_QUALITY_AUTO: - case DRAWING_CACHE_QUALITY_LOW: - case DRAWING_CACHE_QUALITY_HIGH: - default: - quality = Bitmap.Config.ARGB_8888; - break; - } + try { + bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), + width, height, quality); + bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); + if (autoScale) { + mDrawingCache = bitmap; } else { - // Optimization for translucent windows - // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() - quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; + mUnscaledDrawingCache = bitmap; } - - // Try to cleanup memory - if (bitmap != null) bitmap.recycle(); - - try { - bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(), - width, height, quality); - bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); - if (autoScale) { - mDrawingCache = bitmap; - } else { - mUnscaledDrawingCache = bitmap; - } - if (opaque && use32BitCache) bitmap.setHasAlpha(false); - } catch (OutOfMemoryError e) { - // If there is not enough memory to create the bitmap cache, just - // ignore the issue as bitmap caches are not required to draw the - // view hierarchy - if (autoScale) { - mDrawingCache = null; - } else { - mUnscaledDrawingCache = null; - } - mCachingFailed = true; - return; + if (opaque && use32BitCache) bitmap.setHasAlpha(false); + } catch (OutOfMemoryError e) { + // If there is not enough memory to create the bitmap cache, just + // ignore the issue as bitmap caches are not required to draw the + // view hierarchy + if (autoScale) { + mDrawingCache = null; + } else { + mUnscaledDrawingCache = null; } - - clear = drawingCacheBackgroundColor != 0; + mCachingFailed = true; + return; } - Canvas canvas; - if (attachInfo != null) { - canvas = attachInfo.mCanvas; - if (canvas == null) { - canvas = new Canvas(); - } - canvas.setBitmap(bitmap); - // Temporarily clobber the cached Canvas in case one of our children - // is also using a drawing cache. Without this, the children would - // steal the canvas by attaching their own bitmap to it and bad, bad - // thing would happen (invisible views, corrupted drawings, etc.) - attachInfo.mCanvas = null; - } else { - // This case should hopefully never or seldom happen - canvas = new Canvas(bitmap); - } + clear = drawingCacheBackgroundColor != 0; + } - if (clear) { - bitmap.eraseColor(drawingCacheBackgroundColor); + Canvas canvas; + if (attachInfo != null) { + canvas = attachInfo.mCanvas; + if (canvas == null) { + canvas = new Canvas(); } + canvas.setBitmap(bitmap); + // Temporarily clobber the cached Canvas in case one of our children + // is also using a drawing cache. Without this, the children would + // steal the canvas by attaching their own bitmap to it and bad, bad + // thing would happen (invisible views, corrupted drawings, etc.) + attachInfo.mCanvas = null; + } else { + // This case should hopefully never or seldom happen + canvas = new Canvas(bitmap); + } - computeScroll(); - final int restoreCount = canvas.save(); + if (clear) { + bitmap.eraseColor(drawingCacheBackgroundColor); + } - if (autoScale && scalingRequired) { - final float scale = attachInfo.mApplicationScale; - canvas.scale(scale, scale); - } + computeScroll(); + final int restoreCount = canvas.save(); - canvas.translate(-mScrollX, -mScrollY); + if (autoScale && scalingRequired) { + final float scale = attachInfo.mApplicationScale; + canvas.scale(scale, scale); + } - mPrivateFlags |= PFLAG_DRAWN; - if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || - mLayerType != LAYER_TYPE_NONE) { - mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; - } + canvas.translate(-mScrollX, -mScrollY); - // Fast path for layouts with no backgrounds - if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { - mPrivateFlags &= ~PFLAG_DIRTY_MASK; - dispatchDraw(canvas); - if (mOverlay != null && !mOverlay.isEmpty()) { - mOverlay.getOverlayView().draw(canvas); - } - } else { - draw(canvas); + mPrivateFlags |= PFLAG_DRAWN; + if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || + mLayerType != LAYER_TYPE_NONE) { + mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID; + } + + // Fast path for layouts with no backgrounds + if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) { + mPrivateFlags &= ~PFLAG_DIRTY_MASK; + dispatchDraw(canvas); + if (mOverlay != null && !mOverlay.isEmpty()) { + mOverlay.getOverlayView().draw(canvas); } + } else { + draw(canvas); + } - canvas.restoreToCount(restoreCount); - canvas.setBitmap(null); + canvas.restoreToCount(restoreCount); + canvas.setBitmap(null); - if (attachInfo != null) { - // Restore the cached Canvas for our siblings - attachInfo.mCanvas = canvas; - } + if (attachInfo != null) { + // Restore the cached Canvas for our siblings + attachInfo.mCanvas = canvas; } } @@ -15470,10 +15486,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, && mAttachInfo.mHardwareRenderer != null) { mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode); - final RenderNode displayList = mBackgroundRenderNode; - if (displayList != null && displayList.isValid()) { - setBackgroundDisplayListProperties(displayList); - ((HardwareCanvas) canvas).drawRenderNode(displayList); + final RenderNode renderNode = mBackgroundRenderNode; + if (renderNode != null && renderNode.isValid()) { + setBackgroundRenderNodeProperties(renderNode); + ((HardwareCanvas) canvas).drawRenderNode(renderNode); return; } } @@ -15489,14 +15505,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } } - /** - * Set up background drawable display list properties. - * - * @param displayList Valid display list for the background drawable - */ - private void setBackgroundDisplayListProperties(RenderNode displayList) { - displayList.setTranslationX(mScrollX); - displayList.setTranslationY(mScrollY); + private void setBackgroundRenderNodeProperties(RenderNode renderNode) { + renderNode.setTranslationX(mScrollX); + renderNode.setTranslationY(mScrollY); } /** diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index b95636b..9aa29ca 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -20,11 +20,18 @@ #include "Caches.h" #include "DeferredDisplayList.h" -#include "RenderState.h" #include "Layer.h" #include "LayerRenderer.h" #include "OpenGLRenderer.h" #include "RenderNode.h" +#include "RenderState.h" +#include "utils/TraceUtils.h" + +#define ATRACE_LAYER_WORK(label) \ + ATRACE_FORMAT("%s HW Layer DisplayList %s %ux%u", \ + label, \ + (renderNode.get() != NULL) ? renderNode->getName() : "", \ + getWidth(), getHeight()) namespace android { namespace uirenderer { @@ -223,6 +230,8 @@ void Layer::allocateTexture() { } void Layer::defer(const OpenGLRenderer& rootRenderer) { + ATRACE_LAYER_WORK("Optimize"); + updateLightPosFromRenderer(rootRenderer); const float width = layer.getWidth(); const float height = layer.getHeight(); @@ -260,6 +269,9 @@ void Layer::cancelDefer() { void Layer::flush() { // renderer is checked as layer may be destroyed/put in layer cache with flush scheduled if (deferredList && renderer) { + ATRACE_LAYER_WORK("Issue"); + renderer->startMark((renderNode.get() != NULL) ? renderNode->getName() : "Layer"); + renderer->setViewport(layer.getWidth(), layer.getHeight()); renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, !isBlend()); @@ -270,10 +282,14 @@ void Layer::flush() { dirtyRect.setEmpty(); renderNode = NULL; + + renderer->endMark(); } } void Layer::render(const OpenGLRenderer& rootRenderer) { + ATRACE_LAYER_WORK("Direct-Issue"); + updateLightPosFromRenderer(rootRenderer); renderer->setViewport(layer.getWidth(), layer.getHeight()); renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 394c647..83f9c6a 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -27,6 +27,7 @@ #include "Matrix.h" #include "Properties.h" #include "Rect.h" +#include "utils/TraceUtils.h" namespace android { namespace uirenderer { @@ -185,7 +186,7 @@ void LayerRenderer::generateMesh() { /////////////////////////////////////////////////////////////////////////////// Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height) { - ATRACE_CALL(); + ATRACE_FORMAT("Allocate %ux%u HW Layer", width, height); LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height); Caches& caches = Caches::getInstance(); @@ -310,7 +311,7 @@ void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t he void LayerRenderer::destroyLayer(Layer* layer) { if (layer) { - ATRACE_CALL(); + ATRACE_FORMAT("Destroy %ux%u HW Layer", layer->getWidth(), layer->getHeight()); LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d", layer->getWidth(), layer->getHeight(), layer->getFbo()); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index d570b0d..80b4c2a 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -42,6 +42,7 @@ #include "ShadowTessellator.h" #include "SkiaShader.h" #include "utils/GLUtils.h" +#include "utils/TraceUtils.h" #include "Vector.h" #include "VertexBuffer.h" @@ -51,21 +52,6 @@ #define EVENT_LOGD(...) #endif -static void atraceFormatBegin(const char* fmt, ...) { - const int BUFFER_SIZE = 256; - va_list ap; - char buf[BUFFER_SIZE]; - - va_start(ap, fmt); - vsnprintf(buf, BUFFER_SIZE, fmt, ap); - va_end(ap); - - ATRACE_BEGIN(buf); -} - -#define ATRACE_FORMAT_BEGIN(fmt, ...) \ - if (CC_UNLIKELY(ATRACE_ENABLED())) atraceFormatBegin(fmt, ##__VA_ARGS__) - namespace android { namespace uirenderer { @@ -466,8 +452,6 @@ void OpenGLRenderer::renderOverdraw() { bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) { if (layer->deferredUpdateScheduled && layer->renderer && layer->renderNode.get() && layer->renderNode->isRenderable()) { - ATRACE_CALL(); - Rect& dirty = layer->dirtyRect; if (inFrame) { @@ -525,20 +509,10 @@ void OpenGLRenderer::flushLayers() { int count = mLayerUpdates.size(); if (count > 0) { startMark("Apply Layer Updates"); - char layerName[12]; // Note: it is very important to update the layers in order for (int i = 0; i < count; i++) { - Layer* layer = mLayerUpdates.itemAt(i).get(); - - sprintf(layerName, "Layer #%d", i); - startMark(layerName); - ATRACE_FORMAT_BEGIN("flushLayer %ux%u", layer->getWidth(), layer->getHeight()); - - layer->flush(); - - ATRACE_END(); - endMark(); + mLayerUpdates.itemAt(i)->flush(); } mLayerUpdates.clear(); @@ -575,7 +549,7 @@ void OpenGLRenderer::cancelLayerUpdate(Layer* layer) { } void OpenGLRenderer::flushLayerUpdates() { - ATRACE_CALL(); + ATRACE_NAME("Update HW Layers"); syncState(); updateLayers(); flushLayers(); diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 9ba8854..6f48e4d 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -255,7 +255,7 @@ void PathCache::trim() { PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *path, const SkPaint* paint) { - ATRACE_CALL(); + ATRACE_NAME("Generate Path Texture"); float left, top, offset; uint32_t width, height; diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp index 0dad0dc..e6fd2dc 100644 --- a/libs/hwui/Program.cpp +++ b/libs/hwui/Program.cpp @@ -132,7 +132,7 @@ int Program::getUniform(const char* name) { } GLuint Program::buildShader(const char* source, GLenum type) { - ATRACE_CALL(); + ATRACE_NAME("Build GL Shader"); GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, 0); diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 13c5499..eb0948f 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -25,7 +25,6 @@ #include <SkCanvas.h> #include <algorithm> -#include <utils/Trace.h> #include "DamageAccumulator.h" #include "Debug.h" @@ -34,6 +33,7 @@ #include "LayerRenderer.h" #include "OpenGLRenderer.h" #include "utils/MathUtils.h" +#include "utils/TraceUtils.h" #include "renderthread/CanvasContext.h" namespace android { @@ -426,6 +426,10 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) { clipFlags = 0; // all clipping done by saveLayer } + ATRACE_FORMAT("%s alpha caused %ssaveLayer %ux%u", + getName(), clipFlags ? "" : "unclipped ", + layerBounds.getWidth(), layerBounds.getHeight()); + SaveLayerOp* op = new (handler.allocator()) SaveLayerOp( layerBounds.left, layerBounds.top, layerBounds.right, layerBounds.bottom, properties().getAlpha() * 255, saveFlags); diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 3b8a9a4..5fcb194 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -26,6 +26,7 @@ #include "Caches.h" #include "TextureCache.h" #include "Properties.h" +#include "utils/TraceUtils.h" namespace android { namespace uirenderer { @@ -266,7 +267,7 @@ void TextureCache::generateTexture(const SkBitmap* bitmap, Texture* texture, boo return; } - ATRACE_CALL(); + ATRACE_FORMAT("Upload %ux%u Texture", bitmap->width(), bitmap->height()); // We could also enable mipmapping if both bitmap dimensions are powers // of 2 but we'd have to deal with size changes. Let's keep this simple diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp index ba878ba..af39f16 100644 --- a/libs/hwui/font/Font.cpp +++ b/libs/hwui/font/Font.cpp @@ -363,7 +363,7 @@ void Font::measure(const SkPaint* paint, const char* text, uint32_t start, uint3 } void Font::precache(const SkPaint* paint, const char* text, int numGlyphs) { - ATRACE_NAME("precacheText"); + ATRACE_NAME("Precache Glyphs"); if (numGlyphs == 0 || text == NULL) { return; diff --git a/libs/hwui/utils/TraceUtils.h b/libs/hwui/utils/TraceUtils.h new file mode 100644 index 0000000..ff8ccb8 --- /dev/null +++ b/libs/hwui/utils/TraceUtils.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TRACE_UTILS_H +#define TRACE_UTILS_H + +#include <utils/Trace.h> + +#define ATRACE_FORMAT(fmt, ...) \ + TraceUtils::TraceEnder __traceEnder = (TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__), TraceUtils::TraceEnder()) + +#define ATRACE_FORMAT_BEGIN(fmt, ...) \ + TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__) + +namespace android { +namespace uirenderer { + +class TraceUtils { +public: + class TraceEnder { + public: + ~TraceEnder() { ATRACE_END(); } + }; + + static void atraceFormatBegin(const char* fmt, ...) { + if (CC_UNLIKELY(!ATRACE_ENABLED())) return; + + const int BUFFER_SIZE = 256; + va_list ap; + char buf[BUFFER_SIZE]; + + va_start(ap, fmt); + vsnprintf(buf, BUFFER_SIZE, fmt, ap); + va_end(ap); + + ATRACE_BEGIN(buf); + } + +}; // class TraceUtils + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* TRACE_UTILS_H */ |