summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/ThreadedRenderer.java2
-rw-r--r--core/java/android/view/View.java259
-rw-r--r--libs/hwui/Layer.cpp18
-rw-r--r--libs/hwui/LayerRenderer.cpp5
-rwxr-xr-xlibs/hwui/OpenGLRenderer.cpp32
-rw-r--r--libs/hwui/PathCache.cpp2
-rw-r--r--libs/hwui/Program.cpp2
-rw-r--r--libs/hwui/RenderNode.cpp6
-rw-r--r--libs/hwui/TextureCache.cpp3
-rw-r--r--libs/hwui/font/Font.cpp2
-rw-r--r--libs/hwui/utils/TraceUtils.h56
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 */