Merge "Make layoutlib more lenient with recoverable errors" into oc-dev

This commit is contained in:
Diego Perez
2017-03-30 13:12:34 +00:00
committed by Android (Google) Code Review
17 changed files with 119 additions and 78 deletions

View File

@@ -740,9 +740,11 @@ public final class BridgeTypedArray extends TypedArray {
} }
int id = getResourceId(index, 0); int id = getResourceId(index, 0);
String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : ""; String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
throw new NotFoundException( assert false :
String.format("%1$s in %2$s%3$s is not a valid array resource.", String.format("%1$s in %2$s%3$s is not a valid array resource.", resVal.getValue(),
resVal.getValue(), mNames[index], resIdMessage)); mNames[index], resIdMessage);
return new CharSequence[0];
} }
@Override @Override

View File

@@ -88,8 +88,9 @@ public final class BlendComposite implements Composite {
private void setAlpha(float alpha) { private void setAlpha(float alpha) {
if (alpha < 0.0f || alpha > 1.0f) { if (alpha < 0.0f || alpha > 1.0f) {
throw new IllegalArgumentException( assert false : "alpha must be comprised between 0.0f and 1.0f";
"alpha must be comprised between 0.0f and 1.0f"); alpha = Math.min(alpha, 1.0f);
alpha = Math.max(alpha, 0.0f);
} }
this.alpha = alpha; this.alpha = alpha;
@@ -266,9 +267,21 @@ public final class BlendComposite implements Composite {
return result; return result;
} }
}; };
default:
assert false : "Blender not implement for " + composite.getMode().name();
// Ignore the blend
return new Blender() {
@Override
public int[] blend(int[] src, int[] dst, int[] result) {
result[0] = dst[0];
result[1] = dst[1];
result[2] = dst[2];
result[3] = dst[3];
return result;
}
};
} }
throw new IllegalArgumentException("Blender not implement for " +
composite.getMode().name());
} }
} }
} }

View File

@@ -252,7 +252,8 @@ public class FontFamily_Delegate {
/*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex, /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex,
FontConfig.Axis[] axes, int weight, int italic) { FontConfig.Axis[] axes, int weight, int italic) {
if (thisFontFamily.mBuilderPtr == 0) { if (thisFontFamily.mBuilderPtr == 0) {
throw new IllegalStateException("Unable to call addFont after freezing."); assert false : "Unable to call addFont after freezing.";
return false;
} }
final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr); final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr);
return delegate != null && delegate.addFont(path, ttcIndex, weight, italic); return delegate != null && delegate.addFont(path, ttcIndex, weight, italic);

View File

@@ -49,21 +49,19 @@ public abstract class Gradient_Delegate extends Shader_Delegate {
*/ */
protected Gradient_Delegate(long nativeMatrix, int colors[], float positions[]) { protected Gradient_Delegate(long nativeMatrix, int colors[], float positions[]) {
super(nativeMatrix); super(nativeMatrix);
if (colors.length < 2) { assert colors.length >= 2 : "needs >= 2 number of colors";
throw new IllegalArgumentException("needs >= 2 number of colors");
}
if (positions != null && colors.length != positions.length) {
throw new IllegalArgumentException("color and position arrays must be of equal length");
}
if (positions == null) { if (positions == null) {
float spacing = 1.f / (colors.length - 1); float spacing = 1.f / (colors.length - 1);
positions = new float[colors.length]; positions = new float[colors.length];
positions[0] = 0.f; positions[0] = 0.f;
positions[colors.length-1] = 1.f; positions[colors.length - 1] = 1.f;
for (int i = 1; i < colors.length - 1 ; i++) { for (int i = 1; i < colors.length - 1; i++) {
positions[i] = spacing * i; positions[i] = spacing * i;
} }
} else {
assert colors.length == positions.length :
"color and position " + "arrays must be of equal length";
} }
mColors = colors; mColors = colors;

View File

@@ -548,10 +548,11 @@ public final class Path_Delegate {
case EVEN_ODD: case EVEN_ODD:
case INVERSE_EVEN_ODD: case INVERSE_EVEN_ODD:
return GeneralPath.WIND_EVEN_ODD; return GeneralPath.WIND_EVEN_ODD;
}
assert false; default:
throw new IllegalArgumentException(); assert false;
return GeneralPath.WIND_NON_ZERO;
}
} }
@NonNull @NonNull

View File

