diff options
Diffstat (limited to 'tools/layoutlib')
40 files changed, 548 insertions, 334 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 new file mode 100644 index 0000000..914a359 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import com.android.tools.layoutlib.annotations.LayoutlibDelegate; + +/** + * Delegate used to provide implementation of a select few native methods of {@link AssetManager} + * <p/> + * Through the layoutlib_create tool, the original native methods of AssetManager have been replaced + * by calls to methods of the same name in this delegate class. + * + */ +public class AssetManager_Delegate { + + @LayoutlibDelegate + /*package*/ static long newTheme(AssetManager manager) { + return Resources_Theme_Delegate.getDelegateManager() + .addNewDelegate(new Resources_Theme_Delegate()); + } + + @LayoutlibDelegate + /*package*/ static void deleteTheme(AssetManager manager, long theme) { + Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme); + } + + @LayoutlibDelegate + /*package*/ static void applyThemeStyle(long theme, int styleRes, boolean 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 c9d615c..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 @@ -16,7 +16,13 @@ package android.content.res; +import com.android.annotations.Nullable; +import com.android.ide.common.rendering.api.ResourceReference; +import com.android.ide.common.rendering.api.StyleResourceValue; +import com.android.layoutlib.bridge.android.BridgeContext; +import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.layoutlib.bridge.impl.RenderSessionImpl; +import com.android.resources.ResourceType; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; import android.content.res.Resources.NotFoundException; @@ -25,7 +31,7 @@ import android.util.AttributeSet; import android.util.TypedValue; /** - * Delegate used to provide new implementation of a select few methods of {@link Resources$Theme} + * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme} * * Through the layoutlib_create tool, the original methods of Theme have been replaced * by calls to methods of the same name in this delegate class. @@ -33,11 +39,28 @@ import android.util.TypedValue; */ public class Resources_Theme_Delegate { + // Whether to use the Theme.mThemeResId as primary theme. + boolean force; + + // ---- delegate manager ---- + + private static final DelegateManager<Resources_Theme_Delegate> sManager = + new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class); + + public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() { + return sManager; + } + + // ---- delegate methods. ---- + @LayoutlibDelegate /*package*/ static TypedArray obtainStyledAttributes( Resources thisResources, Theme thisTheme, int[] attrs) { - return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs); + boolean changed = setupResources(thisTheme); + TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs); + restoreResources(changed); + return ta; } @LayoutlibDelegate @@ -45,15 +68,21 @@ public class Resources_Theme_Delegate { Resources thisResources, Theme thisTheme, int resid, int[] attrs) throws NotFoundException { - return RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs); + boolean changed = setupResources(thisTheme); + TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, attrs); + restoreResources(changed); + return ta; } @LayoutlibDelegate /*package*/ static TypedArray obtainStyledAttributes( Resources thisResources, Theme thisTheme, AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { - return RenderSessionImpl.getCurrentContext().obtainStyledAttributes( - set, attrs, defStyleAttr, defStyleRes); + boolean changed = setupResources(thisTheme); + TypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, attrs, + defStyleAttr, defStyleRes); + restoreResources(changed); + return ta; } @LayoutlibDelegate @@ -61,7 +90,45 @@ public class Resources_Theme_Delegate { Resources thisResources, Theme thisTheme, int resid, TypedValue outValue, boolean resolveRefs) { - return RenderSessionImpl.getCurrentContext().resolveThemeAttribute( + boolean changed = setupResources(thisTheme); + boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute( resid, outValue, resolveRefs); + restoreResources(changed); + return found; + } + + // ---- private helper methods ---- + + private static boolean setupResources(Theme thisTheme) { + Resources_Theme_Delegate themeDelegate = sManager.getDelegate(thisTheme.getNativeTheme()); + StyleResourceValue style = resolveStyle(thisTheme.getAppliedStyleResId()); + if (style != null) { + RenderSessionImpl.getCurrentContext().getRenderResources() + .applyStyle(style, themeDelegate.force); + return true; + } + return false; + } + + private static void restoreResources(boolean changed) { + if (changed) { + RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles(); + } + } + + @Nullable + private static StyleResourceValue resolveStyle(int nativeResid) { + if (nativeResid == 0) { + return null; + } + BridgeContext context = RenderSessionImpl.getCurrentContext(); + ResourceReference theme = context.resolveId(nativeResid); + if (theme.isFramework()) { + return (StyleResourceValue) context.getRenderResources() + .getFrameworkResource(ResourceType.STYLE, theme.getName()); + } else { + return (StyleResourceValue) context.getRenderResources() + .getProjectResource(ResourceType.STYLE, theme.getName()); + } } } diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 89d7e23..7016136 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -518,7 +518,8 @@ public final class Bitmap_Delegate { } @LayoutlibDelegate - /*package*/ static void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha) { + /*package*/ static void nativeSetAlphaAndPremultiplied(long nativeBitmap, boolean hasAlpha, + boolean isPremul) { // get the delegate from the native int. Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index 73d274c..bb05d45 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -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. @@ -975,8 +975,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 +1008,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/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java index 7007b71..de2e592 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java @@ -688,7 +688,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 +710,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 +732,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 +889,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 +922,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 +964,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 +1012,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 +1021,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..b235408 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; @@ -484,6 +491,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 ea23649..edb7025 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java @@ -275,21 +275,20 @@ public class Region_Delegate { } @LayoutlibDelegate - /*package*/ static boolean nativeSetRegion(long native_dst, long native_src) { + /*package*/ static void nativeSetRegion(long native_dst, long native_src) { Region_Delegate dstRegion = sManager.getDelegate(native_dst); if (dstRegion == null) { - return true; + return; } Region_Delegate srcRegion = sManager.getDelegate(native_src); if (srcRegion == null) { - return true; + return; } dstRegion.mArea.reset(); dstRegion.mArea.add(srcRegion.mArea); - return true; } @LayoutlibDelegate diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java index 941f1ce6..cdbe200 100644 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java @@ -125,10 +125,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..4dd1446 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -23,22 +23,11 @@ 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; /** * Basic implementation of {@link IWindowManager} so that {@link Display} (and @@ -458,44 +447,20 @@ 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) { - // TODO Auto-generated method stub - } - - @Override - public void setMagnificationCallbacks(IMagnificationCallbacks callbacks) { + public boolean isRotationFrozen() throws RemoteException { // TODO Auto-generated method stub + return false; } @Override - public void setMagnificationSpec(MagnificationSpec spec) { + public boolean clearWindowContentFrameStats(IBinder token) { // TODO Auto-generated method stub + return false; } @Override - public MagnificationSpec getCompatibleMagnificationSpecForWindow(IBinder windowToken) { + public WindowContentFrameStats getWindowContentFrameStats(IBinder token) { // 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/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 b9294ab..9ee2f60 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 @@ -16,6 +16,7 @@ package com.android.layoutlib.bridge.android; +import com.android.annotations.Nullable; import com.android.ide.common.rendering.api.ILayoutPullParser; import com.android.ide.common.rendering.api.IProjectCallback; import com.android.ide.common.rendering.api.LayoutLog; @@ -109,7 +110,7 @@ public final class BridgeContext extends Context { // maps for dynamically generated id representing style objects (StyleResourceValue) private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap; private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap; - private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style + private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace // cache for TypedArray generated from IStyleResourceValue object private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache; @@ -315,6 +316,11 @@ public final class BridgeContext extends Context { } } + // The base value for R.style is 0x01030000 and the custom style is 0x02030000. + // So, if the second byte is 03, it's probably a style. + if ((id >> 16 & 0xFF) == 0x03) { + return getStyleByDynamicId(id); + } return null; } @@ -455,7 +461,10 @@ public final class BridgeContext extends Context { @Override public final TypedArray obtainStyledAttributes(int[] attrs) { - return createStyleBasedTypedArray(mRenderResources.getCurrentTheme(), attrs); + // No style is specified here, so create the typed array based on the default theme + // and the styles already applied to it. A null value of style indicates that the default + // theme should be used. + return createStyleBasedTypedArray(null, attrs); } @Override @@ -723,11 +732,13 @@ public final class BridgeContext extends Context { /** * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the - * values found in the given style. + * values found in the given style. If no style is specified, the default theme, along with the + * styles applied to it are used. + * * @see #obtainStyledAttributes(int, int[]) */ - private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs) - throws Resources.NotFoundException { + private BridgeTypedArray createStyleBasedTypedArray(@Nullable StyleResourceValue style, + int[] attrs) throws Resources.NotFoundException { List<Pair<String, Boolean>> attributes = searchAttrs(attrs); @@ -740,8 +751,14 @@ public final class BridgeContext extends Context { if (attribute != null) { // look for the value in the given style - ResourceValue resValue = mRenderResources.findItemInStyle(style, - attribute.getFirst(), attribute.getSecond()); + ResourceValue resValue; + if (style != null) { + resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(), + attribute.getSecond()); + } else { + resValue = mRenderResources.findItemInTheme(attribute.getFirst(), + attribute.getSecond()); + } if (resValue != null) { // resolve it to make sure there are no references left. @@ -756,7 +773,6 @@ public final class BridgeContext extends Context { return ta; } - /** * The input int[] attrs is a list of attributes. The returns a list of information about * each attributes. The information is (name, isFramework) 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 908fc47..4eb70aa 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/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/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 998b08b..b16b4aa 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 d3218db..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,6 +121,15 @@ public class TestDelegates extends TestCase { Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(), parameters); + // check the return type of the methods match. + assertTrue( + String.format("Delegate method %1$s.%2$s does not match the corresponding " + + "framework method which returns %3$s", + delegateClass.getName(), + getMethodName(delegateMethod), + originalMethod.getReturnType().getName()), + delegateMethod.getReturnType() == originalMethod.getReturnType()); + // check that the method has the annotation assertNotNull( 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/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java index 9a31705..3e75c9e 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java @@ -632,8 +632,8 @@ public class AsmAnalyzer { // field instruction @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - // name is the field's name. - considerName(name); + // owner is the class that declares the field. + considerName(owner); // desc is the field's descriptor (see Type). considerDesc(desc); } 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 79aa642..e0c05de 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,10 @@ 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", "android.content.res.TypedArray#getValueAt", "android.graphics.BitmapFactory#finishDecode", "android.os.Handler#sendMessageAtTime", diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java index c988c70..2016c0e 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java @@ -527,7 +527,8 @@ public class DependencyFinder { // field instruction @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - // name is the field's name. + // owner is the class that declares the field. + considerName(owner); // desc is the field's descriptor (see Type). considerDesc(desc); } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java index 2ef3d5f..7c3ab6f 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java @@ -115,6 +115,7 @@ public class Main { "android.database.ContentObserver", // for Digital clock "com.android.i18n.phonenumbers.*", // for TextView with autolink attribute "android.app.DatePickerDialog", // b.android.com/28318 + "android.app.TimePickerDialog", // b.android.com/61515 }, excludeClasses, new String[] { diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java index 7ec0d38..78e2c48 100644 --- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java +++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java @@ -83,6 +83,7 @@ public class AsmAnalyzerTest { "mock_android.dummy.InnerTest$MyStaticInnerClass", "mock_android.dummy.InnerTest$NotStaticInner1", "mock_android.dummy.InnerTest$NotStaticInner2", + "mock_android.util.EmptyArray", "mock_android.view.View", "mock_android.view.ViewGroup", "mock_android.view.ViewGroup$LayoutParams", @@ -217,15 +218,16 @@ public class AsmAnalyzerTest { TreeMap<String, ClassReader> in_deps = new TreeMap<String, ClassReader>(); TreeMap<String, ClassReader> out_deps = new TreeMap<String, ClassReader>(); - ClassReader cr = mAa.findClass("mock_android.widget.TableLayout", zipClasses, keep); + ClassReader cr = mAa.findClass("mock_android.widget.LinearLayout", zipClasses, keep); DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps); // get first level dependencies cr.accept(visitor, 0 /* flags */); assertArrayEquals(new String[] { + "mock_android.util.EmptyArray", "mock_android.view.ViewGroup", - "mock_android.widget.TableLayout$LayoutParams", + "mock_android.widget.LinearLayout$LayoutParams", }, out_deps.keySet().toArray()); @@ -255,7 +257,7 @@ public class AsmAnalyzerTest { assertArrayEquals(new String[] { }, out_deps.keySet().toArray()); assertArrayEquals(new String[] { - "mock_android.widget.TableLayout", + "mock_android.widget.LinearLayout", }, keep.keySet().toArray()); } } diff --git a/tools/layoutlib/create/tests/data/mock_android.jar b/tools/layoutlib/create/tests/data/mock_android.jar Binary files differindex 8dd0481..c6ca3c4 100644 --- a/tools/layoutlib/create/tests/data/mock_android.jar +++ b/tools/layoutlib/create/tests/data/mock_android.jar diff --git a/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java b/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java new file mode 100644 index 0000000..aaeebf6 --- /dev/null +++ b/tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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 mock_android.util; + +import java.lang.JavaClass; + +public class EmptyArray { + + public static final Object[] OBJECT = new Object[0]; +} diff --git a/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java index 3870a63..af56c4b 100644 --- a/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java +++ b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java @@ -16,11 +16,13 @@ package mock_android.widget; +import mock_android.util.EmptyArray; import mock_android.view.ViewGroup; public class LinearLayout extends ViewGroup { - public class LayoutParams extends mock_android.view.ViewGroup.LayoutParams { + Object[] mObjects = EmptyArray.OBJECT; + public class LayoutParams extends MarginLayoutParams { } |