From d17043dcb49d4f060349a8bd58abcddcf3bac9a2 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Tue, 19 Feb 2013 14:12:55 -0800 Subject: [PATCH] Show Dalvik stack trace if an exception happens at draw time External bug: http://code.google.com/p/android/issues/detail?id=49379 Drawing was previously wrapped in a try/finally block which was silently swallowing user code exceptions. For instance, if a View throws a NullPointerException in its onDraw() method, the previous implementation would silently crash in native code. This change extracts the section that builds display lists into a new method that does not contain any try/finally block. In addition, this change logs any exception thrown while drawing display lists. Change-Id: I0abffa4c9183d41aac8b0f8442813e56b957f08f --- core/java/android/view/HardwareRenderer.java | 52 ++++++++------------ 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index c6e145f2fbefd..7929112d8d64a 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -441,16 +441,6 @@ public abstract class HardwareRenderer { abstract boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty); - /** - * Creates a new display list that can be used to record batches of - * drawing operations. - * - * @return A new display list. - */ - public DisplayList createDisplayList() { - return createDisplayList(null); - } - /** * Creates a new display list that can be used to record batches of * drawing operations. @@ -1356,31 +1346,25 @@ public abstract class HardwareRenderer { dirty = beginFrame(canvas, dirty, surfaceState); + DisplayList displayList = buildDisplayList(view, canvas); + int saveCount = 0; int status = DisplayList.STATUS_DONE; try { - view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) - == View.PFLAG_INVALIDATED; - view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; - - long buildDisplayListStartTime = startBuildDisplayListProfiling(); - canvas.clearLayerUpdates(); - - DisplayList displayList = buildDisplayList(view); status = prepareFrame(dirty); saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); - endBuildDisplayListProfiling(buildDisplayListStartTime); - if (displayList != null) { status = drawDisplayList(attachInfo, canvas, displayList, status); } else { // Shouldn't reach here view.draw(canvas); } + } catch (Exception e) { + Log.e(LOG_TAG, "An error has occurred while drawing:", e); } finally { callbacks.onHardwarePostDraw(canvas); canvas.restoreToCount(saveCount); @@ -1408,6 +1392,23 @@ public abstract class HardwareRenderer { return false; } + private DisplayList buildDisplayList(View view, HardwareCanvas canvas) { + view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) + == View.PFLAG_INVALIDATED; + view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; + + long buildDisplayListStartTime = startBuildDisplayListProfiling(); + canvas.clearLayerUpdates(); + + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList"); + DisplayList displayList = view.getDisplayList(); + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + + endBuildDisplayListProfiling(buildDisplayListStartTime); + + return displayList; + } + abstract void drawProfileData(View.AttachInfo attachInfo); private Rect beginFrame(HardwareCanvas canvas, Rect dirty, int surfaceState) { @@ -1455,17 +1456,6 @@ public abstract class HardwareRenderer { } } - private static DisplayList buildDisplayList(View view) { - DisplayList displayList; - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList"); - try { - displayList = view.getDisplayList(); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); - } - return displayList; - } - private int prepareFrame(Rect dirty) { int status; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");