Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d17043dc authored by Romain Guy's avatar Romain Guy
Browse files

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
parent 4bac6c1a
Loading
Loading
Loading
Loading
+21 −31
Original line number Diff line number Diff line
@@ -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");