diff options
Diffstat (limited to 'tools/layoutlib')
43 files changed, 678 insertions, 510 deletions
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath index 2e4274d..aef3efa 100644 --- a/tools/layoutlib/bridge/.classpath +++ b/tools/layoutlib/bridge/.classpath @@ -1,12 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry excluding="org/kxml2/io/" kind="src" path="src"/> + <classpathentry kind="src" path="tests/src"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar"/> + <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar" sourcepath="/ANDROID_SRC/tools/base/layoutlib-api/src/main"/> <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/> <classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/> <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/> <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/> <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/icu4j/icu4j.jar"/> + <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/> <classpathentry kind="output" path="bin"/> </classpath> diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java index 224eac6..4603b63 100644 --- a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java +++ b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java @@ -48,6 +48,20 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; } @LayoutlibDelegate + /*package*/ static long nGetMultipleIntMethod(Class<?> targetClass, String methodName, + int numParams) { + // TODO: return the right thing. + return 0; + } + + @LayoutlibDelegate + /*package*/ static long nGetMultipleFloatMethod(Class<?> targetClass, String methodName, + int numParams) { + // TODO: return the right thing. + return 0; + } + + @LayoutlibDelegate /*package*/ static void nCallIntMethod(Object target, long methodID, int arg) { // do nothing } @@ -56,4 +70,40 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; /*package*/ static void nCallFloatMethod(Object target, long methodID, float arg) { // do nothing } + + @LayoutlibDelegate + /*package*/ static void nCallTwoIntMethod(Object target, long methodID, int arg1, + int arg2) { + // do nothing + } + + @LayoutlibDelegate + /*package*/ static void nCallFourIntMethod(Object target, long methodID, int arg1, + int arg2, int arg3, int arg4) { + // do nothing + } + + @LayoutlibDelegate + /*package*/ static void nCallMultipleIntMethod(Object target, long methodID, + int[] args) { + // do nothing + } + + @LayoutlibDelegate + /*package*/ static void nCallTwoFloatMethod(Object target, long methodID, float arg1, + float arg2) { + // do nothing + } + + @LayoutlibDelegate + /*package*/ static void nCallFourFloatMethod(Object target, long methodID, float arg1, + float arg2, float arg3, float arg4) { + // do nothing + } + + @LayoutlibDelegate + /*package*/ static void nCallMultipleFloatMethod(Object target, long methodID, + float[] args) { + // do nothing + } } diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java index 5c2b793..914a359 100644 --- a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java +++ b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java @@ -40,9 +40,6 @@ public class AssetManager_Delegate { @LayoutlibDelegate /*package*/ static void applyThemeStyle(long theme, int styleRes, boolean force) { - Resources_Theme_Delegate delegate = Resources_Theme_Delegate.getDelegateManager() - .getDelegate(theme); - delegate.mThemeResId = styleRes; - delegate.force = force; + Resources_Theme_Delegate.getDelegateManager().getDelegate(theme).force = force; } } diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java index 8794452..dd573be 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java @@ -51,6 +51,7 @@ public final class BridgeResources extends Resources { private BridgeContext mContext; private IProjectCallback mProjectCallback; private boolean[] mPlatformResourceFlag = new boolean[1]; + private TypedValue mTmpValue = new TypedValue(); /** * Simpler wrapper around FileInputStream. This is used when the input stream represent @@ -154,6 +155,11 @@ public final class BridgeResources extends Resources { @Override public Drawable getDrawable(int id) throws NotFoundException { + return getDrawable(id, null); + } + + @Override + public Drawable getDrawable(int id, Theme theme) { Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag); if (value != null) { diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java index 446d139..cc621c4 100644 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java @@ -52,13 +52,13 @@ public final class BridgeTypedArray extends TypedArray { private final BridgeContext mContext; private final boolean mPlatformFile; - private ResourceValue[] mResourceData; - private String[] mNames; - private boolean[] mIsFramework; + private final ResourceValue[] mResourceData; + private final String[] mNames; + private final boolean[] mIsFramework; public BridgeTypedArray(BridgeResources resources, BridgeContext context, int len, boolean platformFile) { - super(null, null, null, 0); + super(resources, null, null, 0); mBridgeResources = resources; mContext = context; mPlatformFile = platformFile; @@ -81,8 +81,8 @@ public final class BridgeTypedArray extends TypedArray { } /** - * Seals the array after all calls to {@link #bridgeSetValue(int, String, ResourceValue)} have - * been done. + * Seals the array after all calls to + * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done. * <p/>This allows to compute the list of non default values, permitting * {@link #getIndexCount()} to return the proper value. */ @@ -252,7 +252,7 @@ public final class BridgeTypedArray extends TypedArray { for (String keyword : keywords) { Integer i = map.get(keyword.trim()); if (i != null) { - result |= i.intValue(); + result |= i; } else { Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, String.format( @@ -731,7 +731,7 @@ public final class BridgeTypedArray extends TypedArray { } // not a direct id valid reference? resolve it - Integer idValue = null; + Integer idValue; if (resValue.isFramework()) { idValue = Bridge.getResourceId(resValue.getResourceType(), @@ -742,7 +742,7 @@ public final class BridgeTypedArray extends TypedArray { } if (idValue != null) { - return idValue.intValue(); + return idValue; } Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE, @@ -753,6 +753,12 @@ public final class BridgeTypedArray extends TypedArray { return defValue; } + @Override + public int getThemeAttributeId(int index, int defValue) { + // TODO: Get the right Theme Attribute ID to enable caching of the drawables. + return defValue; + } + /** * Retrieve the Drawable for the attribute at <var>index</var>. This * gets the resource ID of the selected attribute, and uses @@ -854,6 +860,7 @@ public final class BridgeTypedArray extends TypedArray { */ @Override public boolean hasValue(int index) { + //noinspection SimplifiableIfStatement if (index < 0 || index >= mResourceData.length) { return false; } diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java new file mode 100644 index 0000000..112250d --- /dev/null +++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java @@ -0,0 +1,37 @@ +/* + * 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 android.content.res; + +import java.util.Locale; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; +import com.ibm.icu.util.ULocale; + +/** + * Delegate used to provide new implementation of a select few methods of {@link Resources} + * + * Through the layoutlib_create tool, the original methods of Resources have been replaced + * by calls to methods of the same name in this delegate class. + * + */ +public class Resources_Delegate { + + @LayoutlibDelegate + /*package*/ static String localeToLanguageTag(Resources res, Locale locale) { + return ULocale.forLocale(locale).toLanguageTag(); + } +} diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java index b89d15f..31d1594 100644 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java +++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java @@ -39,8 +39,6 @@ import android.util.TypedValue; */ public class Resources_Theme_Delegate { - // Resource identifier for the theme. - int mThemeResId; // Whether to use the Theme.mThemeResId as primary theme. boolean force; @@ -103,7 +101,7 @@ public class Resources_Theme_Delegate { private static boolean setupResources(Theme thisTheme) { Resources_Theme_Delegate themeDelegate = sManager.getDelegate(thisTheme.getNativeTheme()); - StyleResourceValue style = resolveStyle(themeDelegate.mThemeResId); + StyleResourceValue style = resolveStyle(thisTheme.getAppliedStyleResId()); if (style != null) { RenderSessionImpl.getCurrentContext().getRenderResources() .applyStyle(style, themeDelegate.force); diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index 73d274c..56c0de9 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -71,7 +71,7 @@ public final class Canvas_Delegate { * Returns the native delegate associated to a given {@link Canvas} object. */ public static Canvas_Delegate getDelegate(Canvas canvas) { - return sManager.getDelegate(canvas.mNativeCanvas); + return sManager.getDelegate(canvas.getNativeCanvas()); } /** @@ -102,7 +102,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static boolean isOpaque(Canvas thisCanvas) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return false; } @@ -113,7 +113,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static int getWidth(Canvas thisCanvas) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return 0; } @@ -124,7 +124,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static int getHeight(Canvas thisCanvas) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return 0; } @@ -135,7 +135,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void translate(Canvas thisCanvas, float dx, float dy) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return; } @@ -146,7 +146,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void rotate(Canvas thisCanvas, float degrees) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return; } @@ -157,7 +157,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void scale(Canvas thisCanvas, float sx, float sy) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return; } @@ -168,7 +168,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void skew(Canvas thisCanvas, float kx, float ky) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return; } @@ -204,7 +204,7 @@ public final class Canvas_Delegate { /*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right, float bottom) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return false; } @@ -227,7 +227,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static int save(Canvas thisCanvas, int saveFlags) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return 0; } @@ -238,7 +238,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void restore(Canvas thisCanvas) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return; } @@ -249,7 +249,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static int getSaveCount(Canvas thisCanvas) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return 0; } @@ -260,7 +260,7 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) { // get the delegate from the native int. - Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas); + Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas()); if (canvasDelegate == null) { return; } @@ -287,7 +287,7 @@ public final class Canvas_Delegate { /*package*/ static void drawLines(Canvas thisCanvas, final float[] pts, final int offset, final int count, Paint paint) { - draw(thisCanvas.mNativeCanvas, paint.mNativePaint, false /*compositeOnly*/, + draw(thisCanvas.getNativeCanvas(), paint.mNativePaint, false /*compositeOnly*/, false /*forceSrcMode*/, new GcSnapshot.Drawable() { @Override public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) { @@ -344,7 +344,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static long native_saveLayer(long nativeCanvas, RectF bounds, + /*package*/ static int native_saveLayer(long nativeCanvas, RectF bounds, long paint, int layerFlags) { // get the delegate from the native int. Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas); @@ -361,7 +361,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static long native_saveLayer(long nativeCanvas, float l, + /*package*/ static int native_saveLayer(long nativeCanvas, float l, float t, float r, float b, long paint, int layerFlags) { // get the delegate from the native int. @@ -380,7 +380,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static long native_saveLayerAlpha(long nativeCanvas, + /*package*/ static int native_saveLayerAlpha(long nativeCanvas, RectF bounds, int alpha, int layerFlags) { // get the delegate from the native int. @@ -393,7 +393,7 @@ public final class Canvas_Delegate { } @LayoutlibDelegate - /*package*/ static long native_saveLayerAlpha(long nativeCanvas, float l, + /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l, float t, float r, float b, int alpha, int layerFlags) { // get the delegate from the native int. @@ -757,7 +757,8 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void native_drawRoundRect(long nativeCanvas, - final RectF rect, final float rx, final float ry, long paint) { + final float left, final float top, final float right, final float bottom, + final float rx, final float ry, long paint) { draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, new GcSnapshot.Drawable() { @@ -769,16 +770,16 @@ public final class Canvas_Delegate { if (style == Paint.Style.FILL.nativeInt || style == Paint.Style.FILL_AND_STROKE.nativeInt) { graphics.fillRoundRect( - (int)rect.left, (int)rect.top, - (int)rect.width(), (int)rect.height(), + (int)left, (int)top, + (int)(right - left), (int)(bottom - top), (int)rx, (int)ry); } if (style == Paint.Style.STROKE.nativeInt || style == Paint.Style.FILL_AND_STROKE.nativeInt) { graphics.drawRoundRect( - (int)rect.left, (int)rect.top, - (int)rect.width(), (int)rect.height(), + (int)left, (int)top, + (int)(right - left), (int)(bottom - top), (int)rx, (int)ry); } } @@ -975,8 +976,10 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void native_drawText(long nativeCanvas, final char[] text, final int index, final int count, - final float startX, final float startY, final int flags, long paint) { + final float startX, final float startY, final int flags, long paint, + long typeface) { + // TODO: use typeface. draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/, new GcSnapshot.Drawable() { @Override @@ -1006,30 +1009,31 @@ public final class Canvas_Delegate { @LayoutlibDelegate /*package*/ static void native_drawText(long nativeCanvas, String text, - int start, int end, float x, float y, final int flags, long paint) { + int start, int end, float x, float y, final int flags, long paint, + long typeface) { int count = end - start; char[] buffer = TemporaryBuffer.obtain(count); TextUtils.getChars(text, start, end, buffer, 0); - native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint); + native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface); } @LayoutlibDelegate /*package*/ static void native_drawTextRun(long nativeCanvas, String text, int start, int end, int contextStart, int contextEnd, - float x, float y, int flags, long paint) { + float x, float y, int flags, long paint, long typeface) { int count = end - start; char[] buffer = TemporaryBuffer.obtain(count); TextUtils.getChars(text, start, end, buffer, 0); - native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint); + native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface); } @LayoutlibDelegate /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text, int start, int count, int contextStart, int contextCount, - float x, float y, int flags, long paint) { - native_drawText(nativeCanvas, text, start, count, x, y, flags, paint); + float x, float y, int flags, long paint, long typeface) { + native_drawText(nativeCanvas, text, start, count, x, y, flags, paint, typeface); } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java index d6b3da1..bf03a5e 100644 --- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java @@ -56,7 +56,7 @@ public abstract class ColorFilter_Delegate { // ---- native methods ---- @LayoutlibDelegate - /*package*/ static void finalizer(long native_instance, long nativeColorFilter) { + /*package*/ static void destroyFilter(long native_instance) { sManager.removeJavaReferenceFor(native_instance); } diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java index ca8f450..9aac2bd 100644 --- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java @@ -60,11 +60,5 @@ public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate { return sManager.addNewDelegate(newDelegate); } - @LayoutlibDelegate - /*package*/ static long nColorMatrixFilter(long nativeFilter, float[] array) { - // pass - return 0; - } - // ---- Private delegate/helper methods ---- } diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java index defaac3..501d55c 100644 --- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java @@ -60,11 +60,5 @@ public class LightingColorFilter_Delegate extends ColorFilter_Delegate { return sManager.addNewDelegate(newDelegate); } - @LayoutlibDelegate - /*package*/ static int nCreateLightingFilter(long nativeFilter, int mul, int add) { - // pass - return 0; - } - // ---- Private delegate/helper methods ---- } diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java index ebfe9bc..8862f5b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java @@ -355,227 +355,162 @@ public final class Matrix_Delegate { } @LayoutlibDelegate - /*package*/ static boolean native_setConcat(long native_object, long a, long b) { + /*package*/ static void native_setConcat(long native_object, long a, long b) { if (a == native_object) { - return native_preConcat(native_object, b); + native_preConcat(native_object, b); + return; } else if (b == native_object) { - return native_postConcat(native_object, a); + native_postConcat(native_object, a); + return; } Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - Matrix_Delegate a_mtx = sManager.getDelegate(a); - if (a_mtx == null) { - return false; - } - Matrix_Delegate b_mtx = sManager.getDelegate(b); - if (b_mtx == null) { - return false; + if (d != null && a_mtx != null && b_mtx != null) { + multiply(d.mValues, a_mtx.mValues, b_mtx.mValues); } - - multiply(d.mValues, a_mtx.mValues, b_mtx.mValues); - - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preTranslate(long native_object, float dx, float dy) { + /*package*/ static void native_preTranslate(long native_object, float dx, float dy) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.preTransform(getTranslate(dx, dy)); } - - d.preTransform(getTranslate(dx, dy)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preScale(long native_object, float sx, float sy, + /*package*/ static void native_preScale(long native_object, float sx, float sy, float px, float py) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.preTransform(getScale(sx, sy, px, py)); } - - d.preTransform(getScale(sx, sy, px, py)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preScale(long native_object, float sx, float sy) { + /*package*/ static void native_preScale(long native_object, float sx, float sy) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.preTransform(getScale(sx, sy)); } - - d.preTransform(getScale(sx, sy)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preRotate(long native_object, float degrees, + /*package*/ static void native_preRotate(long native_object, float degrees, float px, float py) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.preTransform(getRotate(degrees, px, py)); } - - d.preTransform(getRotate(degrees, px, py)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preRotate(long native_object, float degrees) { + /*package*/ static void native_preRotate(long native_object, float degrees) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } + if (d != null) { - double rad = Math.toRadians(degrees); - float sin = (float)Math.sin(rad); - float cos = (float)Math.cos(rad); + double rad = Math.toRadians(degrees); + float sin = (float) Math.sin(rad); + float cos = (float) Math.cos(rad); - d.preTransform(getRotate(sin, cos)); - return true; + d.preTransform(getRotate(sin, cos)); + } } @LayoutlibDelegate - /*package*/ static boolean native_preSkew(long native_object, float kx, float ky, + /*package*/ static void native_preSkew(long native_object, float kx, float ky, float px, float py) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.preTransform(getSkew(kx, ky, px, py)); } - - d.preTransform(getSkew(kx, ky, px, py)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preSkew(long native_object, float kx, float ky) { + /*package*/ static void native_preSkew(long native_object, float kx, float ky) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.preTransform(getSkew(kx, ky)); } - - d.preTransform(getSkew(kx, ky)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_preConcat(long native_object, long other_matrix) { + /*package*/ static void native_preConcat(long native_object, long other_matrix) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - Matrix_Delegate other = sManager.getDelegate(other_matrix); - if (other == null) { - return false; + if (d != null && other != null) { + d.preTransform(other.mValues); } - - d.preTransform(other.mValues); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postTranslate(long native_object, float dx, float dy) { + /*package*/ static void native_postTranslate(long native_object, float dx, float dy) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getTranslate(dx, dy)); } - - d.postTransform(getTranslate(dx, dy)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postScale(long native_object, float sx, float sy, + /*package*/ static void native_postScale(long native_object, float sx, float sy, float px, float py) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getScale(sx, sy, px, py)); } - - d.postTransform(getScale(sx, sy, px, py)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postScale(long native_object, float sx, float sy) { + /*package*/ static void native_postScale(long native_object, float sx, float sy) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getScale(sx, sy)); } - - d.postTransform(getScale(sx, sy)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postRotate(long native_object, float degrees, + /*package*/ static void native_postRotate(long native_object, float degrees, float px, float py) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getRotate(degrees, px, py)); } - - d.postTransform(getRotate(degrees, px, py)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postRotate(long native_object, float degrees) { + /*package*/ static void native_postRotate(long native_object, float degrees) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getRotate(degrees)); } - - d.postTransform(getRotate(degrees)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postSkew(long native_object, float kx, float ky, + /*package*/ static void native_postSkew(long native_object, float kx, float ky, float px, float py) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getSkew(kx, ky, px, py)); } - - d.postTransform(getSkew(kx, ky, px, py)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postSkew(long native_object, float kx, float ky) { + /*package*/ static void native_postSkew(long native_object, float kx, float ky) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; + if (d != null) { + d.postTransform(getSkew(kx, ky)); } - - d.postTransform(getSkew(kx, ky)); - return true; } @LayoutlibDelegate - /*package*/ static boolean native_postConcat(long native_object, long other_matrix) { + /*package*/ static void native_postConcat(long native_object, long other_matrix) { Matrix_Delegate d = sManager.getDelegate(native_object); - if (d == null) { - return false; - } - Matrix_Delegate other = sManager.getDelegate(other_matrix); - if (other == null) { - return false; + if (d != null && other != null) { + d.postTransform(other.mValues); } - - d.postTransform(other.mValues); - return true; } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index 7007b71..83df745 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -420,7 +420,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy, + /*package*/ static void native_setShadowLayer(long paint, float radius, float dx, float dy, int color) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -428,6 +428,24 @@ public class Paint_Delegate { } @LayoutlibDelegate + /*package*/ static boolean native_hasShadowLayer(long paint) { + // FIXME + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "Paint.hasShadowLayer is not supported.", null, null /*data*/); + return false; + } + + @LayoutlibDelegate + /*package*/ static boolean isElegantTextHeight(Paint thisPaint) { + return false; + } + + @LayoutlibDelegate + /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) { + // TODO + } + + @LayoutlibDelegate /*package*/ static float getTextSize(Paint thisPaint) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint); @@ -688,7 +706,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getStyle(long native_object) { + /*package*/ static int native_getStyle(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -710,7 +728,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getStrokeCap(long native_object) { + /*package*/ static int native_getStrokeCap(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -732,7 +750,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getStrokeJoin(long native_object) { + /*package*/ static int native_getStrokeJoin(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -889,7 +907,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getTextAlign(long native_object) { + /*package*/ static int native_getTextAlign(long native_object) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); if (delegate == null) { @@ -922,7 +940,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getTextWidths(long native_object, char[] text, int index, + /*package*/ static int native_getTextWidths(long native_object, char[] text, int index, int count, int bidiFlags, float[] widths) { // get the delegate from the native int. Paint_Delegate delegate = sManager.getDelegate(native_object); @@ -964,14 +982,14 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getTextWidths(long native_object, String text, int start, + /*package*/ static int native_getTextWidths(long native_object, String text, int start, int end, int bidiFlags, float[] widths) { return native_getTextWidths(native_object, text.toCharArray(), start, end - start, bidiFlags, widths); } @LayoutlibDelegate - /* package */static long native_getTextGlyphs(long native_object, String text, int start, + /* package */static int native_getTextGlyphs(long native_object, String text, int start, int end, int contextStart, int contextEnd, int flags, char[] glyphs) { // FIXME return 0; @@ -1012,7 +1030,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getTextRunCursor(Paint thisPaint, long native_object, char[] text, + /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text, int contextStart, int contextLength, int flags, int offset, int cursorOpt) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, @@ -1021,7 +1039,7 @@ public class Paint_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getTextRunCursor(Paint thisPaint, long native_object, String text, + /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) { // FIXME Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java index 6f6ef20..0ec7115 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java @@ -142,7 +142,14 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static long native_getFillType(long nPath) { + /*package*/ static boolean native_isConvex(long nPath) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "Path.isConvex is not supported.", null, null); + return true; + } + + @LayoutlibDelegate + /*package*/ static int native_getFillType(long nPath) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return 0; @@ -311,16 +318,6 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addRect(long nPath, RectF rect, int dir) { - Path_Delegate pathDelegate = sManager.getDelegate(nPath); - if (pathDelegate == null) { - return; - } - - pathDelegate.addRect(rect.left, rect.top, rect.right, rect.bottom, dir); - } - - @LayoutlibDelegate /*package*/ static void native_addRect(long nPath, float left, float top, float right, float bottom, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); @@ -332,14 +329,15 @@ public final class Path_Delegate { } @LayoutlibDelegate - /*package*/ static void native_addOval(long nPath, RectF oval, int dir) { + /*package*/ static void native_addOval(long nPath, float left, float top, float right, + float bottom, int dir) { Path_Delegate pathDelegate = sManager.getDelegate(nPath); if (pathDelegate == null) { return; } pathDelegate.mPath.append(new Ellipse2D.Float( - oval.left, oval.top, oval.width(), oval.height()), false); + left, top, right - left, bottom - top), false); } @LayoutlibDelegate @@ -484,6 +482,11 @@ public final class Path_Delegate { sManager.removeJavaReferenceFor(nPath); } + @LayoutlibDelegate + /*package*/ static float[] native_approximate(long nPath, float error) { + Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not supported", null); + return new float[0]; + } // ---- Private helper methods ---- diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java index 6049919..1bc3033 100644 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java @@ -60,12 +60,5 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate { return sManager.addNewDelegate(newDelegate); } - @LayoutlibDelegate - /*package*/ static long nCreatePorterDuffFilter(long nativeFilter, int srcColor, - int porterDuffMode) { - // pass - return 0; - } - // ---- Private delegate/helper methods ---- } diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java index d2aae92..edb7025 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java @@ -289,7 +289,6 @@ public class Region_Delegate { dstRegion.mArea.reset(); dstRegion.mArea.add(srcRegion.mArea); - return; } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/os/Build_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java index ff82a5e..1e7564e 100644 --- a/tools/layoutlib/bridge/src/android/os/Build_Delegate.java +++ b/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * 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. @@ -23,26 +23,29 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import java.util.Map; /** - * Delegate implementing the native methods of android.os.Build + * Delegate implementing the native methods of android.os.SystemProperties * - * Through the layoutlib_create tool, the original native methods of Build have been replaced - * by calls to methods of the same name in this delegate class. + * Through the layoutlib_create tool, the original native methods of SystemProperties have been + * replaced by calls to methods of the same name in this delegate class. * * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} * around to map int to instance of the delegate. - * */ -public class Build_Delegate { +public class SystemProperties_Delegate { @LayoutlibDelegate - /*package*/ static String getString(String property) { + /*package*/ static String native_get(String key) { + return native_get(key, ""); + } + + @LayoutlibDelegate + /*package*/ static String native_get(String key, String def) { Map<String, String> properties = Bridge.getPlatformProperties(); - String value = properties.get(property); + String value = properties.get(key); if (value != null) { return value; } - return Build.UNKNOWN; + return def; } - } diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java index a2e93a7..af22f44 100644 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -121,10 +121,11 @@ public final class BridgeInflater extends LayoutInflater { } @Override - public View createViewFromTag(View parent, String name, AttributeSet attrs) { + public View createViewFromTag(View parent, String name, AttributeSet attrs, + boolean inheritContext) { View view = null; try { - view = super.createViewFromTag(parent, name, attrs); + view = super.createViewFromTag(parent, name, attrs, inheritContext); } catch (InflateException e) { // try to load the class from using the custom view loader try { diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index dd2cbc1..757cdd2 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -23,22 +23,13 @@ import com.android.internal.view.IInputMethodClient; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; -import android.graphics.Rect; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.RemoteException; import android.util.DisplayMetrics; -import android.view.Display; -import android.view.Gravity; -import android.view.IApplicationToken; -import android.view.IInputFilter; -import android.view.IOnKeyguardExitResult; -import android.view.IRotationWatcher; -import android.view.IWindowManager; -import android.view.IWindowSession; -import java.util.List; +import java.lang.Override; /** * Basic implementation of {@link IWindowManager} so that {@link Display} (and @@ -458,44 +449,26 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public IBinder getFocusedWindowToken() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void setInputFilter(IInputFilter filter) throws RemoteException { - // TODO Auto-generated method stub - } - - @Override - public void getWindowFrame(IBinder token, Rect outFrame) { + public boolean isRotationFrozen() throws RemoteException { // TODO Auto-generated method stub + return false; } @Override - public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) { + public void enableScreenIfNeeded() throws RemoteException { // TODO Auto-generated method stub } @Override - public void setMagnificationSpec(MagnificationSpec spec) { + public boolean clearWindowContentFrameStats(IBinder token) throws RemoteException { // TODO Auto-generated method stub + return false; } @Override - public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { + public WindowContentFrameStats getWindowContentFrameStats(IBinder token) + throws RemoteException { // TODO Auto-generated method stub return null; } - - @Override - public boolean isRotationFrozen() throws RemoteException { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setTouchExplorationEnabled(boolean enabled) { - } } diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java index 3db3a1b..7a73fae 100644 --- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java @@ -48,9 +48,9 @@ public class LayoutInflater_Delegate { * This implementation just records the merge status before calling the default implementation. */ @LayoutlibDelegate - /*package*/ static void rInflate(LayoutInflater thisInflater, - XmlPullParser parser, View parent, final AttributeSet attrs, - boolean finishInflate) throws XmlPullParserException, IOException { + /* package */ static void rInflate(LayoutInflater thisInflater, XmlPullParser parser, + View parent, final AttributeSet attrs, boolean finishInflate, boolean inheritContext) + throws XmlPullParserException, IOException { if (finishInflate == false) { // this is a merge rInflate! @@ -61,7 +61,7 @@ public class LayoutInflater_Delegate { // ---- START DEFAULT IMPLEMENTATION. - thisInflater.rInflate_Original(parser, parent, attrs, finishInflate); + thisInflater.rInflate_Original(parser, parent, attrs, finishInflate, inheritContext); // ---- END DEFAULT IMPLEMENTATION. @@ -74,10 +74,8 @@ public class LayoutInflater_Delegate { } @LayoutlibDelegate - public static void parseInclude( - LayoutInflater thisInflater, - XmlPullParser parser, View parent, AttributeSet attrs) - throws XmlPullParserException, IOException { + public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser, View parent, + AttributeSet attrs, boolean inheritContext) throws XmlPullParserException, IOException { int type; @@ -113,9 +111,11 @@ public class LayoutInflater_Delegate { if (TAG_MERGE.equals(childName)) { // Inflate all children. - thisInflater.rInflate(childParser, parent, childAttrs, false); + thisInflater.rInflate(childParser, parent, childAttrs, false, + inheritContext); } else { - final View view = thisInflater.createViewFromTag(parent, childName, childAttrs); + final View view = thisInflater.createViewFromTag(parent, childName, + childAttrs, inheritContext); final ViewGroup group = (ViewGroup) parent; // We try to load the layout params set in the <include /> tag. If @@ -151,7 +151,7 @@ public class LayoutInflater_Delegate { } // Inflate all children. - thisInflater.rInflate(childParser, view, childAttrs, true); + thisInflater.rInflate(childParser, view, childAttrs, true, true); // Attempt to override the included layout's android:id with the // one set on the <include /> tag itself. diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java index e34ad38..0dddf3d 100644 --- a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java +++ b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java @@ -23,7 +23,6 @@ import com.android.internal.view.menu.BridgeMenuItemImpl; import com.android.internal.view.menu.MenuView; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; -import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.util.AttributeSet; diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilderAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilderAccessor.java deleted file mode 100644 index f0798cb..0000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilderAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.android.internal.view.menu; - -import java.util.ArrayList; - -/** - * To access non public members of {@link MenuBuilder} - */ -public class MenuBuilderAccessor { - public static ArrayList<MenuItemImpl> getNonActionItems(MenuBuilder builder) { - return builder.getNonActionItems(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java index 47a3679..40b6220 100644 --- a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java +++ b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java @@ -16,7 +16,7 @@ package com.android.internal.widget; -import com.android.internal.view.menu.ActionMenuPresenter; +import android.widget.ActionMenuPresenter; /** * To access non public members of AbsActionBarView diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java index 01740b1..89288bf 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java @@ -135,6 +135,7 @@ public final class BridgeContentProvider implements IContentProvider { return null; } + @Override public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException { return null; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 6595ce1..d31239b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -58,6 +58,7 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -101,6 +102,7 @@ public final class BridgeContext extends Context { private final ApplicationInfo mApplicationInfo; private final IProjectCallback mProjectCallback; private final WindowManager mWindowManager; + private final DisplayManager mDisplayManager; private Resources.Theme mTheme; @@ -149,6 +151,7 @@ public final class BridgeContext extends Context { } mWindowManager = new WindowManagerImpl(mMetrics); + mDisplayManager = new DisplayManager(this); } /** @@ -455,6 +458,10 @@ public final class BridgeContext extends Context { return new PowerManager(this, new BridgePowerManager(), new Handler()); } + if (DISPLAY_SERVICE.equals(service)) { + return mDisplayManager; + } + throw new UnsupportedOperationException("Unsupported Service: " + service); } @@ -560,7 +567,7 @@ public final class BridgeContext extends Context { StyleResourceValue customStyleValues = null; if (customStyle != null) { ResourceValue item = mRenderResources.findResValue(customStyle, - false /*forceFrameworkOnly*/); + isPlatformFile /*forceFrameworkOnly*/); // resolve it in case it links to something else item = mRenderResources.resolveResValue(item); @@ -1277,6 +1284,14 @@ public final class BridgeContext extends Context { } @Override + public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, + String receiverPermission, int appOp, BroadcastReceiver resultReceiver, + Handler scheduler, + int initialCode, String initialData, Bundle initialExtras) { + // pass + } + + @Override public void sendStickyBroadcast(Intent arg0) { // pass diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java index 3cf5ed5..0bb7fc2 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java @@ -209,6 +209,17 @@ public class BridgeIInputMethodManager implements IInputMethodManager { } @Override + public int getInputMethodWindowVisibleHeight() throws RemoteException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void notifyTextCommitted() throws RemoteException { + // TODO Auto-generated method stub + } + + @Override public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException { // TODO Auto-generated method stub @@ -227,4 +238,9 @@ public class BridgeIInputMethodManager implements IInputMethodManager { // TODO Auto-generated method stub return null; } + + @Override + public void setCursorAnchorMonitorMode(IBinder arg0, int arg1) { + // TODO Auto-generated method stub + } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java index 95221fb..00c0f93 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java @@ -39,7 +39,7 @@ public class BridgePowerManager implements IPowerManager { } @Override - public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3) + public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3, String arg4) throws RemoteException { // pass for now. } @@ -51,6 +51,11 @@ public class BridgePowerManager implements IPowerManager { } @Override + public void powerHint(int hintId, int data) { + // pass for now. + } + + @Override public void crash(String arg0) throws RemoteException { // pass for now. } @@ -111,7 +116,7 @@ public class BridgePowerManager implements IPowerManager { } @Override - public void updateWakeLockWorkSource(IBinder arg0, WorkSource arg1) throws RemoteException { + public void updateWakeLockWorkSource(IBinder arg0, WorkSource arg1, String arg2) throws RemoteException { // pass for now. } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java index 0e39a57..936ab4f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java @@ -25,11 +25,9 @@ import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.SessionParams; import com.android.ide.common.rendering.api.SystemViewCookie; import com.android.internal.R; -import com.android.internal.app.ActionBarImpl; +import com.android.internal.app.WindowDecorActionBar; import com.android.internal.util.Predicate; -import com.android.internal.view.menu.ActionMenuView; import com.android.internal.view.menu.MenuBuilder; -import com.android.internal.view.menu.MenuBuilderAccessor; import com.android.internal.view.menu.MenuItemImpl; import com.android.internal.widget.ActionBarAccessor; import com.android.internal.widget.ActionBarContainer; @@ -52,6 +50,7 @@ import android.view.LayoutInflater; import android.view.MenuInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ActionMenuView; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ListAdapter; @@ -101,7 +100,7 @@ public class ActionBarLayout extends LinearLayout { // Inflate action bar layout. LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this, true /*attachToRoot*/); - mActionBar = new ActionBarImpl(this); + mActionBar = new WindowDecorActionBar(this); // Set contexts. mBridgeContext = context; @@ -323,7 +322,7 @@ public class ActionBarLayout extends LinearLayout { return false; } // Copied from android.widget.ActionMenuPresenter.updateMenuView() - ArrayList<MenuItemImpl> menus = MenuBuilderAccessor.getNonActionItems(mMenuBuilder); + ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems(); if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() && menus != null) { final int count = menus.size(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index bcd08eb4..86797e5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -87,7 +87,7 @@ abstract class CustomBar extends LinearLayout { } } - private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction, + private InputStream getIcon(String iconName, Density[] densityInOut, LayoutDirection direction, String[] pathOut, boolean tryOtherDensities) { // current density Density density = densityInOut[0]; @@ -111,10 +111,10 @@ abstract class CustomBar extends LinearLayout { return stream; } } - } - // couldn't find resource with direction qualifier. try without. - if (direction != null) { - return getIcon(iconName, densityInOut, null, pathOut, true); + // couldn't find resource with direction qualifier. try without. + if (direction != null) { + return getIcon(iconName, densityInOut, null, pathOut, true); + } } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java index 84e676e..112c267 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java @@ -17,7 +17,6 @@ package com.android.layoutlib.bridge.bars; import com.android.resources.Density; -import com.android.layoutlib.bridge.Bridge; import org.xmlpull.v1.XmlPullParserException; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java index 79e231c..778305d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java @@ -17,7 +17,6 @@ package com.android.layoutlib.bridge.bars; import com.android.internal.view.menu.MenuBuilder; -import com.android.internal.view.menu.MenuBuilderAccessor; import com.android.internal.view.menu.MenuItemImpl; import com.android.internal.view.menu.MenuView; @@ -47,7 +46,7 @@ public class OverflowMenuAdapter extends BaseAdapter { @Override public int getCount() { - ArrayList<MenuItemImpl> items = MenuBuilderAccessor.getNonActionItems(mMenu); + ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); if (mExpandedIndex < 0) { return items.size(); } @@ -56,7 +55,7 @@ public class OverflowMenuAdapter extends BaseAdapter { @Override public MenuItemImpl getItem(int position) { - ArrayList<MenuItemImpl> items = MenuBuilderAccessor.getNonActionItems(mMenu); + ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); if (mExpandedIndex >= 0 && position >= mExpandedIndex) { position++; } @@ -86,7 +85,7 @@ public class OverflowMenuAdapter extends BaseAdapter { private void findExpandedIndex() { final MenuItemImpl expandedItem = mMenu.getExpandedItem(); if (expandedItem != null) { - final ArrayList<MenuItemImpl> items = MenuBuilderAccessor.getNonActionItems(mMenu); + final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); final int count = items.size(); for (int i = 0; i < count; i++) { final MenuItemImpl item = items.get(i); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java index 3692d96..1498044 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java @@ -33,7 +33,6 @@ public class StatusBar extends CustomBar { public StatusBar(Context context, Density density, int direction, boolean RtlEnabled) throws XmlPullParserException { // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar. - super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml"); // FIXME: use FILL_H? diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java index 53e1640..a2a8aa9 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java @@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.util; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.GrowingArrayUtils; import android.util.SparseArray; @@ -59,10 +60,8 @@ public class SparseWeakArray<E> { * number of mappings. */ public SparseWeakArray(int initialCapacity) { - initialCapacity = ArrayUtils.idealLongArraySize(initialCapacity); - - mKeys = new long[initialCapacity]; - mValues = new WeakReference[initialCapacity]; + mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity); + mValues = new WeakReference[mKeys.length]; mSize = 0; } @@ -142,18 +141,6 @@ public class SparseWeakArray<E> { mGarbage = false; mSize = o; - - int newSize = ArrayUtils.idealLongArraySize(mSize); - if (newSize < mKeys.length) { - long[] nkeys = new long[newSize]; - WeakReference<?>[] nvalues = new WeakReference[newSize]; - - System.arraycopy(mKeys, 0, nkeys, 0, newSize); - System.arraycopy(mValues, 0, nvalues, 0, newSize); - - mKeys = nkeys; - mValues = nvalues; - } } /** @@ -182,28 +169,8 @@ public class SparseWeakArray<E> { i = ~binarySearch(mKeys, 0, mSize, key); } - if (mSize >= mKeys.length) { - int n = ArrayUtils.idealLongArraySize(mSize + 1); - - long[] nkeys = new long[n]; - WeakReference<?>[] nvalues = new WeakReference[n]; - - // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); - System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); - System.arraycopy(mValues, 0, nvalues, 0, mValues.length); - - mKeys = nkeys; - mValues = nvalues; - } - - if (mSize - i != 0) { - // Log.e("SparseArray", "move " + (mSize - i)); - System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i); - System.arraycopy(mValues, i, mValues, i + 1, mSize - i); - } - - mKeys[i] = key; - mValues[i] = new WeakReference(value); + mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key); + mValues = GrowingArrayUtils.insert(mValues, mSize, i, new WeakReference(value)); mSize++; } } @@ -321,24 +288,9 @@ public class SparseWeakArray<E> { gc(); } - int pos = mSize; - if (pos >= mKeys.length) { - int n = ArrayUtils.idealLongArraySize(pos + 1); - - long[] nkeys = new long[n]; - WeakReference<?>[] nvalues = new WeakReference[n]; - - // Log.e("SparseArray", "grow " + mKeys.length + " to " + n); - System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length); - System.arraycopy(mValues, 0, nvalues, 0, mValues.length); - - mKeys = nkeys; - mValues = nvalues; - } - - mKeys[pos] = key; - mValues[pos] = new WeakReference(value); - mSize = pos + 1; + mKeys = GrowingArrayUtils.append(mKeys, mSize, key); + mValues = GrowingArrayUtils.append(mValues, mSize, new WeakReference(value)); + mSize++; } private boolean hasReclaimedRefs() { diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java index 0f66fd7..19d249b 100644 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java @@ -18,6 +18,7 @@ package libcore.icu; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import com.ibm.icu.text.DateTimePatternGenerator; +import com.ibm.icu.util.Currency; import com.ibm.icu.util.ULocale; import java.util.Locale; @@ -117,6 +118,11 @@ public class ICU_Delegate { } @LayoutlibDelegate + /*package*/ static int getCurrencyNumericCode(String currencyCode) { + return Currency.getInstance(currencyCode).getNumericCode(); + } + + @LayoutlibDelegate /*package*/ static String getCurrencySymbol(String locale, String currencyCode) { return ""; } diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java index 7c0bc84..274516c 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java @@ -121,14 +121,6 @@ public class TestDelegates extends TestCase { Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(), parameters); - // check that the method has the annotation - assertNotNull( - String.format( - "Delegate method %1$s for class %2$s does not have the @LayoutlibDelegate annotation", - delegateMethod.getName(), - originalClass.getName()), - delegateMethod.getAnnotation(LayoutlibDelegate.class)); - // check the return type of the methods match. assertTrue( String.format("Delegate method %1$s.%2$s does not match the corresponding " + @@ -138,6 +130,14 @@ public class TestDelegates extends TestCase { originalMethod.getReturnType().getName()), delegateMethod.getReturnType() == originalMethod.getReturnType()); + // check that the method has the annotation + assertNotNull( + String.format( + "Delegate method %1$s for class %2$s does not have the @LayoutlibDelegate annotation", + delegateMethod.getName(), + originalClass.getName()), + delegateMethod.getAnnotation(LayoutlibDelegate.class)); + // check that the method is static assertTrue( String.format( 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 @@ The tool works in two phases: - 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 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: +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. + +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 @@ This strategy is now obsolete and replaced by the method delegates. - 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. - -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. +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. 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 @@ public abstract class AbstractClassAdapter extends ClassVisitor { } } + /* 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); } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 911df7d..bb72a1e 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -125,6 +125,7 @@ public final class CreateInfo implements ICreateInfo { "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;", "android.content.res.Resources$Theme#obtainStyledAttributes", "android.content.res.Resources$Theme#resolveAttribute", + "android.content.res.Resources#localeToLanguageTag", "android.content.res.AssetManager#newTheme", "android.content.res.AssetManager#deleteTheme", "android.content.res.AssetManager#applyThemeStyle", @@ -132,7 +133,6 @@ public final class CreateInfo implements ICreateInfo { "android.graphics.BitmapFactory#finishDecode", "android.os.Handler#sendMessageAtTime", "android.os.HandlerThread#run", - "android.os.Build#getString", "android.text.format.DateFormat#is24HourFormat", "android.view.Choreographer#getRefreshRate", "android.view.Display#updateDisplayInfoLocked", @@ -147,6 +147,7 @@ public final class CreateInfo implements ICreateInfo { "com.android.internal.view.menu.MenuBuilder#createNewMenuItem", "com.android.internal.util.XmlUtils#convertValueToInt", "com.android.internal.textservice.ITextServicesManager$Stub#asInterface", + "android.os.SystemProperties#native_get", }; /** diff --git a/tools/layoutlib/rename_font/README b/tools/layoutlib/rename_font/README new file mode 100644 index 0000000..600b756 --- /dev/null +++ b/tools/layoutlib/rename_font/README @@ -0,0 +1,9 @@ +This tool is used to rename the PS name encoded inside the ttf font that we ship +with the SDK. There is bug in Java that returns incorrect results for +java.awt.Font#layoutGlyphVector() if two fonts with same name but differnt +versions are loaded. As a workaround, we rename all the fonts that we ship with +the SDK by appending the font version to its name. + + +The build_font.py copies all files from input_dir to output_dir while renaming +the font files (*.ttf) in the process. diff --git a/tools/layoutlib/rename_font/Roboto-Regular.ttf b/tools/layoutlib/rename_font/Roboto-Regular.ttf Binary files differnew file mode 100644 index 0000000..7469063 --- /dev/null +++ b/tools/layoutlib/rename_font/Roboto-Regular.ttf diff --git a/tools/layoutlib/rename_font/build_font.py b/tools/layoutlib/rename_font/build_font.py new file mode 100755 index 0000000..ea3dccc --- /dev/null +++ b/tools/layoutlib/rename_font/build_font.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python + +# 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. + +""" +Rename the PS name of all fonts in the input directory and copy them to the +output directory. + +Usage: build_font.py /path/to/input_fonts/ /path/to/output_fonts/ + +""" + +import sys +# fontTools is available at platform/external/fonttools +from fontTools import ttx +import re +import os +from lxml import etree +import shutil +import glob + +def main(argv): + if len(argv) != 2: + print "Usage: build_font.py /path/to/input_fonts/ /path/to/out/dir/" + sys.exit(1) + if not os.path.isdir(argv[0]): + print argv[0] + "is not a valid directory" + sys.exit(1) + if not os.path.isdir(argv[1]): + print argv[1] + "is not a valid directory" + sys.exit(1) + cwd = os.getcwd() + os.chdir(argv[1]) + files = glob.glob('*') + for filename in files: + os.remove(filename) + os.chdir(cwd) + for filename in os.listdir(argv[0]): + if not os.path.splitext(filename)[1].lower() == ".ttf": + shutil.copy(os.path.join(argv[0], filename), argv[1]) + continue + print os.path.join(argv[0], filename) + old_ttf_path = os.path.join(argv[0], filename) + # run ttx to generate an xml file in the output folder which represents all + # its info + ttx_args = ["-d", argv[1], old_ttf_path] + ttx.main(ttx_args) + # the path to the output file. The file name is the fontfilename.ttx + ttx_path = os.path.join(argv[1], filename) + ttx_path = ttx_path[:-1] + "x" + # now parse the xml file to change its PS name. + tree = etree.parse(ttx_path) + encoding = tree.docinfo.encoding + root = tree.getroot() + for name in root.iter('name'): + [old_ps_name, version] = get_font_info(name) + new_ps_name = old_ps_name + version + update_name(name, new_ps_name) + tree.write(ttx_path, xml_declaration=True, encoding=encoding ) + # generate the udpated font now. + ttx_args = ["-d", argv[1], ttx_path] + ttx.main(ttx_args) + # delete the temp ttx file. + os.remove(ttx_path) + +def get_font_info(tag): + ps_name = None + ps_version = None + for namerecord in tag.iter('namerecord'): + if 'nameID' in namerecord.attrib: + # if the tag has nameID=6, it is the postscript name of the font. + # see: http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08#3054f18b + if namerecord.attrib['nameID'] == '6': + if ps_name is not None: + if not sanitize(namerecord.text) == ps_name: + sys.exit('found multiple possibilities of the font name') + else: + ps_name = sanitize(namerecord.text) + # nameID=5 means the font version + if namerecord.attrib['nameID'] == '5': + if ps_version is not None: + if not ps_version == get_version(namerecord.text): + sys.exit('found multiple possibilities of the font version') + else: + ps_version = get_version(namerecord.text) + if ps_name is not None and ps_version is not None: + return [ps_name, ps_version] + sys.exit('didn\'t find the font name or version') + + +def update_name(tag, name): + for namerecord in tag.iter('namerecord'): + if 'nameID' in namerecord.attrib: + if namerecord.attrib['nameID'] == '6': + namerecord.text = name + +def sanitize(string): + return re.sub(r'[^\w-]+', '', string) + +def get_version(string): + # The string must begin with "Version n.nn " + # to extract n.nn, we return the second entry in the split strings. + string = string.strip() + if not string.startswith("Version "): + sys.exit('mal-formed font version') + return sanitize(string.split()[1]) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/tools/layoutlib/rename_font/test.py b/tools/layoutlib/rename_font/test.py new file mode 100755 index 0000000..d4c86cb --- /dev/null +++ b/tools/layoutlib/rename_font/test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +"""Tests build_font.py by renaming a font. + +The test copies Roboto-Regular.ttf to a tmp directory and ask build_font.py to rename it and put in another dir. +We then use ttx to dump the new font to its xml and check if rename was successful + +To test locally, use: +PYTHONPATH="$PYTHONPATH:/path/to/android/checkout/external/fonttools/Lib" ./test.py +""" + +import unittest +import build_font + +from fontTools import ttx +import os +from lxml import etree +import shutil +import tempfile + +class MyTest(unittest.TestCase): + def test(self): + font_name = "Roboto-Regular.ttf" + srcdir = tempfile.mkdtemp() + print "srcdir: " + srcdir + shutil.copy(font_name, srcdir) + destdir = tempfile.mkdtemp() + print "destdir: " + destdir + self.assertTrue(build_font.main([srcdir, destdir]) is None) + out_path = os.path.join(destdir, font_name) + ttx.main([out_path]) + ttx_path = out_path[:-1] + "x" + tree = etree.parse(ttx_path) + root = tree.getroot() + name_tag = root.find('name') + [f_name, f_version] = build_font.get_font_info(name_tag) + shutil.rmtree(srcdir) + shutil.rmtree(destdir) + self.assertEqual(f_name, "Roboto-Regular1200310") + + + +if __name__ == '__main__': + unittest.main() |