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

Commit 10c42162 authored by Aurimas Liutikas's avatar Aurimas Liutikas
Browse files

Start throwing better exceptions in LayoutInflater.

Include source layout file in exceptions thrown from
LayoutInflater. This makes it easier to trace failures
when using <include ...> tags.

You'll get something like
Caused by: android.view.InflateException: Binary XML file line #11 in com.myapp:layout/activity_main: Binary XML file line #6 in com.myapp:layout/overlay: Error inflating class MyView
Caused by: android.view.InflateException: Binary XML file line #6 in com.myapp:layout/overlay: Error inflating class MyView
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.myapp.MyView"...

Bug: 127425845
Test: Manual app launch that has invalid XML
Change-Id: I262fa9625dd2981eb22e493e9e4a1d2b7b75ef4b
parent 436a76d1
Loading
Loading
Loading
Loading
+28 −13
Original line number Diff line number Diff line
@@ -714,7 +714,8 @@ public abstract class LayoutInflater {
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } catch (Exception e) {
                final InflateException ie = new InflateException(parser.getPositionDescription()
                final InflateException ie = new InflateException(
                        getParserStateDescription(inflaterContext, attrs)
                        + ": " + e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
@@ -730,6 +731,16 @@ public abstract class LayoutInflater {
        }
    }

    private static String getParserStateDescription(Context context, AttributeSet attrs) {
        int sourceResId = Resources.getAttributeSetSourceResId(attrs);
        if (sourceResId == Resources.ID_NULL) {
            return attrs.getPositionDescription();
        } else {
            return attrs.getPositionDescription() + " in "
                    + context.getResources().getResourceName(sourceResId);
        }
    }

    private static final ClassLoader BOOT_CLASS_LOADER = LayoutInflater.class.getClassLoader();

    private final boolean verifyClassLoader(Constructor<? extends View> constructor) {
@@ -818,7 +829,7 @@ public abstract class LayoutInflater {
                if (mFilter != null && clazz != null) {
                    boolean allowed = mFilter.onLoadClass(clazz);
                    if (!allowed) {
                        failNotAllowed(name, prefix, attrs);
                        failNotAllowed(name, prefix, viewContext, attrs);
                    }
                }
                constructor = clazz.getConstructor(mConstructorSignature);
@@ -837,10 +848,10 @@ public abstract class LayoutInflater {
                        boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                        mFilterMap.put(name, allowed);
                        if (!allowed) {
                            failNotAllowed(name, prefix, attrs);
                            failNotAllowed(name, prefix, viewContext, attrs);
                        }
                    } else if (allowedState.equals(Boolean.FALSE)) {
                        failNotAllowed(name, prefix, attrs);
                        failNotAllowed(name, prefix, viewContext, attrs);
                    }
                }
            }
@@ -862,14 +873,16 @@ public abstract class LayoutInflater {
                mConstructorArgs[0] = lastContext;
            }
        } catch (NoSuchMethodException e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription()
            final InflateException ie = new InflateException(
                    getParserStateDescription(viewContext, attrs)
                    + ": Error inflating class " + (prefix != null ? (prefix + name) : name), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;

        } catch (ClassCastException e) {
            // If loaded class is not a View subclass
            final InflateException ie = new InflateException(attrs.getPositionDescription()
            final InflateException ie = new InflateException(
                    getParserStateDescription(viewContext, attrs)
                    + ": Class is not a View " + (prefix != null ? (prefix + name) : name), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
@@ -878,7 +891,7 @@ public abstract class LayoutInflater {
            throw e;
        } catch (Exception e) {
            final InflateException ie = new InflateException(
                    attrs.getPositionDescription() + ": Error inflating class "
                    getParserStateDescription(viewContext, attrs) + ": Error inflating class "
                            + (clazz == null ? "<unknown>" : clazz.getName()), e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
@@ -890,8 +903,8 @@ public abstract class LayoutInflater {
    /**
     * Throw an exception because the specified class is not allowed to be inflated.
     */
    private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
        throw new InflateException(attrs.getPositionDescription()
    private void failNotAllowed(String name, String prefix, Context context, AttributeSet attrs) {
        throw new InflateException(getParserStateDescription(context, attrs)
                + ": Class not allowed to be inflated "+ (prefix != null ? (prefix + name) : name));
    }

@@ -1013,13 +1026,15 @@ public abstract class LayoutInflater {
            throw e;

        } catch (ClassNotFoundException e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription()
            final InflateException ie = new InflateException(
                    getParserStateDescription(context, attrs)
                    + ": Error inflating class " + name, e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;

        } catch (Exception e) {
            final InflateException ie = new InflateException(attrs.getPositionDescription()
            final InflateException ie = new InflateException(
                    getParserStateDescription(context, attrs)
                    + ": Error inflating class " + name, e);
            ie.setStackTrace(EMPTY_STACK_TRACE);
            throw ie;
@@ -1215,8 +1230,8 @@ public abstract class LayoutInflater {
                }

                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(childParser.getPositionDescription() +
                        ": No start tag found!");
                    throw new InflateException(getParserStateDescription(context, childAttrs)
                            + ": No start tag found!");
                }

                final String childName = childParser.getName();