@@ -61,10 +61,8 @@ public class RoundRectangle extends RectangularShape {
* ellipse that corner is a quarter of. * ellipse that corner is a quarter of.
*/ */
public RoundRectangle(float x, float y, float width, float height, float[] cornerDimensions) { public RoundRectangle(float x, float y, float width, float height, float[] cornerDimensions) {
if (cornerDimensions.length != 8) { assert cornerDimensions.length == 8 : "The array of corner dimensions must have eight " +
throw new IllegalArgumentException("The array of corner dimensions must have eight " + "elements";
"elements");
}
this.x = x; this.x = x;
this.y = y; this.y = y;

View File

@@ -585,8 +585,8 @@ public class VectorDrawable_Delegate {
return this::setTrimPathOffset; return this::setTrimPathOffset;
} }
throw new IllegalArgumentException("Invalid VFullPath_Delegate property index " assert false : ("Invalid VFullPath_Delegate property index " + propertyIdx);
+ propertyIdx); return t -> {};
} }
@NonNull @NonNull
@@ -598,8 +598,8 @@ public class VectorDrawable_Delegate {
return this::setFillColor; return this::setFillColor;
} }
throw new IllegalArgumentException("Invalid VFullPath_Delegate property index " assert false : ("Invalid VFullPath_Delegate property index " + propertyIdx);
+ propertyIdx); return t -> {};
} }
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@@ -827,8 +827,8 @@ public class VectorDrawable_Delegate {
return this::setTranslateY; return this::setTranslateY;
} }
throw new IllegalArgumentException("Invalid VGroup_Delegate property index " assert false : ("Invalid VGroup_Delegate property index " + propertyIdx);
+ propertyIdx); return t -> {};
} }
///////////////////////////////////////////////////// /////////////////////////////////////////////////////

View File

@@ -164,7 +164,9 @@ public class StaticLayout_Delegate {
builder.mTabStopCalculator); builder.mTabStopCalculator);
break; break;
default: default:
throw new AssertionError("Unknown break strategy: " + builder.mBreakStrategy); assert false : "Unknown break strategy: " + builder.mBreakStrategy;
builder.mLineBreaker = new GreedyLineBreaker(primitives, builder.mLineWidth,
builder.mTabStopCalculator);
} }
builder.mLineBreaker.computeBreaks(recycle); builder.mLineBreaker.computeBreaks(recycle);
return recycle.breaks.length; return recycle.breaks.length;

View File

@@ -361,7 +361,8 @@ public class PathParser_Delegate {
} }
return Arrays.copyOf(results, count); return Arrays.copyOf(results, count);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
throw new RuntimeException("error in parsing \"" + s + "\"", e); assert false : "error in parsing \"" + s + "\"" + e;
return new float[0];
} }
} }

View File

@@ -16,6 +16,8 @@
package android.view; package android.view;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
@@ -104,8 +106,10 @@ public class LayoutInflater_Delegate {
if (layout == 0) { if (layout == 0) {
final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
if (value == null || value.length() <= 0) { if (value == null || value.length() <= 0) {
throw new InflateException("You must specify a layout in the" Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a layout in the"
+ " include tag: <include layout=\"@layout/layoutID\" />"); + " include tag: <include layout=\"@layout/layoutID\" />", null);
LayoutInflater.consumeChildElements(parser);
return;
} }
// Attempt to resolve the "?attr/name" string to an identifier. // Attempt to resolve the "?attr/name" string to an identifier.
@@ -125,11 +129,11 @@ public class LayoutInflater_Delegate {
if (layout == 0) { if (layout == 0) {
final String value = attrs.getAttributeValue(null, ATTR_LAYOUT); final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
if (value == null) { if (value == null) {
throw new InflateException("You must specifiy a layout in the" Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a layout in the"
+ " include tag: <include layout=\"@layout/layoutID\" />"); + " include tag: <include layout=\"@layout/layoutID\" />", null);
} else { } else {
throw new InflateException("You must specifiy a valid layout " Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a valid layout "
+ "reference. The layout ID " + value + " is not valid."); + "reference. The layout ID " + value + " is not valid.", null);
} }
} else { } else {
final XmlResourceParser childParser = final XmlResourceParser childParser =
@@ -144,8 +148,11 @@ public class LayoutInflater_Delegate {
} }
if (type != XmlPullParser.START_TAG) { if (type != XmlPullParser.START_TAG) {
throw new InflateException(childParser.getPositionDescription() + Bridge.getLog().error(LayoutLog.TAG_BROKEN,
": No start tag found!"); childParser.getPositionDescription() + ": No start tag found!",
null);
LayoutInflater.consumeChildElements(parser);
return;
} }
final String childName = childParser.getName(); final String childName = childParser.getName();
@@ -219,7 +226,9 @@ public class LayoutInflater_Delegate {
} }
} }
} else { } else {
throw new InflateException("<include /> can only be used inside of a ViewGroup"); Bridge.getLog().error(LayoutLog.TAG_BROKEN,
"<include /> can only be used inside of a ViewGroup",
null);
} }
LayoutInflater.consumeChildElements(parser); LayoutInflater.consumeChildElements(parser);

View File

@@ -37,7 +37,8 @@ public class RectShadowPainter {
@NonNull Canvas canvas) { @NonNull Canvas canvas) {
Rect outline = new Rect(); Rect outline = new Rect();
if (!viewOutline.getRect(outline)) { if (!viewOutline.getRect(outline)) {
throw new IllegalArgumentException("Outline is not a rect shadow"); assert false : "Outline is not a rect shadow";
return;
} }
Rect originCanvasRect = canvas.getClipBounds(); Rect originCanvasRect = canvas.getClipBounds();

View File

@@ -652,7 +652,8 @@ public class BridgeContext extends Context {
return null; return null;
} }
throw new UnsupportedOperationException("Unsupported Service: " + service); assert false : "Unsupported Service: " + service;
return null;
} }
@Override @Override
@@ -682,7 +683,9 @@ public class BridgeContext extends Context {
} }
if (style == null) { if (style == null) {
throw new Resources.NotFoundException(); Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
"Failed to find style with " + resId, null);
return null;
} }
} }

