Skip to content

Commit f49d835

Browse files
Justin HoAndroid (Google) Code Review
authored andcommitted
This restores JB MR0 behavior where the framework throws an exception for improper layouts that are missing layout_width and/or layout_height.
This reverts commit 57fca90 Change-Id: I0fe25056cd54b8852b32ae4621e048d3f5c7d555
1 parent 57fca90 commit f49d835

File tree

8 files changed

+106
-74
lines changed

8 files changed

+106
-74
lines changed

api/current.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7094,7 +7094,7 @@ package android.content.res {
70947094
method public int getIndexCount();
70957095
method public int getInt(int, int);
70967096
method public int getInteger(int, int);
7097-
method public deprecated int getLayoutDimension(int, java.lang.String);
7097+
method public int getLayoutDimension(int, java.lang.String);
70987098
method public int getLayoutDimension(int, int);
70997099
method public java.lang.String getNonResourceString(int);
71007100
method public java.lang.String getPositionDescription();
@@ -16149,7 +16149,7 @@ package android.os {
1614916149

1615016150
public class Looper {
1615116151
method public void dump(android.util.Printer, java.lang.String);
16152-
method public static android.os.Looper getMainLooper();
16152+
method public static synchronized android.os.Looper getMainLooper();
1615316153
method public java.lang.Thread getThread();
1615416154
method public static void loop();
1615516155
method public static android.os.Looper myLooper();

core/java/android/content/res/TypedArray.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -469,20 +469,13 @@ public int getDimensionPixelSize(int index, int defValue) {
469469
* {@link android.view.ViewGroup}'s layout_width and layout_height
470470
* attributes. This is only here for performance reasons; applications
471471
* should use {@link #getDimensionPixelSize}.
472-
*
472+
*
473473
* @param index Index of the attribute to retrieve.
474474
* @param name Textual name of attribute for error reporting.
475475
*
476476
* @return Attribute dimension value multiplied by the appropriate
477477
* metric and truncated to integer pixels.
478-
*
479-
* @throws RuntimeException
480-
* if this TypedArray does not contain an entry for <code>index</code>
481-
*
482-
* @deprecated Use {@link #getLayoutDimension(int, int)} instead.
483-
*
484478
*/
485-
@Deprecated
486479
public int getLayoutDimension(int index, String name) {
487480
index *= AssetManager.STYLE_NUM_ENTRIES;
488481
final int[] data = mData;

core/java/android/view/LayoutInflater.java

Lines changed: 53 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import android.os.Handler;
2121
import android.os.Message;
2222
import android.widget.FrameLayout;
23-
import com.android.internal.R;
2423
import org.xmlpull.v1.XmlPullParser;
2524
import org.xmlpull.v1.XmlPullParserException;
2625

@@ -44,20 +43,20 @@
4443
*
4544
* <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
4645
* (Context.LAYOUT_INFLATER_SERVICE);</pre>
47-
*
46+
*
4847
* <p>
4948
* To create a new LayoutInflater with an additional {@link Factory} for your
5049
* own views, you can use {@link #cloneInContext} to clone an existing
5150
* ViewFactory, and then call {@link #setFactory} on it to include your
5251
* Factory.
53-
*
52+
*
5453
* <p>
5554
* For performance reasons, view inflation relies heavily on pre-processing of
5655
* XML files that is done at build time. Therefore, it is not currently possible
5756
* to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
5857
* it only works with an XmlPullParser returned from a compiled resource
5958
* (R.<em>something</em> file.)
60-
*
59+
*
6160
* @see Context#getSystemService
6261
*/
6362
public abstract class LayoutInflater {
@@ -83,7 +82,7 @@ public abstract class LayoutInflater {
8382

8483
private static final HashMap<String, Constructor<? extends View>> sConstructorMap =
8584
new HashMap<String, Constructor<? extends View>>();
86-
85+
8786
private HashMap<String, Boolean> mFilterMap;
8887

8988
private static final String TAG_MERGE = "merge";
@@ -94,36 +93,36 @@ public abstract class LayoutInflater {
9493
/**
9594
* Hook to allow clients of the LayoutInflater to restrict the set of Views that are allowed
9695
* to be inflated.
97-
*
96+
*
9897
*/
9998
public interface Filter {
10099
/**
101100
* Hook to allow clients of the LayoutInflater to restrict the set of Views
102101
* that are allowed to be inflated.
103-
*
102+
*
104103
* @param clazz The class object for the View that is about to be inflated
105-
*
104+
*
106105
* @return True if this class is allowed to be inflated, or false otherwise
107106
*/
108107
@SuppressWarnings("unchecked")
109108
boolean onLoadClass(Class clazz);
110109
}
111-
110+
112111
public interface Factory {
113112
/**
114113
* Hook you can supply that is called when inflating from a LayoutInflater.
115114
* You can use this to customize the tag names available in your XML
116115
* layout files.
117-
*
116+
*
118117
* <p>
119118
* Note that it is good practice to prefix these custom names with your
120119
* package (i.e., com.coolcompany.apps) to avoid conflicts with system
121120
* names.
122-
*
121+
*
123122
* @param name Tag name to be inflated.
124123
* @param context The context the view is being created in.
125124
* @param attrs Inflation attributes as specified in XML file.
126-
*
125+
*
127126
* @return View Newly created view. Return null for the default
128127
* behavior.
129128
*/
@@ -151,14 +150,14 @@ public interface Factory2 extends Factory {
151150
private static class FactoryMerger implements Factory2 {
152151
private final Factory mF1, mF2;
153152
private final Factory2 mF12, mF22;
154-
153+
155154
FactoryMerger(Factory f1, Factory2 f12, Factory f2, Factory2 f22) {
156155
mF1 = f1;
157156
mF2 = f2;
158157
mF12 = f12;
159158
mF22 = f22;
160159
}
161-
160+
162161
public View onCreateView(String name, Context context, AttributeSet attrs) {
163162
View v = mF1.onCreateView(name, context, attrs);
164163
if (v != null) return v;
@@ -173,13 +172,13 @@ public View onCreateView(View parent, String name, Context context, AttributeSet
173172
: mF2.onCreateView(name, context, attrs);
174173
}
175174
}
176-
175+
177176
/**
178177
* Create a new LayoutInflater instance associated with a particular Context.
179178
* Applications will almost always want to use
180179
* {@link Context#getSystemService Context.getSystemService()} to retrieve
181180
* the standard {@link Context#LAYOUT_INFLATER_SERVICE Context.INFLATER_SERVICE}.
182-
*
181+
*
183182
* @param context The Context in which this LayoutInflater will create its
184183
* Views; most importantly, this supplies the theme from which the default
185184
* values for their attributes are retrieved.
@@ -192,7 +191,7 @@ protected LayoutInflater(Context context) {
192191
* Create a new LayoutInflater instance that is a copy of an existing
193192
* LayoutInflater, optionally with its Context changed. For use in
194193
* implementing {@link #cloneInContext}.
195-
*
194+
*
196195
* @param original The original LayoutInflater to copy.
197196
* @param newContext The new Context to use.
198197
*/
@@ -203,7 +202,7 @@ protected LayoutInflater(LayoutInflater original, Context newContext) {
203202
mPrivateFactory = original.mPrivateFactory;
204203
mFilter = original.mFilter;
205204
}
206-
205+
207206
/**
208207
* Obtains the LayoutInflater from the given context.
209208
*/
@@ -221,15 +220,15 @@ public static LayoutInflater from(Context context) {
221220
* pointing to a different Context than the original. This is used by
222221
* {@link ContextThemeWrapper} to create a new LayoutInflater to go along
223222
* with the new Context theme.
224-
*
223+
*
225224
* @param newContext The new Context to associate with the new LayoutInflater.
226225
* May be the same as the original Context if desired.
227-
*
226+
*
228227
* @return Returns a brand spanking new LayoutInflater object associated with
229228
* the given Context.
230229
*/
231230
public abstract LayoutInflater cloneInContext(Context newContext);
232-
231+
233232
/**
234233
* Return the context we are running in, for access to resources, class
235234
* loader, etc.
@@ -265,7 +264,7 @@ public final Factory2 getFactory2() {
265264
* called on each element name as the xml is parsed. If the factory returns
266265
* a View, that is added to the hierarchy. If it returns null, the next
267266
* factory default {@link #onCreateView} method is called.
268-
*
267+
*
269268
* <p>If you have an existing
270269
* LayoutInflater and want to add your own factory to it, use
271270
* {@link #cloneInContext} to clone the existing instance and then you
@@ -321,13 +320,13 @@ public void setPrivateFactory(Factory2 factory) {
321320
public Filter getFilter() {
322321
return mFilter;
323322
}
324-
323+
325324
/**
326325
* Sets the {@link Filter} to by this LayoutInflater. If a view is attempted to be inflated
327326
* which is not allowed by the {@link Filter}, the {@link #inflate(int, ViewGroup)} call will
328327
* throw an {@link InflateException}. This filter will replace any previous filter set on this
329328
* LayoutInflater.
330-
*
329+
*
331330
* @param filter The Filter which restricts the set of Views that are allowed to be inflated.
332331
* This filter will replace any previous filter set on this LayoutInflater.
333332
*/
@@ -341,7 +340,7 @@ public void setFilter(Filter filter) {
341340
/**
342341
* Inflate a new view hierarchy from the specified xml resource. Throws
343342
* {@link InflateException} if there is an error.
344-
*
343+
*
345344
* @param resource ID for an XML layout resource to load (e.g.,
346345
* <code>R.layout.main_page</code>)
347346
* @param root Optional view to be the parent of the generated hierarchy.
@@ -361,7 +360,7 @@ public View inflate(int resource, ViewGroup root) {
361360
* reasons, view inflation relies heavily on pre-processing of XML files
362361
* that is done at build time. Therefore, it is not currently possible to
363362
* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
364-
*
363+
*
365364
* @param parser XML dom node containing the description of the view
366365
* hierarchy.
367366
* @param root Optional view to be the parent of the generated hierarchy.
@@ -376,7 +375,7 @@ public View inflate(XmlPullParser parser, ViewGroup root) {
376375
/**
377376
* Inflate a new view hierarchy from the specified xml resource. Throws
378377
* {@link InflateException} if there is an error.
379-
*
378+
*
380379
* @param resource ID for an XML layout resource to load (e.g.,
381380
* <code>R.layout.main_page</code>)
382381
* @param root Optional view to be the parent of the generated hierarchy (if
@@ -408,7 +407,7 @@ public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
408407
* reasons, view inflation relies heavily on pre-processing of XML files
409408
* that is done at build time. Therefore, it is not currently possible to
410409
* use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
411-
*
410+
*
412411
* @param parser XML dom node containing the description of the view
413412
* hierarchy.
414413
* @param root Optional view to be the parent of the generated hierarchy (if
@@ -443,7 +442,7 @@ public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
443442
}
444443

445444
final String name = parser.getName();
446-
445+
447446
if (DEBUG) {
448447
System.out.println("**************************");
449448
System.out.println("Creating root view: "
@@ -529,17 +528,17 @@ public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)
529528
* Low-level function for instantiating a view by name. This attempts to
530529
* instantiate a view class of the given <var>name</var> found in this
531530
* LayoutInflater's ClassLoader.
532-
*
531+
*
533532
* <p>
534533
* There are two things that can happen in an error case: either the
535534
* exception describing the error will be thrown, or a null will be
536535
* returned. You must deal with both possibilities -- the former will happen
537536
* the first time createView() is called for a class of a particular name,
538537
* the latter every time there-after for that class name.
539-
*
538+
*
540539
* @param name The full name of the class to be instantiated.
541540
* @param attrs The XML attributes supplied for this instance.
542-
*
541+
*
543542
* @return View The newly instantiated view, or null.
544543
*/
545544
public final View createView(String name, String prefix, AttributeSet attrs)
@@ -552,7 +551,7 @@ public final View createView(String name, String prefix, AttributeSet attrs)
552551
// Class not found in the cache, see if it's real, and try to add it
553552
clazz = mContext.getClassLoader().loadClass(
554553
prefix != null ? (prefix + name) : name).asSubclass(View.class);
555-
554+
556555
if (mFilter != null && clazz != null) {
557556
boolean allowed = mFilter.onLoadClass(clazz);
558557
if (!allowed) {
@@ -570,7 +569,7 @@ public final View createView(String name, String prefix, AttributeSet attrs)
570569
// New class -- remember whether it is allowed
571570
clazz = mContext.getClassLoader().loadClass(
572571
prefix != null ? (prefix + name) : name).asSubclass(View.class);
573-
572+
574573
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
575574
mFilterMap.put(name, allowed);
576575
if (!allowed) {
@@ -633,10 +632,10 @@ private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
633632
* given the xml element name. Override it to handle custom view objects. If
634633
* you override this in your subclass be sure to call through to
635634
* super.onCreateView(name) for names you do not recognize.
636-
*
635+
*
637636
* @param name The fully qualified class name of the View to be create.
638637
* @param attrs An AttributeSet of attributes to apply to the View.
639-
*
638+
*
640639
* @return View The View created.
641640
*/
642641
protected View onCreateView(String name, AttributeSet attrs)
@@ -680,7 +679,7 @@ View createViewFromTag(View parent, String name, AttributeSet attrs) {
680679
if (view == null && mPrivateFactory != null) {
681680
view = mPrivateFactory.onCreateView(parent, name, mContext, attrs);
682681
}
683-
682+
684683
if (view == null) {
685684
if (-1 == name.indexOf('.')) {
686685
view = onCreateView(parent, name, attrs);
@@ -727,7 +726,7 @@ void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
727726
}
728727

729728
final String name = parser.getName();
730-
729+
731730
if (TAG_REQUEST_FOCUS.equals(name)) {
732731
parseRequestFocus(parser, parent);
733732
} else if (TAG_INCLUDE.equals(name)) {
@@ -742,7 +741,7 @@ void rInflate(XmlPullParser parser, View parent, final AttributeSet attrs,
742741
final ViewGroup viewGroup = (ViewGroup) parent;
743742
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
744743
rInflate(parser, view, attrs, true);
745-
viewGroup.addView(view, params);
744+
viewGroup.addView(view, params);
746745
} else {
747746
final View view = createViewFromTag(parent, name, attrs);
748747
final ViewGroup viewGroup = (ViewGroup) parent;
@@ -811,14 +810,21 @@ private void parseInclude(XmlPullParser parser, View parent, AttributeSet attrs)
811810
// We try to load the layout params set in the <include /> tag. If
812811
// they don't exist, we will rely on the layout params set in the
813812
// included XML file.
814-
TypedArray ta = getContext().obtainStyledAttributes(attrs,
815-
R.styleable.ViewGroup_Layout);
816-
boolean definesBothWidthAndHeight =
817-
ta.hasValue(R.styleable.ViewGroup_Layout_layout_width) &&
818-
ta.hasValue(R.styleable.ViewGroup_Layout_layout_height);
819-
AttributeSet attributes = definesBothWidthAndHeight ? attrs : childAttrs;
820-
view.setLayoutParams(group.generateLayoutParams(attributes));
821-
ta.recycle();
813+
// During a layoutparams generation, a runtime exception is thrown
814+
// if either layout_width or layout_height is missing. We catch
815+
// this exception and set localParams accordingly: true means we
816+
// successfully loaded layout params from the <include /> tag,
817+
// false means we need to rely on the included layout params.
818+
ViewGroup.LayoutParams params = null;
819+
try {
820+
params = group.generateLayoutParams(attrs);
821+
} catch (RuntimeException e) {
822+
params = group.generateLayoutParams(childAttrs);
823+
} finally {
824+
if (params != null) {
825+
view.setLayoutParams(params);
826+
}
827+
}
822828

823829
// Inflate all children.
824830
rInflate(childParser, view, childAttrs, true);

core/java/android/view/ViewGroup.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5611,19 +5611,15 @@ public LayoutParams(LayoutParams source) {
56115611
}
56125612

56135613
/**
5614-
* Extracts the <code>width</code> and <code>height</code> layout parameters
5615-
* from the supplied TypedArray, <code>a</code>, and assigns them
5616-
* to the appropriate fields. If, <code>a</code>, does not contain an
5617-
* entry for either attribute, the value, {@link ViewGroup.LayoutParams#WRAP_CONTENT},
5618-
* is used as a default.
5614+
* Extracts the layout parameters from the supplied attributes.
56195615
*
56205616
* @param a the style attributes to extract the parameters from
56215617
* @param widthAttr the identifier of the width attribute
56225618
* @param heightAttr the identifier of the height attribute
56235619
*/
56245620
protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
5625-
width = a.getLayoutDimension(widthAttr, WRAP_CONTENT);
5626-
height = a.getLayoutDimension(heightAttr, WRAP_CONTENT);
5621+
width = a.getLayoutDimension(widthAttr, "layout_width");
5622+
height = a.getLayoutDimension(heightAttr, "layout_height");
56275623
}
56285624

56295625
/**

0 commit comments

Comments
 (0)