diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:23 -0800 |
commit | b798689749c64baba81f02e10cf2157c747d6b46 (patch) | |
tree | da394a395ddb1a6cf69193314846b03fe47a397e /tools | |
parent | f013e1afd1e68af5e3b868c26a653bbfb39538f8 (diff) | |
download | frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.zip frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.tar.gz frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.tar.bz2 |
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'tools')
20 files changed, 616 insertions, 98 deletions
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp index 9d5937c..7c4963f 100644 --- a/tools/aapt/Images.cpp +++ b/tools/aapt/Images.cpp @@ -618,10 +618,151 @@ static bool patch_equals(Res_png_9patch& patch1, Res_png_9patch& patch2) { return true; } + +static void analyze_image(image_info &imageInfo, png_colorp rgbPalette, png_bytep alphaPalette, + int *paletteEntries, bool *hasTransparency, int *colorType, + png_bytepp outRows) +{ + int w = imageInfo.width; + int h = imageInfo.height; + bool trans = imageInfo.hasTransparency; + int i, j, rr, gg, bb, aa, idx; + uint32_t colors[256], col; + int num_colors = 0; + + bool isOpaque = true; + bool isPalette = true; + bool isGrayscale = true; + + // Scan the entire image and determine if: + // 1. Every pixel has R == G == B (grayscale) + // 2. Every pixel has A == 255 (opaque) + // 3. There are no more than 256 distinct RGBA colors + for (j = 0; j < h; j++) { + png_bytep row = imageInfo.rows[j]; + png_bytep out = outRows[j]; + for (i = 0; i < w; i++) { + rr = *row++; + gg = *row++; + bb = *row++; + aa = *row++; + if (!trans) { + // Ignore the actually byte and assume alpha == 255 + aa = 0xff; + } + + // Check if image is really grayscale + if (isGrayscale) { + if (rr != gg || rr != bb) { + isGrayscale = false; + } + } + + // Check if image is really opaque + if (isOpaque) { + if (aa != 0xff) { + isOpaque = false; + } + } + + // Check if image is really <= 256 colors + if (isPalette) { + col = (uint32_t) ((rr << 24) | (gg << 16) | (bb << 8) | aa); + bool match = false; + for (idx = 0; idx < num_colors; idx++) { + if (colors[idx] == col) { + match = true; + break; + } + } + + // Write the palette index for the pixel to outRows optimistically + // We might overwrite it later if we decide to encode as gray or + // gray + alpha + *out++ = idx; + if (!match) { + if (num_colors == 256) { + isPalette = false; + } else { + colors[num_colors++] = col; + } + } + } + } + } + + *paletteEntries = 0; + *hasTransparency = !isOpaque; + int bpp = isOpaque ? 3 : 4; + int paletteSize = w * h + bpp * num_colors; + + // Choose the best color type for the image. + // 1. Opaque gray - use COLOR_TYPE_GRAY at 1 byte/pixel + // 2. Gray + alpha - use COLOR_TYPE_PALETTE if the number of distinct combinations + // is sufficiently small, otherwise use COLOR_TYPE_GRAY_ALPHA + // 3. RGB(A) - use COLOR_TYPE_PALETTE if the number of distinct colors is sufficiently + // small, otherwise use COLOR_TYPE_RGB{_ALPHA} + if (isGrayscale) { + if (isOpaque) { + *colorType = PNG_COLOR_TYPE_GRAY; // 1 byte/pixel + } else { + // Use a simple heuristic to determine whether using a palette will + // save space versus using gray + alpha for each pixel. + // This doesn't take into account chunk overhead, filtering, LZ + // compression, etc. + if (isPalette && (paletteSize < 2 * w * h)) { + *colorType = PNG_COLOR_TYPE_PALETTE; // 1 byte/pixel + 4 bytes/color + } else { + *colorType = PNG_COLOR_TYPE_GRAY_ALPHA; // 2 bytes per pixel + } + } + } else if (isPalette && (paletteSize < bpp * w * h)) { + *colorType = PNG_COLOR_TYPE_PALETTE; + } else { + *colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA; + } + + // Perform postprocessing of the image or palette data based on the final + // color type chosen + + if (*colorType == PNG_COLOR_TYPE_PALETTE) { + // Create separate RGB and Alpha palettes and set the number of colors + *paletteEntries = num_colors; + + // Create the RGB and alpha palettes + for (int idx = 0; idx < num_colors; idx++) { + col = colors[idx]; + rgbPalette[idx].red = (png_byte) ((col >> 24) & 0xff); + rgbPalette[idx].green = (png_byte) ((col >> 16) & 0xff); + rgbPalette[idx].blue = (png_byte) ((col >> 8) & 0xff); + alphaPalette[idx] = (png_byte) (col & 0xff); + } + } else if (*colorType == PNG_COLOR_TYPE_GRAY || *colorType == PNG_COLOR_TYPE_GRAY_ALPHA) { + // If the image is gray or gray + alpha, compact the pixels into outRows + for (j = 0; j < h; j++) { + png_bytep row = imageInfo.rows[j]; + png_bytep out = outRows[j]; + for (i = 0; i < w; i++) { + rr = *row++; + gg = *row++; + bb = *row++; + aa = *row++; + + *out++ = rr; + if (!isOpaque) { + *out++ = aa; + } + } + } + } +} + + static void write_png(const char* imageName, png_structp write_ptr, png_infop write_info, image_info& imageInfo) { + bool optimize = true; png_uint_32 width, height; int color_type; int bit_depth, interlace_type, compression_type; @@ -629,17 +770,73 @@ static void write_png(const char* imageName, png_unknown_chunk unknowns[1]; + png_bytepp outRows = (png_bytepp) malloc((int) imageInfo.height * png_sizeof(png_bytep)); + if (outRows == (png_bytepp) 0) { + printf("Can't allocate output buffer!\n"); + exit(1); + } + for (i = 0; i < (int) imageInfo.height; i++) { + outRows[i] = (png_bytep) malloc(2 * (int) imageInfo.width); + if (outRows[i] == (png_bytep) 0) { + printf("Can't allocate output buffer!\n"); + exit(1); + } + } + png_set_compression_level(write_ptr, Z_BEST_COMPRESSION); - color_type = PNG_COLOR_MASK_COLOR; - if (imageInfo.hasTransparency) { - color_type |= PNG_COLOR_MASK_ALPHA; + NOISY(printf("Writing image %s: w = %d, h = %d, trans = %s\n", imageName, + (int) imageInfo.width, (int) imageInfo.height, + imageInfo.hasTransparency ? "true" : "false")); + + png_color rgbPalette[256]; + png_byte alphaPalette[256]; + bool hasTransparency; + int paletteEntries; + + if (optimize) { + analyze_image(imageInfo, rgbPalette, alphaPalette, &paletteEntries, &hasTransparency, + &color_type, outRows); + switch (color_type) { + case PNG_COLOR_TYPE_PALETTE: + NOISY(printf("Image %s has %d colors%s, using PNG_COLOR_TYPE_PALETTE\n", + imageName, paletteEntries, + hasTransparency ? " (with alpha)" : "")); + break; + case PNG_COLOR_TYPE_GRAY: + NOISY(printf("Image %s is opaque gray, using PNG_COLOR_TYPE_GRAY\n", imageName)); + break; + case PNG_COLOR_TYPE_GRAY_ALPHA: + NOISY(printf("Image %s is gray + alpha, using PNG_COLOR_TYPE_GRAY_ALPHA\n", imageName)); + break; + case PNG_COLOR_TYPE_RGB: + NOISY(printf("Image %s is opaque RGB, using PNG_COLOR_TYPE_RGB\n", imageName)); + break; + case PNG_COLOR_TYPE_RGB_ALPHA: + NOISY(printf("Image %s is RGB + alpha, using PNG_COLOR_TYPE_RGB_ALPHA\n", imageName)); + break; + } + } else { + // Force RGB or RGB_ALPHA color type, copy transparency from input + paletteEntries = 0; + hasTransparency = imageInfo.hasTransparency; + color_type = hasTransparency ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB; } png_set_IHDR(write_ptr, write_info, imageInfo.width, imageInfo.height, 8, color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + if (color_type == PNG_COLOR_TYPE_PALETTE) { + png_set_PLTE(write_ptr, write_info, rgbPalette, paletteEntries); + if (hasTransparency) { + png_set_tRNS(write_ptr, write_info, alphaPalette, paletteEntries, (png_color_16p) 0); + } + png_set_filter(write_ptr, 0, PNG_NO_FILTERS); + } else { + png_set_filter(write_ptr, 0, PNG_ALL_FILTERS); + } + if (imageInfo.is9Patch) { NOISY(printf("Adding 9-patch info...\n")); strcpy((char*)unknowns[0].name, "npTc"); @@ -659,15 +856,24 @@ static void write_png(const char* imageName, } png_write_info(write_ptr, write_info); - + if (!imageInfo.hasTransparency) { png_set_filler(write_ptr, 0, PNG_FILLER_AFTER); } - png_write_image(write_ptr, imageInfo.rows); + if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) { + png_write_image(write_ptr, imageInfo.rows); + } else { + png_write_image(write_ptr, outRows); + } png_write_end(write_ptr, write_info); + for (i = 0; i < (int) imageInfo.height; i++) { + free(outRows[i]); + } + free(outRows); + png_get_IHDR(write_ptr, write_info, &width, &height, &bit_depth, &color_type, &interlace_type, &compression_type, NULL); @@ -687,9 +893,9 @@ status_t preProcessImage(Bundle* bundle, const sp<AaptAssets>& assets, return NO_ERROR; } - // Example of renaming a file: - //*outNewLeafName = file->getPath().getBasePath().getFileName(); - //outNewLeafName->append(".nupng"); + // Example of renaming a file: + //*outNewLeafName = file->getPath().getBasePath().getFileName(); + //outNewLeafName->append(".nupng"); String8 printableName(file->getPrintableSource()); diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp index 0df4606..5d9e140 100644 --- a/tools/aapt/Package.cpp +++ b/tools/aapt/Package.cpp @@ -22,7 +22,7 @@ static const char* kExcludeExtension = ".EXCLUDE"; static const char* kNoCompressExt[] = { ".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg", ".aac", - ".mpg", ".mpeg", ".mid", ".midi", ".smf", + ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet", ".rtttl", ".imy", ".xmf", ".mp4", ".m4a", ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2", ".amr", ".awb", ".wma", ".wmv" diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 3641458..33f8f72 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -115,7 +115,7 @@ static const flag_entry gFormatFlags[] = { "a floating point value, such as \"<code>1.2</code>\"."}, { dimensionArray, sizeof(dimensionArray)/2, ResTable_map::TYPE_DIMENSION, "a dimension value, which is a floating point number appended with a unit such as \"<code>14.5sp</code>\".\n" - "Available units are: px (pixels), db (density-independent pixels), sp (scaled pixels based on preferred font size),\n" + "Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size),\n" "in (inches), mm (millimeters)." }, { fractionArray, sizeof(fractionArray)/2, ResTable_map::TYPE_FRACTION, "a fractional value, which is a floating point number appended with either % or %p, such as \"<code>14.5%</code>\".\n" @@ -3479,4 +3479,3 @@ bool ResourceTable::getItemValue( } return res; } - diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp index 927d21e..dc61567 100644 --- a/tools/aidl/aidl.cpp +++ b/tools/aidl/aidl.cpp @@ -10,6 +10,8 @@ #include <sys/stat.h> #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <map> #ifdef HAVE_MS_C_RUNTIME diff --git a/tools/aidl/generate_java.cpp b/tools/aidl/generate_java.cpp index 7f84ff4..e3c0af0 100644 --- a/tools/aidl/generate_java.cpp +++ b/tools/aidl/generate_java.cpp @@ -2,6 +2,8 @@ #include "AST.h" #include "Type.h" #include <stdio.h> +#include <stdlib.h> +#include <string.h> // ================================================= class VariableFactory diff --git a/tools/aidl/options.cpp b/tools/aidl/options.cpp index a890556..57b10ae 100644 --- a/tools/aidl/options.cpp +++ b/tools/aidl/options.cpp @@ -1,6 +1,10 @@ #include "options.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + static int usage() { diff --git a/tools/aidl/search_path.cpp b/tools/aidl/search_path.cpp index 3c4e14b..ffb6cb2 100644 --- a/tools/aidl/search_path.cpp +++ b/tools/aidl/search_path.cpp @@ -1,6 +1,7 @@ #include <unistd.h> #include "search_path.h" #include "options.h" +#include <string.h> #ifdef HAVE_MS_C_RUNTIME #include <io.h> diff --git a/tools/aidl/search_path.h b/tools/aidl/search_path.h index 8d85d81..2bf94b1 100644 --- a/tools/aidl/search_path.h +++ b/tools/aidl/search_path.h @@ -5,6 +5,7 @@ #if __cplusplus #include <vector> +#include <string> using namespace std; extern "C" { #endif diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index b898192..f5087d9 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -28,7 +28,7 @@ import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo; import com.android.layoutlib.bridge.LayoutResult.LayoutViewInfo; import com.android.ninepatch.NinePatch; import com.android.tools.layoutlib.create.OverrideMethod; -import com.android.tools.layoutlib.create.OverrideMethod.MethodListener; +import com.android.tools.layoutlib.create.MethodAdapter; import android.graphics.Bitmap; import android.graphics.Rect; @@ -101,13 +101,10 @@ public final class Bridge implements ILayoutBridge { new HashMap<String, NinePatch>(); private static Map<String, Map<String, Integer>> sEnumValueMap; - - private final static MethodListener sNullMethodListener = new MethodListener() { - public void onInvoke(String signature, boolean isNative, Object caller) { - // pass - } - }; + /** + * A default logger than prints to stdout/stderr. + */ private final static ILayoutLog sDefaultLogger = new ILayoutLog() { public void error(String message) { System.err.println(message); @@ -127,21 +124,16 @@ public final class Bridge implements ILayoutBridge { } }; - /** Logger defined during a compute layout operation. */ + /** + * Logger defined during a compute layout operation. + * <p/> + * This logger is generally set to {@link #sDefaultLogger} except during rendering + * operations when it might be set to a specific provided logger. + * <p/> + * To change this value, use a block synchronized on {@link #sDefaultLogger}. + */ private static ILayoutLog sLogger = sDefaultLogger; - private final static String[] IGNORED_STATIC_METHODS = new String[] { - "android.content.res.AssetManager#init()V", - "android.content.res.AssetManager#deleteTheme(I)V", - "android.content.res.AssetManager#destroy()V", - "android.graphics._Original_Paint#native_init()I", - "android.graphics.Bitmap#nativeRecycle(I)V", - "android.graphics.Bitmap#nativeDestructor(I)V", - "android.view.animation.Transformation#<clinit>()V", - "android.view.animation.Transformation#<init>()V", - "android.view.animation.Transformation#clear()V", - }; - /* * (non-Javadoc) * @see com.android.layoutlib.api.ILayoutBridge#getApiLevel() @@ -163,32 +155,52 @@ public final class Bridge implements ILayoutBridge { private static synchronized boolean sinit(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) { - // set an empty method listener for some known static methods we don't care about. - for (String method : IGNORED_STATIC_METHODS) { - OverrideMethod.setMethodListener(method, sNullMethodListener); - } - - - // set a the default listener for the rest of the static methods. It prints out - // missing stub methods and then throws an exception for native methods if the - // environment variable DEBUG_LAYOUT is not defined. - OverrideMethod.setDefaultListener(new MethodListener() { - public void onInvoke(String signature, boolean isNative, Object caller) { - if (isNative) { + // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener + // on static (native) methods which prints the signature on the console and + // throws an exception. + // This is useful when testing the rendering in ADT to identify static native + // methods that are ignored -- layoutlib_create makes them returns 0/false/null + // which is generally OK yet might be a problem, so this is how you'd find out. + // + // Currently layoutlib_create only overrides static native method. + // Static non-natives are not overridden and thus do not get here. + final String debug = System.getenv("DEBUG_LAYOUT"); + if (debug != null && !debug.equals("0") && !debug.equals("false")) { + + OverrideMethod.setDefaultListener(new MethodAdapter() { + @Override + public void onInvokeV(String signature, boolean isNative, Object caller) { if (sLogger != null) { - sLogger.error("Missing Stub: " + signature + - (isNative ? " (native)" : "")); + synchronized (sDefaultLogger) { + sLogger.error("Missing Stub: " + signature + + (isNative ? " (native)" : "")); + } } - if (System.getenv("DEBUG_LAYOUT") == null) { - // TODO throwing this exception doesn't seem that useful. It breaks + if (debug.equalsIgnoreCase("throw")) { + // Throwing this exception doesn't seem that useful. It breaks // the layout editor yet doesn't display anything meaningful to the - // user. Having the error in the console is just as useful. + // user. Having the error in the console is just as useful. We'll + // throw it only if the environment variable is "throw" or "THROW". throw new StaticMethodNotImplementedException(signature); } } + }); + } + + // Override View.isInEditMode to return true. + // + // This allows custom views that are drawn in the Graphical Layout Editor to adapt their + // rendering for preview. Most important this let custom views know that they can't expect + // the rest of their activities to be alive. + OverrideMethod.setMethodListener("android.view.View#isInEditMode()Z", + new MethodAdapter() { + @Override + public int onInvokeI(String signature, boolean isNative, Object caller) { + return 1; + } } - }); + ); // load the fonts. FontLoader fontLoader = FontLoader.create(fontOsLocation); @@ -283,7 +295,9 @@ public final class Bridge implements ILayoutBridge { logger = sDefaultLogger; } - sLogger = logger; + synchronized (sDefaultLogger) { + sLogger = logger; + } // find the current theme and compute the style inheritance map Map<IStyleResourceValue, IStyleResourceValue> styleParentMap = @@ -368,7 +382,9 @@ public final class Bridge implements ILayoutBridge { t.getClass().getSimpleName() + ": " + t.getMessage()); } finally { // Remove the global logger - sLogger = sDefaultLogger; + synchronized (sDefaultLogger) { + sLogger = sDefaultLogger; + } } } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java index b4e2c2b..1adcc17 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java @@ -68,7 +68,8 @@ public class AsmGenerator { * * @param log Output logger. * @param osDestJar The path of the destination JAR to create. - * @param stubMethods The list of methods to stub out + * @param stubMethods The list of methods to stub out. Each entry must be in the form + * "package.package.OuterClass$InnerClass#MethodName". * @param renameClasses The list of classes to rename, must be an even list: the binary FQCN * of class to replace followed by the new FQCN. * @param deleteReturns List of classes for which the methods returning them should be deleted. 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 13443d5..76bd8d4 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 @@ -45,9 +45,11 @@ public class Main { AsmGenerator agen = new AsmGenerator(log, osDestJar[0], new Class<?>[] { // classes to inject in the final JAR OverrideMethod.class, - OverrideMethod.MethodListener.class + MethodListener.class, + MethodAdapter.class }, new String[] { // methods to force override + "android.view.View#isInEditMode", "android.content.res.Resources$Theme#obtainStyledAttributes", }, new String[] { // classes to rename (so that we can replace them in layoutlib) diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java new file mode 100644 index 0000000..627ea17 --- /dev/null +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.tools.layoutlib.create; + + +/** + * An adapter to make it easier to use {@link MethodListener}. + * <p/> + * The adapter calls the void {@link #onInvokeV(String, boolean, Object)} listener + * for all types (I, L, F, D and A), returning 0 or null as appropriate. + */ +public class MethodAdapter implements MethodListener { + /** + * A stub method is being invoked. + * <p/> + * Known limitation: caller arguments are not available. + * + * @param signature The signature of the method being invoked, composed of the + * binary class name followed by the method descriptor (aka argument + * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V". + * @param isNative True if the method was a native method. + * @param caller The calling object. Null for static methods, "this" for instance methods. + */ + public void onInvokeV(String signature, boolean isNative, Object caller) { + } + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar. + * @see #onInvokeV(String, boolean, Object) + * @return an integer, or a boolean, or a short or a byte. + */ + public int onInvokeI(String signature, boolean isNative, Object caller) { + onInvokeV(signature, isNative, caller); + return 0; + } + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long. + * @see #onInvokeV(String, boolean, Object) + * @return a long. + */ + public long onInvokeL(String signature, boolean isNative, Object caller) { + onInvokeV(signature, isNative, caller); + return 0; + } + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float. + * @see #onInvokeV(String, boolean, Object) + * @return a float. + */ + public float onInvokeF(String signature, boolean isNative, Object caller) { + onInvokeV(signature, isNative, caller); + return 0; + } + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double. + * @see #onInvokeV(String, boolean, Object) + * @return a double. + */ + public double onInvokeD(String signature, boolean isNative, Object caller) { + onInvokeV(signature, isNative, caller); + return 0; + } + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object. + * @see #onInvokeV(String, boolean, Object) + * @return an object. + */ + public Object onInvokeA(String signature, boolean isNative, Object caller) { + onInvokeV(signature, isNative, caller); + return null; + } +} + diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java new file mode 100644 index 0000000..6fc2b24 --- /dev/null +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.tools.layoutlib.create; + + +/** + * Interface to allow a method invocation to be listened upon. + * <p/> + * This is used by {@link OverrideMethod} to register a listener for methods that + * have been stubbed by the {@link AsmGenerator}. At runtime the stub will call either a + * default global listener or a specific listener based on the method signature. + */ +public interface MethodListener { + /** + * A stub method is being invoked. + * <p/> + * Known limitation: caller arguments are not available. + * + * @param signature The signature of the method being invoked, composed of the + * binary class name followed by the method descriptor (aka argument + * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V". + * @param isNative True if the method was a native method. + * @param caller The calling object. Null for static methods, "this" for instance methods. + */ + public void onInvokeV(String signature, boolean isNative, Object caller); + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar. + * @see #onInvokeV(String, boolean, Object) + * @return an integer, or a boolean, or a short or a byte. + */ + public int onInvokeI(String signature, boolean isNative, Object caller); + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long. + * @see #onInvokeV(String, boolean, Object) + * @return a long. + */ + public long onInvokeL(String signature, boolean isNative, Object caller); + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float. + * @see #onInvokeV(String, boolean, Object) + * @return a float. + */ + public float onInvokeF(String signature, boolean isNative, Object caller); + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double. + * @see #onInvokeV(String, boolean, Object) + * @return a double. + */ + public double onInvokeD(String signature, boolean isNative, Object caller); + + /** + * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object. + * @see #onInvokeV(String, boolean, Object) + * @return an object. + */ + public Object onInvokeA(String signature, boolean isNative, Object caller); +} + diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java index b061a15..a6aff99 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java @@ -20,27 +20,13 @@ import java.util.HashMap; /** * Allows stub methods from LayoutLib to be overriden at runtime. + * <p/> + * Implementation note: all types required by this class(inner/outer classes & interfaces) + * must be referenced by the injectClass argument to {@link AsmGenerator} in Main.java; + * Otherwise they won't be accessible in layoutlib.jar at runtime. */ public final class OverrideMethod { - /** - * Interface to allow a method invocation to be listend upon. - */ - public interface MethodListener { - /** - * A stub method is being invoked. - * <p/> - * Known limitation: caller arguments are not available. Return value cannot be set. - * - * @param signature The signature of the method being invoked, composed of the - * binary class name followed by the method descriptor (aka argument - * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V". - * @param isNative True if the method was a native method. - * @param caller The calling object. Null for static methods, "this" for instance methods. - */ - public void onInvoke(String signature, boolean isNative, Object caller); - } - /** Map of method overridden. */ private static HashMap<String, MethodListener> sMethods = new HashMap<String, MethodListener>(); /** Default listener for all method not listed in sMethods. Nothing if null. */ @@ -71,7 +57,9 @@ public final class OverrideMethod { } /** - * Invoke the specific listener for the given signature or the default one if defined. + * Invokes the specific listener for the given signature or the default one if defined. + * <p/> + * This version invokes the method listener for the void return type. * <p/> * Note: this is not intended to be used by the LayoutLib Bridge. It is intended to be called * by the stubbed methods generated by the LayoutLib_create tool. @@ -82,12 +70,82 @@ public final class OverrideMethod { * @param isNative True if the method was a native method. * @param caller The calling object. Null for static methods, "this" for instance methods. */ - public static void invoke(String signature, boolean isNative, Object caller) { + public static void invokeV(String signature, boolean isNative, Object caller) { + MethodListener i = sMethods.get(signature); + if (i != null) { + i.onInvokeV(signature, isNative, caller); + } else if (sDefaultListener != null) { + sDefaultListener.onInvokeV(signature, isNative, caller); + } + } + + /** + * Invokes the specific listener for the int return type. + * @see #invokeV(String, boolean, Object) + */ + public static int invokeI(String signature, boolean isNative, Object caller) { + MethodListener i = sMethods.get(signature); + if (i != null) { + return i.onInvokeI(signature, isNative, caller); + } else if (sDefaultListener != null) { + return sDefaultListener.onInvokeI(signature, isNative, caller); + } + return 0; + } + + /** + * Invokes the specific listener for the long return type. + * @see #invokeV(String, boolean, Object) + */ + public static long invokeL(String signature, boolean isNative, Object caller) { + MethodListener i = sMethods.get(signature); + if (i != null) { + return i.onInvokeL(signature, isNative, caller); + } else if (sDefaultListener != null) { + return sDefaultListener.onInvokeL(signature, isNative, caller); + } + return 0; + } + + /** + * Invokes the specific listener for the float return type. + * @see #invokeV(String, boolean, Object) + */ + public static float invokeF(String signature, boolean isNative, Object caller) { + MethodListener i = sMethods.get(signature); + if (i != null) { + return i.onInvokeF(signature, isNative, caller); + } else if (sDefaultListener != null) { + return sDefaultListener.onInvokeF(signature, isNative, caller); + } + return 0; + } + + /** + * Invokes the specific listener for the double return type. + * @see #invokeV(String, boolean, Object) + */ + public static double invokeD(String signature, boolean isNative, Object caller) { + MethodListener i = sMethods.get(signature); + if (i != null) { + return i.onInvokeD(signature, isNative, caller); + } else if (sDefaultListener != null) { + return sDefaultListener.onInvokeD(signature, isNative, caller); + } + return 0; + } + + /** + * Invokes the specific listener for the object return type. + * @see #invokeV(String, boolean, Object) + */ + public static Object invokeA(String signature, boolean isNative, Object caller) { MethodListener i = sMethods.get(signature); if (i != null) { - i.onInvoke(signature, isNative, caller); + return i.onInvokeA(signature, isNative, caller); } else if (sDefaultListener != null) { - sDefaultListener.onInvoke(signature, isNative, caller); + return sDefaultListener.onInvokeA(signature, isNative, caller); } + return null; } } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java index 9bb64bd..9a57a4a 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java @@ -74,23 +74,14 @@ class StubMethodAdapter implements MethodVisitor { } else { mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); } - mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, - "com/android/tools/layoutlib/create/OverrideMethod", - "invoke", - "(Ljava/lang/String;ZLjava/lang/Object;)V"); - } - private void generateReturn() { - /* Generates one of, depending on the return type: - * return; - * return 0; - * return 0L; - * return 0.0f; - * return 0.0; - * return null; - */ - switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) { + int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID; + switch(sort) { case Type.VOID: + mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/android/tools/layoutlib/create/OverrideMethod", + "invokeV", + "(Ljava/lang/String;ZLjava/lang/Object;)V"); mParentVisitor.visitInsn(Opcodes.RETURN); break; case Type.BOOLEAN: @@ -98,27 +89,86 @@ class StubMethodAdapter implements MethodVisitor { case Type.BYTE: case Type.SHORT: case Type.INT: - mParentVisitor.visitInsn(Opcodes.ICONST_0); + mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/android/tools/layoutlib/create/OverrideMethod", + "invokeI", + "(Ljava/lang/String;ZLjava/lang/Object;)I"); + switch(sort) { + case Type.BOOLEAN: + Label l1 = new Label(); + mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1); + mParentVisitor.visitInsn(Opcodes.ICONST_1); + mParentVisitor.visitInsn(Opcodes.IRETURN); + mParentVisitor.visitLabel(l1); + mParentVisitor.visitInsn(Opcodes.ICONST_0); + break; + case Type.CHAR: + mParentVisitor.visitInsn(Opcodes.I2C); + break; + case Type.BYTE: + mParentVisitor.visitInsn(Opcodes.I2B); + break; + case Type.SHORT: + mParentVisitor.visitInsn(Opcodes.I2S); + break; + } mParentVisitor.visitInsn(Opcodes.IRETURN); break; case Type.LONG: - mParentVisitor.visitInsn(Opcodes.LCONST_0); + mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/android/tools/layoutlib/create/OverrideMethod", + "invokeL", + "(Ljava/lang/String;ZLjava/lang/Object;)J"); mParentVisitor.visitInsn(Opcodes.LRETURN); break; case Type.FLOAT: - mParentVisitor.visitInsn(Opcodes.FCONST_0); + mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/android/tools/layoutlib/create/OverrideMethod", + "invokeF", + "(Ljava/lang/String;ZLjava/lang/Object;)F"); mParentVisitor.visitInsn(Opcodes.FRETURN); break; case Type.DOUBLE: - mParentVisitor.visitInsn(Opcodes.DCONST_0); + mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/android/tools/layoutlib/create/OverrideMethod", + "invokeD", + "(Ljava/lang/String;ZLjava/lang/Object;)D"); mParentVisitor.visitInsn(Opcodes.DRETURN); break; case Type.ARRAY: case Type.OBJECT: - mParentVisitor.visitInsn(Opcodes.ACONST_NULL); + mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, + "com/android/tools/layoutlib/create/OverrideMethod", + "invokeA", + "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;"); + mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName()); mParentVisitor.visitInsn(Opcodes.ARETURN); break; } + + } + + private void generatePop() { + /* Pops the stack, depending on the return type. + */ + switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) { + case Type.VOID: + break; + case Type.BOOLEAN: + case Type.CHAR: + case Type.BYTE: + case Type.SHORT: + case Type.INT: + case Type.FLOAT: + case Type.ARRAY: + case Type.OBJECT: + mParentVisitor.visitInsn(Opcodes.POP); + break; + case Type.LONG: + case Type.DOUBLE: + mParentVisitor.visitInsn(Opcodes.POP2); + break; + } } /* Pass down to visitor writer. In this implementation, either do nothing. */ @@ -134,7 +184,6 @@ class StubMethodAdapter implements MethodVisitor { public void visitMaxs(int maxStack, int maxLocals) { if (!mIsInitMethod && !mMessageGenerated) { generateInvoke(); - generateReturn(); mMessageGenerated = true; } mParentVisitor.visitMaxs(maxStack, maxLocals); @@ -148,7 +197,6 @@ class StubMethodAdapter implements MethodVisitor { public void visitEnd() { if (!mIsInitMethod && !mMessageGenerated) { generateInvoke(); - generateReturn(); mMessageGenerated = true; mParentVisitor.visitMaxs(1, 1); } @@ -198,10 +246,13 @@ class StubMethodAdapter implements MethodVisitor { case Opcodes.FRETURN: case Opcodes.IRETURN: case Opcodes.LRETURN: + // Pop the last word from the stack since invoke will generate its own return. + generatePop(); generateInvoke(); mMessageGenerated = true; + default: + mParentVisitor.visitInsn(opcode); } - mParentVisitor.visitInsn(opcode); } } diff --git a/tools/localize/Perforce.cpp b/tools/localize/Perforce.cpp index 3184dfc..3425668 100644 --- a/tools/localize/Perforce.cpp +++ b/tools/localize/Perforce.cpp @@ -1,5 +1,7 @@ #include "Perforce.h" #include "log.h" +#include <string.h> +#include <stdlib.h> #include <sstream> #include <sys/types.h> #include <unistd.h> diff --git a/tools/localize/XLIFFFile.cpp b/tools/localize/XLIFFFile.cpp index 5da05a2..51f81de 100644 --- a/tools/localize/XLIFFFile.cpp +++ b/tools/localize/XLIFFFile.cpp @@ -1,5 +1,6 @@ #include "XLIFFFile.h" +#include <algorithm> #include <sys/time.h> #include <time.h> diff --git a/tools/localize/XMLHandler.cpp b/tools/localize/XMLHandler.cpp index 64af7af..3fab211 100644 --- a/tools/localize/XMLHandler.cpp +++ b/tools/localize/XMLHandler.cpp @@ -1,5 +1,6 @@ #include "XMLHandler.h" +#include <algorithm> #include <expat.h> #include <stdio.h> #include <string.h> diff --git a/tools/localize/file_utils.cpp b/tools/localize/file_utils.cpp index 9431709..bb82a9c 100644 --- a/tools/localize/file_utils.cpp +++ b/tools/localize/file_utils.cpp @@ -1,3 +1,6 @@ +#include <string.h> +#include <stdlib.h> +#include <unistd.h> #include "file_utils.h" #include "Perforce.h" #include <sys/fcntl.h> diff --git a/tools/localize/localize.cpp b/tools/localize/localize.cpp index d03c811..c0d84cc 100644 --- a/tools/localize/localize.cpp +++ b/tools/localize/localize.cpp @@ -10,6 +10,7 @@ #include <host/pseudolocalize.h> +#include <stdlib.h> #include <stdarg.h> #include <sstream> #include <stdio.h> |