Merge "Avoid security exception when requesting badging"
diff --git a/api/current.txt b/api/current.txt
index 75f33f1..58f5a5e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -247,7 +247,7 @@
field public static final int actionBarTabBarStyle = 16843508; // 0x10102f4
field public static final int actionBarTabStyle = 16843507; // 0x10102f3
field public static final int actionBarTabTextStyle = 16843509; // 0x10102f5
- field public static final int actionBarTheme = 16843836; // 0x101043c
+ field public static final int actionBarTheme = 16843837; // 0x101043d
field public static final int actionBarWidgetTheme = 16843671; // 0x1010397
field public static final int actionButtonStyle = 16843480; // 0x10102d8
field public static final int actionDropDownStyle = 16843479; // 0x10102d7
@@ -290,7 +290,7 @@
field public static final int alwaysDrawnWithCache = 16842991; // 0x10100ef
field public static final int alwaysRetainTaskState = 16843267; // 0x1010203
field public static final int angle = 16843168; // 0x10101a0
- field public static final int animate = 16843822; // 0x101042e
+ field public static final int animate = 16843823; // 0x101042f
field public static final int animateFirstView = 16843477; // 0x10102d5
field public static final int animateLayoutChanges = 16843506; // 0x10102f2
field public static final int animateOnClick = 16843356; // 0x101025c
@@ -377,19 +377,19 @@
field public static final int clipChildren = 16842986; // 0x10100ea
field public static final int clipOrientation = 16843274; // 0x101020a
field public static final int clipToPadding = 16842987; // 0x10100eb
- field public static final int clipToPath = 16843821; // 0x101042d
+ field public static final int clipToPath = 16843822; // 0x101042e
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
- field public static final int colorButtonNormal = 16843828; // 0x1010434
- field public static final int colorButtonNormalColored = 16843830; // 0x1010436
- field public static final int colorButtonPressed = 16843829; // 0x1010435
- field public static final int colorButtonPressedColored = 16843831; // 0x1010437
- field public static final int colorControlActivated = 16843827; // 0x1010433
- field public static final int colorControlNormal = 16843826; // 0x1010432
+ field public static final int colorButtonNormal = 16843829; // 0x1010435
+ field public static final int colorButtonNormalColored = 16843831; // 0x1010437
+ field public static final int colorButtonPressed = 16843830; // 0x1010436
+ field public static final int colorButtonPressedColored = 16843832; // 0x1010438
+ field public static final int colorControlActivated = 16843828; // 0x1010434
+ field public static final int colorControlNormal = 16843827; // 0x1010433
field public static final int colorFocusedHighlight = 16843663; // 0x101038f
field public static final int colorForeground = 16842800; // 0x1010030
field public static final int colorForegroundInverse = 16843270; // 0x1010206
@@ -757,7 +757,7 @@
field public static final int layout_x = 16843135; // 0x101017f
field public static final int layout_y = 16843136; // 0x1010180
field public static final int left = 16843181; // 0x10101ad
- field public static final int limitTo = 16843823; // 0x101042f
+ field public static final int limitTo = 16843824; // 0x1010430
field public static final int lineSpacingExtra = 16843287; // 0x1010217
field public static final int lineSpacingMultiplier = 16843288; // 0x1010218
field public static final int lines = 16843092; // 0x1010154
@@ -867,11 +867,11 @@
field public static final int permissionFlags = 16843719; // 0x10103c7
field public static final int permissionGroup = 16842762; // 0x101000a
field public static final int permissionGroupFlags = 16843717; // 0x10103c5
- field public static final int persistable = 16843832; // 0x1010438
+ field public static final int persistable = 16843833; // 0x1010439
field public static final int persistent = 16842765; // 0x101000d
field public static final int persistentDrawingCache = 16842990; // 0x10100ee
field public static final deprecated int phoneNumber = 16843111; // 0x1010167
- field public static final int pinned = 16843825; // 0x1010431
+ field public static final int pinned = 16843826; // 0x1010432
field public static final int pivotX = 16843189; // 0x10101b5
field public static final int pivotY = 16843190; // 0x10101b6
field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -936,7 +936,7 @@
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
- field public static final int requiredForProfile = 16843824; // 0x1010430
+ field public static final int requiredForProfile = 16843825; // 0x1010431
field public static final int requiresFadingEdge = 16843685; // 0x10103a5
field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
field public static final int resizeMode = 16843619; // 0x1010363
@@ -1022,7 +1022,7 @@
field public static final int shrinkColumns = 16843082; // 0x101014a
field public static final deprecated int singleLine = 16843101; // 0x101015d
field public static final int singleUser = 16843711; // 0x10103bf
- field public static final int slideEdge = 16843835; // 0x101043b
+ field public static final int slideEdge = 16843836; // 0x101043c
field public static final int smallIcon = 16843422; // 0x101029e
field public static final int smallScreens = 16843396; // 0x1010284
field public static final int smoothScrollbar = 16843313; // 0x1010231
@@ -1075,10 +1075,11 @@
field public static final int stretchMode = 16843030; // 0x1010116
field public static final int stroke = 16843811; // 0x1010423
field public static final int strokeLineCap = 16843820; // 0x101042c
+ field public static final int strokeLineJoin = 16843821; // 0x101042d
field public static final int strokeOpacity = 16843812; // 0x1010424
field public static final int strokeWidth = 16843813; // 0x1010425
field public static final int subtitle = 16843473; // 0x10102d1
- field public static final int subtitleTextAppearance = 16843834; // 0x101043a
+ field public static final int subtitleTextAppearance = 16843835; // 0x101043b
field public static final int subtitleTextStyle = 16843513; // 0x10102f9
field public static final int subtypeExtraValue = 16843674; // 0x101039a
field public static final int subtypeId = 16843713; // 0x10103c1
@@ -1194,7 +1195,7 @@
field public static final int tintMode = 16843798; // 0x1010416
field public static final int title = 16843233; // 0x10101e1
field public static final int titleCondensed = 16843234; // 0x10101e2
- field public static final int titleTextAppearance = 16843833; // 0x1010439
+ field public static final int titleTextAppearance = 16843834; // 0x101043a
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
@@ -10662,6 +10663,7 @@
method public void applyTheme(android.content.res.Resources.Theme);
method public boolean canApplyTheme();
method public void clearColorFilter();
+ method public void clearHotspots();
method public final void copyBounds(android.graphics.Rect);
method public final android.graphics.Rect copyBounds();
method public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
@@ -10704,6 +10706,7 @@
method protected void onBoundsChange(android.graphics.Rect);
method protected boolean onLevelChange(int);
method protected boolean onStateChange(int[]);
+ method public void removeHotspot(int);
method public static int resolveOpacity(int, int);
method public void scheduleSelf(java.lang.Runnable, long);
method public abstract void setAlpha(int);
@@ -10716,9 +10719,11 @@
method public void setColorFilter(int, android.graphics.PorterDuff.Mode);
method public void setDither(boolean);
method public void setFilterBitmap(boolean);
+ method public void setHotspot(int, float, float);
method public final boolean setLevel(int);
method public boolean setState(int[]);
method public boolean setVisible(boolean, boolean);
+ method public boolean supportsHotspots();
method public void unscheduleSelf(java.lang.Runnable);
}
@@ -27696,6 +27701,14 @@
method public abstract boolean onTune(android.net.Uri);
}
+ public abstract class TvInputSession {
+ ctor public TvInputSession();
+ method public void release();
+ method public void setSurface(android.view.Surface);
+ method public void setVolume(float);
+ method public void tune(android.net.Uri);
+ }
+
}
package android.util {
diff --git a/core/java/android/tv/TvInputSession.java b/core/java/android/tv/TvInputSession.java
index 5b70a0b..cdd363b 100644
--- a/core/java/android/tv/TvInputSession.java
+++ b/core/java/android/tv/TvInputSession.java
@@ -21,8 +21,6 @@
/**
* The TvInputSession provides the per-session functionality of TvInputService.
- *
- * @hide
*/
public abstract class TvInputSession {
/**
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 0233b73..acdf926 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2131,6 +2131,7 @@
<public type="attr" name="trimPathEnd" />
<public type="attr" name="trimPathOffset" />
<public type="attr" name="strokeLineCap" />
+ <public type="attr" name="strokeLineJoin" />
<public type="attr" name="clipToPath" />
<public type="attr" name="animate" />
<public type="attr" name="limitTo" />
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 1760458..077db7a 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -485,14 +485,13 @@
/**
* Indicates whether the drawable supports hotspots. Hotspots are uniquely
- * identifiable coordinates the may be added, updated and removed within the
+ * identifiable coordinates the may be added, updated and removed within a
* drawable.
*
* @return true if hotspots are supported
* @see #setHotspot(int, float, float)
* @see #removeHotspot(int)
* @see #clearHotspots()
- * @hide until hotspot APIs are finalized
*/
public boolean supportsHotspots() {
return false;
@@ -500,33 +499,33 @@
/**
* Specifies a hotspot's location within the drawable.
+ * <p>
+ * The specified key should be an id declared in the resources of the
+ * application to ensure it is unique (see the <a
+ * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
*
- * @param id unique identifier for the hotspot
- * @param x x-coordinate
- * @param y y-coordinate
- * @hide until hotspot APIs are finalized
+ * @param key The key identifying the hotspot
+ * @param x The X coordinate of the center of the hotspot
+ * @param y The Y coordinate of the center of the hotspot
*/
- public void setHotspot(int id, float x, float y) {}
+ public void setHotspot(int key, float x, float y) {}
/**
- * Removes the specified hotspot from the drawable.
+ * Removes the hotspot with the specified key from the drawable.
*
- * @param id unique identifier for the hotspot
- * @hide until hotspot APIs are finalized
+ * @param key The key identifying the hotspot
*/
- public void removeHotspot(int id) {}
+ public void removeHotspot(int key) {}
/**
* Removes all hotspots from the drawable.
- *
- * @hide until hotspot APIs are finalized
*/
public void clearHotspots() {}
/**
* Whether this drawable requests projection.
*
- * @hide
+ * @hide until we finalize these APIs
*/
public boolean isProjected() {
return false;
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 2eb7b90..6ab33f8 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -118,33 +118,21 @@
return mWrappedDrawable.getDirtyBounds();
}
- /**
- * @hide
- */
@Override
public boolean supportsHotspots() {
return mWrappedDrawable.supportsHotspots();
}
- /**
- * @hide
- */
@Override
public void setHotspot(int id, float x, float y) {
mWrappedDrawable.setHotspot(id, x, y);
}
- /**
- * @hide
- */
@Override
public void removeHotspot(int id) {
mWrappedDrawable.removeHotspot(id);
}
- /**
- * @hide
- */
@Override
public void clearHotspots() {
mWrappedDrawable.clearHotspots();
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 59a0c93..9384caf 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -183,33 +183,21 @@
}
}
- /**
- * @hide
- */
@Override
public boolean supportsHotspots() {
return mInsetState.mDrawable.supportsHotspots();
}
- /**
- * @hide
- */
@Override
public void setHotspot(int id, float x, float y) {
mInsetState.mDrawable.setHotspot(id, x, y);
}
- /**
- * @hide
- */
@Override
public void removeHotspot(int id) {
mInsetState.mDrawable.removeHotspot(id);
}
- /**
- * @hide
- */
@Override
public void clearHotspots() {
mInsetState.mDrawable.clearHotspots();
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 52352c4..b366987 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -548,9 +548,6 @@
}
}
- /**
- * @hide
- */
@Override
public boolean supportsHotspots() {
final ChildDrawable[] array = mLayerState.mChildren;
@@ -564,9 +561,6 @@
return false;
}
- /**
- * @hide
- */
@Override
public void setHotspot(int id, float x, float y) {
final ChildDrawable[] array = mLayerState.mChildren;
@@ -576,9 +570,6 @@
}
}
- /**
- * @hide
- */
@Override
public void removeHotspot(int id) {
final ChildDrawable[] array = mLayerState.mChildren;
@@ -588,9 +579,6 @@
}
}
- /**
- * @hide
- */
@Override
public void clearHotspots() {
final ChildDrawable[] array = mLayerState.mChildren;
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 1641511..3323a25 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -217,20 +217,11 @@
return super.canApplyTheme() || mState != null && mState.mTouchThemeAttrs != null;
}
- /**
- * @hide until hotspot APIs are finalized
- */
@Override
public boolean supportsHotspots() {
return true;
}
- /**
- * TODO: Maybe we should set hotspots for state/id combinations? So touch
- * would be state_pressed and the pointer ID.
- *
- * @hide until hotspot APIs are finalized
- */
@Override
public void setHotspot(int id, float x, float y) {
if (mTouchedRipples == null) {
@@ -261,9 +252,6 @@
scheduleAnimation();
}
- /**
- * @hide until hotspot APIs are finalized
- */
@Override
public void removeHotspot(int id) {
if (mTouchedRipples == null) {
@@ -279,9 +267,6 @@
}
}
- /**
- * @hide until hotspot APIs are finalized
- */
@Override
public void clearHotspots() {
if (mTouchedRipples == null) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index c505c0b..6c0b722 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -322,10 +322,6 @@
}
}
- /**
- * Not implemented yet
- * @hide
- */
@Override
public void setColorFilter(ColorFilter colorFilter) {
// TODO: support color filter
@@ -850,11 +846,11 @@
}
if (vPath.mStrokeColor != 0) {
- if (vPath.mStrokelineJoin != null) {
- mStrokePaint.setStrokeJoin(vPath.mStrokelineJoin);
+ if (vPath.mStrokeLineJoin != null) {
+ mStrokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
}
- if (vPath.mStrokelineCap != null) {
- mStrokePaint.setStrokeCap(vPath.mStrokelineCap);
+ if (vPath.mStrokeLineCap != null) {
+ mStrokePaint.setStrokeCap(vPath.mStrokeLineCap);
}
mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
mStrokePaint.setColor(vPath.mStrokeColor);
@@ -1328,8 +1324,8 @@
boolean mAnimated = false;
boolean mClip = false;
- Paint.Cap mStrokelineCap = null;
- Paint.Join mStrokelineJoin = null;
+ Paint.Cap mStrokeLineCap = null;
+ Paint.Join mStrokeLineJoin = null;
float mStrokeMiterlimit = 4;
private VNode[] mNode = null;
@@ -1386,61 +1382,93 @@
}
}
- public String getID(){
+ public String getID() {
return mId;
}
+ private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
+ switch (id) {
+ case LINECAP_BUTT:
+ return Paint.Cap.BUTT;
+ case LINECAP_ROUND:
+ return Paint.Cap.ROUND;
+ case LINECAP_SQUARE:
+ return Paint.Cap.SQUARE;
+ default:
+ return defValue;
+ }
+ }
+
+ private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
+ switch (id) {
+ case LINEJOIN_MITER:
+ return Paint.Join.MITER;
+ case LINEJOIN_ROUND:
+ return Paint.Join.ROUND;
+ case LINEJOIN_BEVEL:
+ return Paint.Join.BEVEL;
+ default:
+ return defValue;
+ }
+ }
+
public void inflate(Resources r, AttributeSet attrs, Theme theme) {
final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
final int[] themeAttrs = a.extractThemeAttrs();
mThemeAttrs = themeAttrs;
- mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, false);
- mId = a.getString(R.styleable.VectorDrawablePath_name);
- mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+ // NOTE: The set of attributes loaded here MUST match the
+ // set of attributes loaded in applyTheme.
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_clipToPath] == 0) {
+ mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_name] == 0) {
+ mId = a.getString(R.styleable.VectorDrawablePath_name);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pathData] == 0) {
+ mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
+ }
if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fill] == 0) {
- mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_fillOpacity] == 0) {
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_rotation] == 0) {
+ mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, mRotate);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pivotX] == 0) {
+ mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, mPivotX);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_pivotY] == 0) {
+ mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, mPivotY);
}
if (themeAttrs == null
- || themeAttrs[R.styleable.VectorDrawablePath_fillOpacity] == 0) {
- mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
+ || themeAttrs[R.styleable.VectorDrawablePath_strokeLineCap] == 0) {
+ mStrokeLineCap = getStrokeLineCap(
+ a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
}
- mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, 0);
- mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, 0);
- mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, 0);
-
- final int lineCap = a.getInt(R.styleable.VectorDrawablePath_strokeLineCap, 0);
- switch (lineCap) {
- case LINECAP_BUTT:
- mStrokelineCap = Paint.Cap.BUTT;
- break;
- case LINECAP_ROUND:
- mStrokelineCap = Paint.Cap.ROUND;
- break;
- case LINECAP_SQUARE:
- mStrokelineCap = Paint.Cap.SQUARE;
- break;
+ if (themeAttrs == null
+ || themeAttrs[R.styleable.VectorDrawablePath_strokeLineJoin] == 0) {
+ mStrokeLineJoin = getStrokeLineJoin(
+ a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
}
- final int lineJoin = a.getInt(R.styleable.VectorDrawablePath_strokeLineJoin, 0);
- switch (lineJoin) {
- case LINEJOIN_MITER:
- mStrokelineJoin = Paint.Join.MITER;
- break;
- case LINEJOIN_ROUND:
- mStrokelineJoin = Paint.Join.ROUND;
- break;
- case LINEJOIN_BEVEL:
- mStrokelineJoin = Paint.Join.BEVEL;
- break;
+ if (themeAttrs == null
+ || themeAttrs[R.styleable.VectorDrawablePath_strokeMiterLimit] == 0) {
+ mStrokeMiterlimit = a.getFloat(
+ R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
}
- mStrokeMiterlimit = a.getFloat(R.styleable.VectorDrawablePath_strokeMiterLimit,
- mStrokeMiterlimit);
-
if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_stroke] == 0) {
mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
}
@@ -1448,14 +1476,30 @@
if (themeAttrs == null
|| themeAttrs[R.styleable.VectorDrawablePath_strokeOpacity] == 0) {
mStrokeOpacity = a.getFloat(
- R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
+ R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
}
- mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 0);
- mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1);
- mTrimPathOffset = a.getFloat(R.styleable.VectorDrawablePath_trimPathOffset, 0);
- mTrimPathStart = a.getFloat(R.styleable.VectorDrawablePath_trimPathStart, 0);
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_strokeWidth] == 0) {
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
+ }
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawablePath_trimPathEnd] == 0) {
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
+ }
+
+ if (themeAttrs == null
+ || themeAttrs[R.styleable.VectorDrawablePath_trimPathOffset] == 0) {
+ mTrimPathOffset = a.getFloat(
+ R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
+ }
+
+ if (themeAttrs == null
+ || themeAttrs[R.styleable.VectorDrawablePath_trimPathStart] == 0) {
+ mTrimPathStart = a.getFloat(
+ R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
+ }
+
+ // TODO: Consider replacing this with existing state attributes.
final int[] states = {
R.styleable.VectorDrawablePath_state_activated,
R.styleable.VectorDrawablePath_state_checkable,
@@ -1493,22 +1537,39 @@
final TypedArray a = t.resolveAttributes(
mThemeAttrs, R.styleable.VectorDrawablePath, 0, 0);
- if (a.hasValue(R.styleable.VectorDrawablePath_fill)) {
- mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, 0);
+ mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
+
+ if (a.hasValue(R.styleable.VectorDrawablePath_name)) {
+ mId = a.getString(R.styleable.VectorDrawablePath_name);
}
- if (a.hasValue(R.styleable.VectorDrawablePath_fillOpacity)) {
- mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, Float.NaN);
+ if (a.hasValue(R.styleable.VectorDrawablePath_pathData)) {
+ mNode = parsePath(a.getString(R.styleable.VectorDrawablePath_pathData));
}
- if (a.hasValue(R.styleable.VectorDrawablePath_stroke)) {
- mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
- }
+ mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
+ mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
- if (a.hasValue(R.styleable.VectorDrawablePath_strokeOpacity)) {
- mStrokeOpacity = a.getFloat(
- R.styleable.VectorDrawablePath_strokeOpacity, Float.NaN);
- }
+ mRotate = a.getFloat(R.styleable.VectorDrawablePath_rotation, mRotate);
+ mPivotX = a.getFloat(R.styleable.VectorDrawablePath_pivotX, mPivotX);
+ mPivotY = a.getFloat(R.styleable.VectorDrawablePath_pivotY, mPivotY);
+
+ mStrokeLineCap = getStrokeLineCap(a.getInt(
+ R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
+ mStrokeLineJoin = getStrokeLineJoin(a.getInt(
+ R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
+ mStrokeMiterlimit = a.getFloat(
+ R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
+ mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
+ mStrokeOpacity = a.getFloat(
+ R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
+ mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
+
+ mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
+ mTrimPathOffset = a.getFloat(
+ R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
+ mTrimPathStart = a.getFloat(
+ R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
updateColorAlphas();
}
@@ -1630,8 +1691,8 @@
mTrimPathStart = p1.mTrimPathStart;
mTrimPathEnd = p1.mTrimPathEnd;
mTrimPathOffset = p1.mTrimPathOffset;
- mStrokelineCap = p1.mStrokelineCap;
- mStrokelineJoin = p1.mStrokelineJoin;
+ mStrokeLineCap = p1.mStrokeLineCap;
+ mStrokeLineJoin = p1.mStrokeLineJoin;
mStrokeMiterlimit = p1.mStrokeMiterlimit;
mNumberOfStates = p1.mNumberOfStates;
for (int i = 0; i < mNumberOfStates; i++) {
@@ -1668,13 +1729,13 @@
returnPath.mTrimPathOffset = t1 * p1.mTrimPathOffset + t * p2.mTrimPathOffset;
returnPath.mStrokeMiterlimit =
t1 * p1.mStrokeMiterlimit + t * p2.mStrokeMiterlimit;
- returnPath.mStrokelineCap = p1.mStrokelineCap;
- if (returnPath.mStrokelineCap == null) {
- returnPath.mStrokelineCap = p2.mStrokelineCap;
+ returnPath.mStrokeLineCap = p1.mStrokeLineCap;
+ if (returnPath.mStrokeLineCap == null) {
+ returnPath.mStrokeLineCap = p2.mStrokeLineCap;
}
- returnPath.mStrokelineJoin = p1.mStrokelineJoin;
- if (returnPath.mStrokelineJoin == null) {
- returnPath.mStrokelineJoin = p2.mStrokelineJoin;
+ returnPath.mStrokeLineJoin = p1.mStrokeLineJoin;
+ if (returnPath.mStrokeLineJoin == null) {
+ returnPath.mStrokeLineJoin = p2.mStrokeLineJoin;
}
returnPath.mFillRule = p1.mFillRule;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index fa82627..c231f6f 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -490,6 +490,16 @@
task->run();
}
+Layer* CanvasContext::createRenderLayer(int width, int height) {
+ requireGlContext();
+ return LayerRenderer::createRenderLayer(width, height);
+}
+
+Layer* CanvasContext::createTextureLayer() {
+ requireGlContext();
+ return LayerRenderer::createTextureLayer();
+}
+
void CanvasContext::requireGlContext() {
if (mEglSurface != EGL_NO_SURFACE) {
mGlobalContext->makeCurrent(mEglSurface);
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index eb9096d..6f1c37f 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -35,6 +35,7 @@
class DisplayListData;
class OpenGLRenderer;
class Rect;
+class Layer;
namespace renderthread {
@@ -76,6 +77,9 @@
void runWithGlContext(RenderTask* task);
+ Layer* createRenderLayer(int width, int height);
+ Layer* createTextureLayer();
+
private:
void setSurface(EGLNativeWindowType window);
void swapBuffers();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 489dc90..e817e61 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -202,10 +202,9 @@
postAndWait(task);
}
-CREATE_BRIDGE2(createDisplayListLayer, int width, int height) {
- Layer* layer = LayerRenderer::createRenderLayer(args->width, args->height);
+CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) {
+ Layer* layer = args->context->createRenderLayer(args->width, args->height);
if (!layer) return 0;
-
return new DeferredLayerUpdater(layer);
}
@@ -213,20 +212,22 @@
SETUP_TASK(createDisplayListLayer);
args->width = width;
args->height = height;
+ args->context = mContext;
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
mDrawFrameTask.addLayer(layer);
return layer;
}
-CREATE_BRIDGE0(createTextureLayer) {
- Layer* layer = LayerRenderer::createTextureLayer();
+CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
+ Layer* layer = args->context->createTextureLayer();
if (!layer) return 0;
return new DeferredLayerUpdater(layer);
}
DeferredLayerUpdater* RenderProxy::createTextureLayer() {
SETUP_TASK(createTextureLayer);
+ args->context = mContext;
void* retval = postAndWait(task);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval);
mDrawFrameTask.addLayer(layer);
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index fcd425e..716418c 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -386,11 +386,12 @@
dataSize = buffer->stride * buffer->height;
break;
case HAL_PIXEL_FORMAT_Y16:
+ bytesPerPixel = 2;
// Single plane, 16bpp, strides are specified in pixels, not in bytes
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
pData = buffer->data;
- dataSize = buffer->stride * buffer->height * 2;
+ dataSize = buffer->stride * buffer->height * bytesPerPixel;
break;
case HAL_PIXEL_FORMAT_BLOB:
// Used for JPEG data, height must be 1, width == size, single plane.
@@ -402,9 +403,10 @@
break;
case HAL_PIXEL_FORMAT_RAW_SENSOR:
// Single plane 16bpp bayer data.
+ bytesPerPixel = 2;
ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
pData = buffer->data;
- dataSize = buffer->width * 2 * buffer->height;
+ dataSize = buffer->stride * buffer->height * bytesPerPixel;
break;
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_RGBX_8888:
diff --git a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
index 834cc2c..e6d7c93 100644
--- a/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
+++ b/packages/SystemUI/res/layout/status_bar_toggle_slider.xml
@@ -29,7 +29,7 @@
android:layout_alignParentBottom="true"
android:button="@null"
/>
- <SeekBar
+ <com.android.systemui.settings.ToggleSeekBar
android:id="@+id/slider"
android:layout_width="0dp"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java
new file mode 100644
index 0000000..a0a5561
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSeekBar.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.settings;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.SeekBar;
+
+public class ToggleSeekBar extends SeekBar {
+ public ToggleSeekBar(Context context) {
+ super(context);
+ }
+
+ public ToggleSeekBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ToggleSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (!isEnabled()) {
+ setEnabled(true);
+ }
+
+ return super.onTouchEvent(event);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index c99f691..7d38058 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -19,20 +19,18 @@
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.android.systemui.R;
-public class ToggleSlider extends RelativeLayout
- implements CompoundButton.OnCheckedChangeListener, SeekBar.OnSeekBarChangeListener {
- private static final String TAG = "StatusBar.ToggleSlider";
-
+public class ToggleSlider extends RelativeLayout {
public interface Listener {
public void onInit(ToggleSlider v);
public void onChanged(ToggleSlider v, boolean tracking, boolean checked, int value);
@@ -55,20 +53,21 @@
public ToggleSlider(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+
View.inflate(context, R.layout.status_bar_toggle_slider, this);
final Resources res = context.getResources();
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ToggleSlider,
- defStyle, 0);
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.ToggleSlider, defStyle, 0);
- mToggle = (CompoundButton)findViewById(R.id.toggle);
- mToggle.setOnCheckedChangeListener(this);
- mToggle.setBackgroundDrawable(res.getDrawable(R.drawable.status_bar_toggle_button));
+ mToggle = (CompoundButton) findViewById(R.id.toggle);
+ mToggle.setOnCheckedChangeListener(mCheckListener);
+ mToggle.setBackground(res.getDrawable(R.drawable.status_bar_toggle_button));
- mSlider = (SeekBar)findViewById(R.id.slider);
- mSlider.setOnSeekBarChangeListener(this);
+ mSlider = (SeekBar) findViewById(R.id.slider);
+ mSlider.setOnSeekBarChangeListener(mSeekListener);
- mLabel = (TextView)findViewById(R.id.label);
+ mLabel = (TextView) findViewById(R.id.label);
mLabel.setText(a.getString(R.styleable.ToggleSlider_text));
a.recycle();
@@ -82,35 +81,6 @@
}
}
- public void onCheckedChanged(CompoundButton toggle, boolean checked) {
- mSlider.setEnabled(checked);
-
- if (mListener != null) {
- mListener.onChanged(this, mTracking, checked, mSlider.getProgress());
- }
- }
-
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (mListener != null) {
- mListener.onChanged(this, mTracking, mToggle.isChecked(), progress);
- }
- }
-
- public void onStartTrackingTouch(SeekBar seekBar) {
- mTracking = true;
- if (mListener != null) {
- mListener.onChanged(this, mTracking, mToggle.isChecked(), mSlider.getProgress());
- }
- mToggle.setChecked(false);
- }
-
- public void onStopTrackingTouch(SeekBar seekBar) {
- mTracking = false;
- if (mListener != null) {
- mListener.onChanged(this, mTracking, mToggle.isChecked(), mSlider.getProgress());
- }
- }
-
public void setOnChangedListener(Listener l) {
mListener = l;
}
@@ -130,5 +100,49 @@
public void setValue(int value) {
mSlider.setProgress(value);
}
+
+ private final OnCheckedChangeListener mCheckListener = new OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton toggle, boolean checked) {
+ mSlider.setEnabled(!checked);
+
+ if (mListener != null) {
+ mListener.onChanged(
+ ToggleSlider.this, mTracking, checked, mSlider.getProgress());
+ }
+ }
+ };
+
+ private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (mListener != null) {
+ mListener.onChanged(
+ ToggleSlider.this, mTracking, mToggle.isChecked(), progress);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mTracking = true;
+
+ if (mListener != null) {
+ mListener.onChanged(
+ ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress());
+ }
+
+ mToggle.setChecked(false);
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mTracking = false;
+
+ if (mListener != null) {
+ mListener.onChanged(
+ ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress());
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 04b7f53..e2d6c5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -31,7 +31,6 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.ViewParent;
import android.widget.OverScroller;
import com.android.systemui.ExpandHelper;
@@ -710,6 +709,12 @@
super.onInterceptTouchEvent(ev);
}
+ @Override
+ protected void onViewRemoved(View child) {
+ super.onViewRemoved(child);
+ mCurrentStackScrollState.removeViewStateForView(child);
+ }
+
private boolean onInterceptTouchEventScroll(MotionEvent ev) {
/*
* This method JUST determines whether we want to intercept the motion.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 881730a..67a1735 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -72,6 +72,10 @@
return mStateMap.get(requestedView);
}
+ public void removeViewStateForView(View child) {
+ mStateMap.remove(child);
+ }
+
/**
* Apply the properties saved in {@link #mStateMap} to the children of the {@link #mHostView}.
* The properties are only applied if they effectively changed.
diff --git a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
index 39f2441..132579d 100644
--- a/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
+++ b/services/backup/java/com/android/server/backup/PackageManagerBackupAgent.java
@@ -189,7 +189,7 @@
if (home != null) {
outputBufferStream.writeUTF(home.flattenToString());
outputBufferStream.writeLong(homeVersion);
- outputBufferStream.writeUTF(homeInstaller);
+ outputBufferStream.writeUTF(homeInstaller != null ? homeInstaller : "" );
writeSignatureArray(outputBufferStream, homeSigs);
writeEntity(data, DEFAULT_HOME_KEY, outputBuffer.toByteArray());
} else {
diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
index 06effe2..28c5f33 100644
--- a/tests/VectorDrawableTest/AndroidManifest.xml
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -17,7 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.test.dynamic" >
- <uses-sdk android:minSdkVersion="11" />
+ <uses-sdk android:minSdkVersion="20" />
<application
android:hardwareAccelerated="true"
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 538993f..6ca1aa7 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -17,8 +17,8 @@
android:trigger="state_checked" android:versionCode="1" >
<size
- android:height="64dp"
- android:width="64dp" />
+ android:height="48dp"
+ android:width="48dp" />
<viewport
android:viewportHeight="480"
@@ -28,42 +28,47 @@
<path
android:name="check"
android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
- android:fill="#ffff00ff"
- android:stroke="#FF00FF00"
- android:strokeWidth="5" />
+ android:fill="?android:attr/colorControlActivated" />
</group>
<group>
<path
android:name="box1"
android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
- android:fill="#ffffffff"
- android:stroke="#FF00FF00"
- android:strokeWidth="5" />
+ android:fill="?android:attr/colorControlActivated"
+ android:stroke="?android:attr/colorControlActivated"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
</group>
<group>
<path
android:name="box2"
android:pathData="m127,171l37,38l33,-31l-37,-40l-1,3l-2,0l-30,30z"
- android:fill="#ff000000"
android:rotation="46.757"
android:pivotX="162"
android:pivotY="173.5"
- android:stroke="#FF00FF00"
- android:strokeWidth="5" />
+ android:fill="?attr/android:colorControlNormal"
+ android:stroke="?attr/android:colorControlNormal"
+ android:strokeWidth="3"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
</group>
<group>
<path
android:name="box3"
android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
- android:stroke="#FF000000"
- android:strokeWidth="4" />
+ android:stroke="?attr/android:colorControlNormal"
+ android:strokeWidth="10"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
</group>
<group>
<path
android:name="box4"
android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
- android:stroke="#FF000000"
- android:strokeWidth="30" />
+ android:stroke="?attr/android:colorControlNormal"
+ android:strokeWidth="30"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round" />
</group>
<animation
diff --git a/tools/layoutlib/create/.classpath b/tools/layoutlib/create/.classpath
index cd8bb0d..25c3b3e 100644
--- a/tools/layoutlib/create/.classpath
+++ b/tools/layoutlib/create/.classpath
@@ -4,6 +4,6 @@
<classpathentry excluding="mock_data/" kind="src" path="tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
- <classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_PLAT/prebuilts/tools/common/asm-tools/src-4.0.zip"/>
+ <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/asm/asm-4.0.jar" sourcepath="/ANDROID_PLAT_SRC/prebuilts/misc/common/asm/src.zip"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index ef2b185..6e0a300 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -4,46 +4,45 @@
- Description -
---------------
-Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor
-to perform layout.
+Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor to perform
+layout.
- Usage -
---------
- ./layoutlib_create path/to/android.jar destination.jar
+ ./layoutlib_create destination.jar path/to/android1.jar path/to/android2.jar
- Design Overview -
-------------------
-Layoutlib_create uses the "android.jar" containing all the Java code used by Android
-as generated by the Android build, right before the classes are converted to a DEX format.
+Layoutlib_create uses a few jars from the framework containing the Java code used by Android as
+generated by the Android build, right before the classes are converted to a DEX format.
-The Android JAR can't be used directly in Eclipse:
-- it contains references to native code (which we want to avoid in Eclipse),
-- some classes need to be overridden, for example all the drawing code that is
- replaced by Java 2D calls in Eclipse.
-- some of the classes that need to be changed are final and/or we need access
- to their private internal state.
+These jars can't be used directly in Eclipse as:
+- they contains references to native code (which we want to avoid in Eclipse),
+- some classes need to be overridden, for example all the drawing code that is replaced by Java 2D
+ calls in Eclipse.
+- some of the classes that need to be changed are final and/or we need access to their private
+ internal state.
Consequently this tool:
- parses the input JAR,
- modifies some of the classes directly using some bytecode manipulation,
- filters some packages and removes those we don't want in the output JAR,
- injects some new classes,
-- generates a modified JAR file that is suitable for the Android plugin
- for Eclipse to perform rendering.
+- generates a modified JAR file that is suitable for the Android plugin for Eclipse to perform
+ rendering.
The ASM library is used to do the bytecode modification using its visitor pattern API.
-The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the
-configuration is done in the main() method and the CreateInfo structure is expected to
-change with the Android platform as new classes are added, changed or removed.
+The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the configuration
+is done in the main() method and the CreateInfo structure is expected to change with the Android
+platform as new classes are added, changed or removed.
-The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the
-platform, that provides all the necessary missing implementation for rendering graphics
-in Eclipse.
+The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the platform, that
+provides all the necessary missing implementation for rendering graphics in Eclipse.
@@ -58,97 +57,96 @@
- Analyzer
----------
-The goal of the analyzer is to create a graph of all the classes from the input JAR
-with their dependencies and then only keep the ones we want.
+The goal of the analyzer is to create a graph of all the classes from the input JAR with their
+dependencies and then only keep the ones we want.
-To do that, the analyzer is created with a list of base classes to keep -- everything
-that derives from these is kept. Currently the one such class is android.view.View:
-since we want to render layouts, anything that is sort of a view needs to be kept.
+To do that, the analyzer is created with a list of base classes to keep -- everything that derives
+from these is kept. Currently the one such class is android.view.View: since we want to render
+layouts, anything that is sort of a view needs to be kept.
-The analyzer is also given a list of class names to keep in the output.
-This is done using shell-like glob patterns that filter on the fully-qualified
-class names, for example "android.*.R**" ("*" does not matches dots whilst "**" does,
-and "." and "$" are interpreted as-is).
-In practice we almost but not quite request the inclusion of full packages.
+The analyzer is also given a list of class names to keep in the output. This is done using
+shell-like glob patterns that filter on the fully-qualified class names, for example "android.*.R**"
+("*" does not matches dots whilst "**" does, and "." and "$" are interpreted as-is). In practice we
+almost but not quite request the inclusion of full packages.
-The analyzer is also given a list of classes to exclude. A fake implementation of these
-classes is injected by the Generator.
+The analyzer is also given a list of classes to exclude. A fake implementation of these classes is
+injected by the Generator.
-With this information, the analyzer parses the input zip to find all the classes.
-All classes deriving from the requested bases classes are kept.
-All classes which name matched the glob pattern are kept.
-The analysis then finds all the dependencies of the classes that are to be kept
-using an ASM visitor on the class, the field types, the method types and annotations types.
-Classes that belong to the current JRE are excluded.
+With this information, the analyzer parses the input zip to find all the classes. All classes
+deriving from the requested bases classes are kept. All classes whose name match the glob pattern
+are kept. The analysis then finds all the dependencies of the classes that are to be kept using an
+ASM visitor on the class, the field types, the method types and annotations types. Classes that
+belong to the current JRE are excluded.
-The output of the analyzer is a set of ASM ClassReader instances which are then
-fed to the generator.
+The output of the analyzer is a set of ASM ClassReader instances which are then fed to the
+generator.
- Generator
-----------
-The generator is constructed from a CreateInfo struct that acts as a config file
-and lists:
-- the classes to inject in the output JAR -- these classes are directly implemented
- in layoutlib_create and will be used to interface with the renderer in Eclipse.
+The generator is constructed from a CreateInfo struct that acts as a config file and lists:
+- the classes to inject in the output JAR -- these classes are directly implemented in
+ layoutlib_create and will be used to interface with the renderer in Eclipse.
- specific methods to override (see method stubs details below).
- specific methods for which to delegate calls.
- specific methods to remove based on their return type.
- specific classes to rename.
- specific classes to refactor.
-Each of these are specific strategies we use to be able to modify the Android code
-to fit within the Eclipse renderer. These strategies are explained beow.
+Each of these are specific strategies we use to be able to modify the Android code to fit within the
+Eclipse renderer. These strategies are explained beow.
-The core method of the generator is transform(): it takes an input ASM ClassReader
-and modifies it to produce a byte array suitable for the final JAR file.
+The core method of the generator is transform(): it takes an input ASM ClassReader and modifies it
+to produce a byte array suitable for the final JAR file.
The first step of the transformation is to implement the method delegates.
-The TransformClassAdapter is then used to process the potentially renamed class.
-All protected or private classes are market as public.
-All classes are made non-final.
-Interfaces are left as-is.
+The TransformClassAdapter is then used to process the potentially renamed class. All protected or
+private classes are market as public. All classes are made non-final. Interfaces are left as-is.
-If a method has a return type that must be erased, the whole method is skipped.
-Methods are also changed from protected/private to public.
-The code of the methods is then kept as-is, except for native methods which are
-replaced by a stub. Methods that are to be overridden are also replaced by a stub.
+If a method has a return type that must be erased, the whole method is skipped. Methods are also
+changed from protected/private to public. The code of the methods is then kept as-is, except for
+native methods which are replaced by a stub. Methods that are to be overridden are also replaced by
+a stub.
Finally fields are also visited and changed from protected/private to public.
-The next step of the transformation is changing the name of the class in case
-we requested the class to be renamed. This uses the RenameClassAdapter to also rename
-all inner classes and references in methods and types. Note that other classes are
-not transformed and keep referencing the original name.
+The next step of the transformation is changing the name of the class in case we requested the class
+to be renamed. This uses the RenameClassAdapter to also rename all inner classes and references in
+methods and types. Note that other classes are not transformed and keep referencing the original
+name.
-The class is then fed to RefactorClassAdapter which is like RenameClassAdapter but
-updates the references in all classes. This is used to update the references of classes
-in the java package that were added in the Dalvik VM but are not a part of the standard
-JVM. The existing classes are modified to update all references to these non-standard
-classes. An alternate implementation of these (com.android.tools.layoutlib.java.*) is
-injected.
+The class is then fed to RefactorClassAdapter which is like RenameClassAdapter but updates the
+references in all classes. This is used to update the references of classes in the java package that
+were added in the Dalvik VM but are not a part of the standard JVM. The existing classes are
+modified to update all references to these non-standard classes. An alternate implementation of
+these (com.android.tools.layoutlib.java.*) is injected.
-The ClassAdapters are chained together to achieve the desired output. (Look at section
-2.2.7 Transformation chains in the asm user guide, link in the References.) The order of
-execution of these is:
+RenameClassAdapter and RefactorClassAdapter both inherit from AbstractClassAdapter which changes the
+class version (version of the JDK used to compile the class) to 50 (corresponding to Java 6), if the
+class was originally compiled with Java 7 (version 51). This is because we don't currently generate
+the StackMapTable correctly and Java 7 VM enforces that classes with version greater than 51 have
+valid StackMapTable. As a side benefit of this, we can continue to support Java 6 because Java 7 on
+Mac has horrible font rendering support.
+
+The ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7
+Transformation chains in the asm user guide, link in the References.) The order of execution of
+these is:
ClassReader -> [DelegateClassAdapter] -> TransformClassAdapter -> [RenameClassAdapter] ->
RefactorClassAdapter -> ClassWriter
- Method stubs
--------------
-As indicated above, all native and overridden methods are replaced by a stub.
-We don't have the code to replace with in layoutlib_create.
-Instead the StubMethodAdapter replaces the code of the method by a call to
-OverrideMethod.invokeX(). When using the final JAR, the bridge can register
+As indicated above, all native and overridden methods are replaced by a stub. We don't have the
+code to replace with in layoutlib_create. Instead the StubMethodAdapter replaces the code of the
+method by a call to OverrideMethod.invokeX(). When using the final JAR, the bridge can register
listeners from these overridden method calls based on the method signatures.
-The listeners are currently pretty basic: we only pass the signature of the
-method being called, its caller object and a flag indicating whether the
-method was native. We do not currently provide the parameters. The listener
-can however specify the return value of the overridden method.
+The listeners are currently pretty basic: we only pass the signature of the method being called, its
+caller object and a flag indicating whether the method was native. We do not currently provide the
+parameters. The listener can however specify the return value of the overridden method.
This strategy is now obsolete and replaced by the method delegates.
@@ -156,97 +154,89 @@
- Strategies
------------
-We currently have 6 strategies to deal with overriding the rendering code
-and make it run in Eclipse. Most of these strategies are implemented hand-in-hand
-by the bridge (which runs in Eclipse) and the generator.
+We currently have 6 strategies to deal with overriding the rendering code and make it run in
+Eclipse. Most of these strategies are implemented hand-in-hand by the bridge (which runs in Eclipse)
+and the generator.
1- Class Injection
This is the easiest: we currently inject the following classes:
-- OverrideMethod and its associated MethodListener and MethodAdapter are used
- to intercept calls to some specific methods that are stubbed out and change
- their return value.
-- CreateInfo class, which configured the generator. Not used yet, but could
- in theory help us track what the generator changed.
-- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new
- classes are injected. The implementation for these classes has been taken from
- Android's libcore (platform/libcore/luni/src/main/java/java/...).
-- Charsets, IntegralToString and UnsafeByteSequence are not part of the standard JAVA VM.
- They are added to the Dalvik VM for performance reasons. An implementation that is very
- close to the original (which is at platform/libcore/luni/src/main/java/...) is injected.
- Since these classees were in part of the java package, where we can't inject classes,
- all references to these have been updated (See strategy 4- Refactoring Classes).
+- OverrideMethod and its associated MethodListener and MethodAdapter are used to intercept calls to
+ some specific methods that are stubbed out and change their return value.
+- CreateInfo class, which configured the generator. Not used yet, but could in theory help us track
+ what the generator changed.
+- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new classes are
+ injected. The implementation for these classes has been taken from Android's libcore
+ (platform/libcore/luni/src/main/java/java/...).
+- Charsets, IntegralToString and UnsafeByteSequence are not part of the standard JAVA VM. They are
+ added to the Dalvik VM for performance reasons. An implementation that is very close to the
+ original (which is at platform/libcore/luni/src/main/java/...) is injected. Since these classees
+ were in part of the java package, where we can't inject classes, all references to these have been
+ updated (See strategy 4- Refactoring Classes).
2- Overriding methods
-As explained earlier, the creator doesn't have any replacement code for
-methods to override. Instead it removes the original code and replaces it
-by a call to a specific OveriddeMethod.invokeX(). The bridge then registers
-a listener on the method signature and can provide an implementation.
+As explained earlier, the creator doesn't have any replacement code for methods to override. Instead
+it removes the original code and replaces it by a call to a specific OveriddeMethod.invokeX(). The
+bridge then registers a listener on the method signature and can provide an implementation.
-This strategy is now obsolete and replaced by the method delegates.
-See strategy 5 below.
+This strategy is now obsolete and replaced by the method delegates (See strategy 6- Method
+Delegates).
3- Renaming classes
-This simply changes the name of a class in its definition, as well as all its
-references in internal inner classes and methods.
-Calls from other classes are not modified -- they keep referencing the original
-class name. This allows the bridge to literally replace an implementation.
+This simply changes the name of a class in its definition, as well as all its references in internal
+inner classes and methods. Calls from other classes are not modified -- they keep referencing the
+original class name. This allows the bridge to literally replace an implementation.
-An example will make this easier: android.graphics.Paint is the main drawing
-class that we need to replace. To do so, the generator renames Paint to _original_Paint.
-Later the bridge provides its own replacement version of Paint which will be used
-by the rest of the Android stack. The replacement version of Paint can still use
-(either by inheritance or delegation) all the original non-native code of _original_Paint
-if it so desires.
+An example will make this easier: android.graphics.Paint is the main drawing class that we need to
+replace. To do so, the generator renames Paint to _original_Paint. Later the bridge provides its own
+replacement version of Paint which will be used by the rest of the Android stack. The replacement
+version of Paint can still use (either by inheritance or delegation) all the original non-native
+code of _original_Paint if it so desires.
-Some of the Android classes are basically wrappers over native objects and since
-we don't have the native code in Eclipse, we need to provide a full alternate
-implementation. Sub-classing doesn't work as some native methods are static and
-we don't control object creation.
+Some of the Android classes are basically wrappers over native objects and since we don't have the
+native code in Eclipse, we need to provide a full alternate implementation. Sub-classing doesn't
+work as some native methods are static and we don't control object creation.
This won't rename/replace the inner static methods of a given class.
4- Refactoring classes
-This is very similar to the Renaming classes except that it also updates the reference in
-all classes. This is done for classes which are added to the Dalvik VM for performance
-reasons but are not present in the Standard Java VM. An implementation for these classes
-is also injected.
+This is very similar to the Renaming classes except that it also updates the reference in all
+classes. This is done for classes which are added to the Dalvik VM for performance reasons but are
+not present in the Standard Java VM. An implementation for these classes is also injected.
5- Method erasure based on return type
-This is mostly an implementation detail of the bridge: in the Paint class
-mentioned above, some inner static classes are used to pass around
-attributes (e.g. FontMetrics, or the Style enum) and all the original implementation
-is native.
+This is mostly an implementation detail of the bridge: in the Paint class mentioned above, some
+inner static classes are used to pass around attributes (e.g. FontMetrics, or the Style enum) and
+all the original implementation is native.
-In this case we have a strategy that tells the generator that anything returning, for
-example, the inner class Paint$Style in the Paint class should be discarded and the
-bridge will provide its own implementation.
+In this case we have a strategy that tells the generator that anything returning, for example, the
+inner class Paint$Style in the Paint class should be discarded and the bridge will provide its own
+implementation.
6- Method Delegates
-This strategy is used to override method implementations.
-Given a method SomeClass.MethodName(), 1 or 2 methods are generated:
-a- A copy of the original method named SomeClass.MethodName_Original().
- The content is the original method as-is from the reader.
- This step is omitted if the method is native, since it has no Java implementation.
-b- A brand new implementation of SomeClass.MethodName() which calls to a
- non-existing static method named SomeClass_Delegate.MethodName().
- The implementation of this 'delegate' method is done in layoutlib_brigde.
+This strategy is used to override method implementations. Given a method SomeClass.MethodName(), 1
+or 2 methods are generated:
+a- A copy of the original method named SomeClass.MethodName_Original(). The content is the original
+method as-is from the reader. This step is omitted if the method is native, since it has no Java
+implementation.
+b- A brand new implementation of SomeClass.MethodName() which calls to a non-existing static method
+named SomeClass_Delegate.MethodName(). The implementation of this 'delegate' method is done in
+layoutlib_brigde.
-The delegate method is a static method.
-If the original method is non-static, the delegate method receives the original 'this'
-as its first argument. If the original method is an inner non-static method, it also
-receives the inner 'this' as the second argument.
+The delegate method is a static method. If the original method is non-static, the delegate method
+receives the original 'this' as its first argument. If the original method is an inner non-static
+method, it also receives the inner 'this' as the second argument.
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
index b2caa25..323a791 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
@@ -177,6 +177,17 @@
}
}
+ /* Java 7 verifies the StackMapTable of a class if its version number is greater than 50.0.
+ * However, the check is disabled if the class version number is 50.0 or less. Generation
+ * of the StackMapTable requires a rewrite using the tree API of ASM. As a workaround,
+ * we rewrite the version number of the class to be 50.0
+ *
+ * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6693236
+ */
+ if (version > 50) {
+ version = 50;
+ }
+
super.visit(version, access, name, signature, superName, interfaces);
}