View File

@@ -49,6 +49,7 @@ import android.content.pm.VersionedPackage;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; import android.os.Handler;
@@ -307,7 +308,8 @@ public class BridgePackageManager extends PackageManager {
@Override @Override
public Drawable getInstantAppIcon(String packageName) { public Drawable getInstantAppIcon(String packageName) {
throw new UnsupportedOperationException(); assert false : "Unsupported operation";
return new ColorDrawable();
} }
@Override @Override

View File

@@ -21,6 +21,7 @@ import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
import com.android.ide.common.rendering.api.RenderResources; import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.SessionParams;
import com.android.layoutlib.bridge.MockView;
import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeContext;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -53,35 +54,41 @@ public abstract class BridgeActionBar {
mParams = params; mParams = params;
mCallback = params.getLayoutlibCallback().getActionBarCallback(); mCallback = params.getLayoutlibCallback().getActionBarCallback();
ResourceValue layoutName = getLayoutResource(context); ResourceValue layoutName = getLayoutResource(context);
if (layoutName == null) {
throw new RuntimeException("Unable to find the layout for Action Bar.");
}
int layoutId;
if (layoutName.isFramework()) {
layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
layoutName.getName(), 0);
} else {
layoutId = context.getProjectResourceValue(layoutName.getResourceType(),
layoutName.getName(), 0);
int layoutId = 0;
if (layoutName == null) {
assert false : "Unable to find the layout for Action Bar.";
}
else {
if (layoutName.isFramework()) {
layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
layoutName.getName(), 0);
} else {
layoutId = context.getProjectResourceValue(layoutName.getResourceType(),
layoutName.getName(), 0);
}
} }
if (layoutId == 0) { if (layoutId == 0) {
throw new RuntimeException( assert false : String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"",
String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"", layoutName.getName(), layoutName.getResourceType());
layoutName.getName(), layoutName.getResourceType())); mDecorContent = new MockView(context);
}
if (mCallback.isOverflowPopupNeeded()) {
// Create a RelativeLayout around the action bar, to which the overflow popup may be
// added.
mEnclosingLayout = new RelativeLayout(mBridgeContext);
setMatchParent(mEnclosingLayout);
} else {
mEnclosingLayout = null; mEnclosingLayout = null;
} }
else {
if (mCallback.isOverflowPopupNeeded()) {
// Create a RelativeLayout around the action bar, to which the overflow popup may be
// added.
mEnclosingLayout = new RelativeLayout(mBridgeContext);
setMatchParent(mEnclosingLayout);
} else {
mEnclosingLayout = null;
}
// Inflate action bar layout. // Inflate action bar layout.
mDecorContent = mDecorContent = getInflater(context).inflate(layoutId, mEnclosingLayout,
getInflater(context).inflate(layoutId, mEnclosingLayout, mEnclosingLayout != null); mEnclosingLayout != null);
}
} }
/** /**

View File

@@ -83,18 +83,18 @@ abstract class CustomBar extends LinearLayout {
XmlPullParser parser; XmlPullParser parser;
try { try {
parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), name); parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), name);
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(parser, context, false);
try {
inflater.inflate(bridgeParser, this, true);
} finally {
bridgeParser.ensurePopped();
}
} catch (XmlPullParserException e) { } catch (XmlPullParserException e) {
// Should not happen as the resource is bundled with the jar, and ParserFactory should // Should not happen as the resource is bundled with the jar, and ParserFactory should
// have been initialized. // have been initialized.
throw new AssertionError(e); assert false;
}
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(parser, context, false);
try {
inflater.inflate(bridgeParser, this, true);
} finally {
bridgeParser.ensurePopped();
} }
} }

View File

@@ -176,7 +176,8 @@ public class FrameworkActionBar extends BridgeActionBar {
ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems(); ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems();
ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter(); ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter();
if (presenter == null) { if (presenter == null) {
throw new RuntimeException("Failed to create a Presenter for Action Bar Menus."); assert false : "Failed to create a Presenter for Action Bar Menus.";
return false;
} }
if (presenter.isOverflowReserved() && if (presenter.isOverflowReserved() &&
menus != null) { menus != null) {

View File

@@ -43,6 +43,7 @@ import android.content.res.GradientColor;
import android.content.res.Resources.Theme; import android.content.res.Resources.Theme;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate; import android.graphics.Bitmap_Delegate;
import android.graphics.Color;
import android.graphics.NinePatch_Delegate; import android.graphics.NinePatch_Delegate;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Typeface; import android.graphics.Typeface;
@@ -184,7 +185,8 @@ public final class ResourceHelper {
} }
if (type != XmlPullParser.START_TAG) { if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found"); assert false : "No start tag found";
return null;
} }
final String name = blockParser.getName(); final String name = blockParser.getName();