From ac1e59d887651220f5367cc7fa4207b34eab774d Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Tue, 11 Aug 2009 13:12:34 -0700 Subject: donut snapshot --- tools/aidl/AST.cpp | 8 ++++++-- tools/aidl/AST.h | 2 ++ tools/aidl/generate_java.cpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/aidl/AST.cpp b/tools/aidl/AST.cpp index 91802a9..85ca5da 100755 --- a/tools/aidl/AST.cpp +++ b/tools/aidl/AST.cpp @@ -6,6 +6,10 @@ WriteModifiers(FILE* to, int mod, int mask) { int m = mod & mask; + if (m & OVERRIDE) { + fprintf(to, "@Override "); + } + if ((m & SCOPE_MASK) == PUBLIC) { fprintf(to, "public "); } @@ -79,7 +83,7 @@ Field::Write(FILE* to) if (this->comment.length() != 0) { fprintf(to, "%s\n", this->comment.c_str()); } - WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL); + WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL | OVERRIDE); fprintf(to, "%s %s", this->variable->type->QualifiedName().c_str(), this->variable->name.c_str()); if (this->value.length() != 0) { @@ -674,7 +678,7 @@ Method::Write(FILE* to) fprintf(to, "%s\n", this->comment.c_str()); } - WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL); + WriteModifiers(to, this->modifiers, SCOPE_MASK | STATIC | FINAL | OVERRIDE); if (this->returnType != NULL) { string dim; diff --git a/tools/aidl/AST.h b/tools/aidl/AST.h index aec2164..3156356 100755 --- a/tools/aidl/AST.h +++ b/tools/aidl/AST.h @@ -22,6 +22,8 @@ enum { FINAL = 0x00000020, ABSTRACT = 0x00000040, + OVERRIDE = 0x00000100, + ALL_MODIFIERS = 0xffffffff }; diff --git a/tools/aidl/generate_java.cpp b/tools/aidl/generate_java.cpp index e3c0af0..622b691 100644 --- a/tools/aidl/generate_java.cpp +++ b/tools/aidl/generate_java.cpp @@ -103,7 +103,7 @@ StubClass::StubClass(Type* type, Type* interfaceType) this->transact_reply = new Variable(PARCEL_TYPE, "reply"); this->transact_flags = new Variable(INT_TYPE, "flags"); Method* onTransact = new Method; - onTransact->modifiers = PUBLIC; + onTransact->modifiers = PUBLIC | OVERRIDE; onTransact->returnType = BOOLEAN_TYPE; onTransact->name = "onTransact"; onTransact->parameters.push_back(this->transact_code); -- cgit v1.1 From 72b1f379d5c97c8ff31d2201e78215af777d6bda Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Mon, 31 Aug 2009 09:17:57 -0700 Subject: donut snapshot --- tools/aapt/Command.cpp | 5 + .../bridge/src/android/graphics/Bitmap.java | 32 +- .../bridge/src/android/graphics/Canvas.java | 1176 ++++++++++++++++++++ .../bridge/src/android/graphics/Matrix.java | 55 +- .../bridge/src/android/os/ServiceManager.java | 72 ++ .../view/accessibility/AccessibilityManager.java | 95 ++ .../src/com/android/layoutlib/bridge/Bridge.java | 46 +- .../com/android/layoutlib/bridge/BridgeCanvas.java | 1099 ------------------ .../android/layoutlib/bridge/BridgeConstants.java | 5 +- .../android/layoutlib/bridge/BridgeContext.java | 228 ++-- .../android/layoutlib/bridge/BridgeResources.java | 142 ++- .../layoutlib/bridge/NinePatchDrawable.java | 28 +- .../com/android/tools/layoutlib/create/Main.java | 23 +- tools/preload/20090811.compiled | Bin 0 -> 15943336 bytes tools/preload/Android.mk | 2 +- tools/preload/ClassRank.java | 53 - tools/preload/LoadedClass.java | 65 +- tools/preload/MemoryUsage.java | 37 +- tools/preload/Policy.java | 89 +- tools/preload/PrintCsv.java | 110 +- tools/preload/PrintHtmlDiff.java | 142 +++ tools/preload/Proc.java | 101 +- tools/preload/Root.java | 2 +- tools/preload/WritePreloadedClassFile.java | 144 ++- tools/preload/loadclass/LoadClass.java | 4 + tools/preload/preload.iml | 5 +- tools/preload/preload.ipr | 68 +- tools/preload/sorttable.js | 493 ++++++++ 28 files changed, 2620 insertions(+), 1701 deletions(-) create mode 100644 tools/layoutlib/bridge/src/android/graphics/Canvas.java create mode 100644 tools/layoutlib/bridge/src/android/os/ServiceManager.java create mode 100644 tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeCanvas.java create mode 100644 tools/preload/20090811.compiled delete mode 100644 tools/preload/ClassRank.java create mode 100644 tools/preload/PrintHtmlDiff.java create mode 100644 tools/preload/sorttable.js (limited to 'tools') diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index e04491d..5f80ade 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -321,6 +321,7 @@ enum { LABEL_ATTR = 0x01010001, ICON_ATTR = 0x01010002, MIN_SDK_VERSION_ATTR = 0x0101020c, + MAX_SDK_VERSION_ATTR = 0x01010271, REQ_TOUCH_SCREEN_ATTR = 0x01010227, REQ_KEYBOARD_TYPE_ATTR = 0x01010228, REQ_HARD_KEYBOARD_ATTR = 0x01010229, @@ -585,6 +586,10 @@ int doDump(Bundle* bundle) targetSdk = code; printf("sdkVersion:'%d'\n", code); } + code = getIntegerAttribute(tree, MAX_SDK_VERSION_ATTR, NULL, -1); + if (code != -1) { + printf("maxSdkVersion:'%d'\n", code); + } code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); if (error != "") { error = ""; diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap.java index 6bc01b1..7dde634 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap.java @@ -16,7 +16,6 @@ package android.graphics; -import com.android.layoutlib.bridge.BridgeCanvas; import java.awt.image.BufferedImage; import java.io.File; @@ -25,15 +24,15 @@ import java.io.IOException; import javax.imageio.ImageIO; public final class Bitmap extends _Original_Bitmap { - + private BufferedImage mImage; public Bitmap(File input) throws IOException { super(1, true, null); - + mImage = ImageIO.read(input); } - + Bitmap(BufferedImage image) { super(1, true, null); mImage = image; @@ -42,9 +41,9 @@ public final class Bitmap extends _Original_Bitmap { public BufferedImage getImage() { return mImage; } - + // ----- overriden methods - + public enum Config { // these native values must match up with the enum in SkBitmap.h ALPHA_8 (2), @@ -56,27 +55,26 @@ public final class Bitmap extends _Original_Bitmap { this.nativeInt = ni; } final int nativeInt; - + /* package */ static Config nativeToConfig(int ni) { return sConfigs[ni]; } - + private static Config sConfigs[] = { null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888 }; } - @Override public int getWidth() { return mImage.getWidth(); } - + @Override public int getHeight() { return mImage.getHeight(); } - + /** * Returns an immutable bitmap from the source bitmap. The new bitmap may * be the same object as source, or a copy may have been made. @@ -100,7 +98,7 @@ public final class Bitmap extends _Original_Bitmap { int width, int height) { return new Bitmap(source.mImage.getSubimage(x, y, width, height)); } - + /** * Returns an immutable bitmap from subset of the source bitmap, * transformed by the optional matrix. @@ -158,7 +156,7 @@ public final class Bitmap extends _Original_Bitmap { neww = Math.round(deviceR.width()); newh = Math.round(deviceR.height()); - BridgeCanvas canvas = new BridgeCanvas(neww, newh); + Canvas canvas = new Canvas(neww, newh); canvas.translate(-deviceR.left, -deviceR.top); canvas.concat(m); @@ -169,10 +167,10 @@ public final class Bitmap extends _Original_Bitmap { } canvas.drawBitmap(source, srcR, dstR, paint); - + return new Bitmap(canvas.getImage()); } - + /** * Returns a mutable bitmap with the specified width and height. * @@ -184,7 +182,7 @@ public final class Bitmap extends _Original_Bitmap { public static Bitmap createBitmap(int width, int height, Config config) { return new Bitmap(new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)); } - + /** * Returns a immutable bitmap with the specified width and height, with each * pixel value set to the corresponding value in the colors array. @@ -215,7 +213,7 @@ public final class Bitmap extends _Original_Bitmap { || (lastScanline + width > length)) { throw new ArrayIndexOutOfBoundsException(); } - + // TODO: create an immutable bitmap... throw new UnsupportedOperationException(); } diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java new file mode 100644 index 0000000..3fa1d1d --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java @@ -0,0 +1,1176 @@ +/* + * 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 android.graphics; + +import com.android.layoutlib.api.ILayoutLog; + +import android.graphics.DrawFilter; +import android.graphics.Picture; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; +import android.graphics.Xfermode; +import android.graphics.Paint.Align; +import android.graphics.Paint.Style; +import android.graphics.Region.Op; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.Stack; + +import javax.microedition.khronos.opengles.GL; + +/** + * Re-implementation of the Canvas, 100% in java on top of a BufferedImage. + */ +public class Canvas extends _Original_Canvas { + + private BufferedImage mBufferedImage; + private final Stack mGraphicsStack = new Stack(); + private final ILayoutLog mLogger; + + public Canvas() { + mLogger = null; + // the mBufferedImage will be taken from a bitmap in #setBitmap() + } + + public Canvas(Bitmap bitmap) { + mLogger = null; + mBufferedImage = bitmap.getImage(); + mGraphicsStack.push(mBufferedImage.createGraphics()); + } + + public Canvas(int nativeCanvas) { + mLogger = null; + throw new UnsupportedOperationException("Can't create Canvas(int)"); + } + + public Canvas(javax.microedition.khronos.opengles.GL gl) { + mLogger = null; + throw new UnsupportedOperationException("Can't create Canvas(javax.microedition.khronos.opengles.GL)"); + } + + // custom constructors for our use. + public Canvas(int width, int height, ILayoutLog logger) { + mLogger = logger; + mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + mGraphicsStack.push(mBufferedImage.createGraphics()); + } + + public Canvas(int width, int height) { + this(width, height, null /* logger*/); + } + + // custom mehtods + public BufferedImage getImage() { + return mBufferedImage; + } + + public Graphics2D getGraphics2d() { + return mGraphicsStack.peek(); + } + + public void dispose() { + while (mGraphicsStack.size() > 0) { + mGraphicsStack.pop().dispose(); + } + } + + /** + * Creates a new {@link Graphics2D} based on the {@link Paint} parameters. + *

The object must be disposed ({@link Graphics2D#dispose()}) after being used. + */ + private Graphics2D getNewGraphics(Paint paint, Graphics2D g) { + // make new one + g = (Graphics2D)g.create(); + g.setColor(new Color(paint.getColor())); + int alpha = paint.getAlpha(); + float falpha = alpha / 255.f; + + Xfermode xfermode = paint.getXfermode(); + if (xfermode instanceof PorterDuffXfermode) { + PorterDuff.Mode mode = ((PorterDuffXfermode)xfermode).getMode(); + + setModeInGraphics(mode, g, falpha); + } else { + if (mLogger != null && xfermode != null) { + mLogger.warning(String.format( + "Xfermode '%1$s' is not supported in the Layout Editor.", + xfermode.getClass().getCanonicalName())); + } + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); + } + + Shader shader = paint.getShader(); + if (shader instanceof LinearGradient) { + g.setPaint(((LinearGradient)shader).getPaint()); + } else { + if (mLogger != null && shader != null) { + mLogger.warning(String.format( + "Shader '%1$s' is not supported in the Layout Editor.", + shader.getClass().getCanonicalName())); + } + } + + return g; + } + + private void setModeInGraphics(PorterDuff.Mode mode, Graphics2D g, float falpha) { + switch (mode) { + case CLEAR: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha)); + break; + case DARKEN: + break; + case DST: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, falpha)); + break; + case DST_ATOP: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha)); + break; + case DST_IN: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha)); + break; + case DST_OUT: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha)); + break; + case DST_OVER: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha)); + break; + case LIGHTEN: + break; + case MULTIPLY: + break; + case SCREEN: + break; + case SRC: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, falpha)); + break; + case SRC_ATOP: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha)); + break; + case SRC_IN: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha)); + break; + case SRC_OUT: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha)); + break; + case SRC_OVER: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); + break; + case XOR: + g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, falpha)); + break; + } + } + + + // -------------------- + // OVERRIDEN ENUMS + // This is needed since we rename Canvas into _Original_Canvas + // -------------------- + + public enum EdgeType { + BW(0), //!< treat edges by just rounding to nearest pixel boundary + AA(1); //!< treat edges by rounding-out, since they may be antialiased + + EdgeType(int nativeInt) { + this.nativeInt = nativeInt; + } + final int nativeInt; + } + + + // -------------------- + // OVERRIDEN METHODS + // -------------------- + + @Override + public void finalize() throws Throwable { + // pass + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#setBitmap(android.graphics.Bitmap) + */ + @Override + public void setBitmap(Bitmap bitmap) { + mBufferedImage = bitmap.getImage(); + mGraphicsStack.push(mBufferedImage.createGraphics()); + } + + + /* (non-Javadoc) + * @see android.graphics.Canvas#translate(float, float) + */ + @Override + public void translate(float dx, float dy) { + getGraphics2d().translate(dx, dy); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#save() + */ + @Override + public int save() { + Graphics2D g = (Graphics2D)getGraphics2d().create(); + mGraphicsStack.push(g); + + return mGraphicsStack.size() - 1; + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#save(int) + */ + @Override + public int save(int saveFlags) { + // For now we ignore saveFlags + return save(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#restore() + */ + @Override + public void restore() { + mGraphicsStack.pop(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#restoreToCount(int) + */ + @Override + public void restoreToCount(int saveCount) { + while (mGraphicsStack.size() > saveCount) { + mGraphicsStack.pop(); + } + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#getSaveCount() + */ + @Override + public int getSaveCount() { + return mGraphicsStack.size() - 1; + } + + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(float, float, float, float, android.graphics.Region.Op) + */ + @Override + public boolean clipRect(float left, float top, float right, float bottom, Op op) { + return clipRect(left, top, right, bottom); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(float, float, float, float) + */ + @Override + public boolean clipRect(float left, float top, float right, float bottom) { + getGraphics2d().clipRect((int)left, (int)top, (int)(right-left), (int)(bottom-top)); + return true; + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(int, int, int, int) + */ + @Override + public boolean clipRect(int left, int top, int right, int bottom) { + getGraphics2d().clipRect(left, top, right-left, bottom-top); + return true; + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(android.graphics.Rect, android.graphics.Region.Op) + */ + @Override + public boolean clipRect(Rect rect, Op op) { + return clipRect(rect.left, rect.top, rect.right, rect.bottom); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(android.graphics.Rect) + */ + @Override + public boolean clipRect(Rect rect) { + return clipRect(rect.left, rect.top, rect.right, rect.bottom); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(android.graphics.RectF, android.graphics.Region.Op) + */ + @Override + public boolean clipRect(RectF rect, Op op) { + return clipRect(rect.left, rect.top, rect.right, rect.bottom); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRect(android.graphics.RectF) + */ + @Override + public boolean clipRect(RectF rect) { + return clipRect(rect.left, rect.top, rect.right, rect.bottom); + } + + public boolean quickReject(RectF rect, EdgeType type) { + return false; + } + + @Override + public boolean quickReject(RectF rect, _Original_Canvas.EdgeType type) { + throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); + } + + public boolean quickReject(Path path, EdgeType type) { + return false; + } + + @Override + public boolean quickReject(Path path, _Original_Canvas.EdgeType type) { + throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); + } + + public boolean quickReject(float left, float top, float right, float bottom, + EdgeType type) { + return false; + } + + @Override + public boolean quickReject(float left, float top, float right, float bottom, + _Original_Canvas.EdgeType type) { + throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); + } + + /** + * Retrieve the clip bounds, returning true if they are non-empty. + * + * @param bounds Return the clip bounds here. If it is null, ignore it but + * still return true if the current clip is non-empty. + * @return true if the current clip is non-empty. + */ + @Override + public boolean getClipBounds(Rect bounds) { + Rectangle rect = getGraphics2d().getClipBounds(); + if (rect != null) { + bounds.left = rect.x; + bounds.top = rect.y; + bounds.right = rect.x + rect.width; + bounds.bottom = rect.y + rect.height; + return true; + } + return false; + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawColor(int, android.graphics.PorterDuff.Mode) + */ + @Override + public void drawColor(int color, PorterDuff.Mode mode) { + Graphics2D g = getGraphics2d(); + + // save old color + Color c = g.getColor(); + + Composite composite = g.getComposite(); + + // get the alpha from the color + int alpha = color >>> 24; + float falpha = alpha / 255.f; + + setModeInGraphics(mode, g, falpha); + + g.setColor(new Color(color)); + + getGraphics2d().fillRect(0, 0, getWidth(), getHeight()); + + g.setComposite(composite); + + // restore color + g.setColor(c); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawColor(int) + */ + @Override + public void drawColor(int color) { + drawColor(color, PorterDuff.Mode.SRC_OVER); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawARGB(int, int, int, int) + */ + @Override + public void drawARGB(int a, int r, int g, int b) { + drawColor(a << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawRGB(int, int, int) + */ + @Override + public void drawRGB(int r, int g, int b) { + drawColor(0xFF << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); + } + + + /* (non-Javadoc) + * @see android.graphics.Canvas#getWidth() + */ + @Override + public int getWidth() { + return mBufferedImage.getWidth(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#getHeight() + */ + @Override + public int getHeight() { + return mBufferedImage.getHeight(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPaint(android.graphics.Paint) + */ + @Override + public void drawPaint(Paint paint) { + drawColor(paint.getColor()); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint) + */ + @Override + public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { + drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), + (int)left, (int)top, + (int)left+bitmap.getWidth(), (int)top+bitmap.getHeight(), paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint) + */ + @Override + public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { + boolean needsRestore = false; + if (matrix.isIdentity() == false) { + // create a new graphics and apply the matrix to it + save(); // this creates a new Graphics2D, and stores it for children call to use + needsRestore = true; + Graphics2D g = getGraphics2d(); // get the newly create Graphics2D + + // get the Graphics2D current matrix + AffineTransform currentTx = g.getTransform(); + // get the AffineTransform from the matrix + AffineTransform matrixTx = matrix.getTransform(); + + // combine them so that the matrix is applied after. + currentTx.preConcatenate(matrixTx); + + // give it to the graphics as a new matrix replacing all previous transform + g.setTransform(currentTx); + } + + // draw the bitmap + drawBitmap(bitmap, 0, 0, paint); + + if (needsRestore) { + // remove the new graphics + restore(); + } + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint) + */ + @Override + public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { + if (src == null) { + drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), + dst.left, dst.top, dst.right, dst.bottom, paint); + } else { + drawBitmap(bitmap, src.left, src.top, src.width(), src.height(), + dst.left, dst.top, dst.right, dst.bottom, paint); + } + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint) + */ + @Override + public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { + if (src == null) { + drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), + (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint); + } else { + drawBitmap(bitmap, src.left, src.top, src.width(), src.height(), + (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint); + } + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint) + */ + @Override + public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, + int height, boolean hasAlpha, Paint paint) { + throw new UnsupportedOperationException(); + } + + private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft, + int dtop, int dright, int dbottom, Paint paint) { + BufferedImage image = bitmap.getImage(); + + Graphics2D g = getGraphics2d(); + + Composite c = null; + + if (paint != null) { + if (paint.isFilterBitmap()) { + g = (Graphics2D)g.create(); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + } + + if (paint.getAlpha() != 0xFF) { + c = g.getComposite(); + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, + paint.getAlpha()/255.f)); + } + } + + g.drawImage(image, dleft, dtop, dright, dbottom, + sleft, stop, sright, sbottom, null); + + if (paint != null) { + if (paint.isFilterBitmap()) { + g.dispose(); + } + if (c != null) { + g.setComposite(c); + } + } + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#rotate(float, float, float) + */ + @Override + public void rotate(float degrees, float px, float py) { + if (degrees != 0) { + Graphics2D g = getGraphics2d(); + g.translate(px, py); + g.rotate(Math.toRadians(degrees)); + g.translate(-px, -py); + } + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#rotate(float) + */ + @Override + public void rotate(float degrees) { + getGraphics2d().rotate(Math.toRadians(degrees)); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#scale(float, float, float, float) + */ + @Override + public void scale(float sx, float sy, float px, float py) { + Graphics2D g = getGraphics2d(); + g.translate(px, py); + g.scale(sx, sy); + g.translate(-px, -py); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#scale(float, float) + */ + @Override + public void scale(float sx, float sy) { + getGraphics2d().scale(sx, sy); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint) + */ + @Override + public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { + Graphics2D g = getGraphics2d(); + + g = (Graphics2D)g.create(); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g.setFont(paint.getFont()); + + // set the color. because this only handles RGB we have to handle the alpha separately + g.setColor(new Color(paint.getColor())); + int alpha = paint.getAlpha(); + float falpha = alpha / 255.f; + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); + + // Paint.TextAlign indicates how the text is positioned relative to X. + // LEFT is the default and there's nothing to do. + if (paint.getTextAlign() != Align.LEFT) { + float m = paint.measureText(text, index, count); + if (paint.getTextAlign() == Align.CENTER) { + x -= m / 2; + } else if (paint.getTextAlign() == Align.RIGHT) { + x -= m; + } + } + + g.drawChars(text, index, count, (int)x, (int)y); + + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint) + */ + @Override + public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { + drawText(text.toString().toCharArray(), start, end - start, x, y, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawText(java.lang.String, float, float, android.graphics.Paint) + */ + @Override + public void drawText(String text, float x, float y, Paint paint) { + drawText(text.toCharArray(), 0, text.length(), x, y, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawText(java.lang.String, int, int, float, float, android.graphics.Paint) + */ + @Override + public void drawText(String text, int start, int end, float x, float y, Paint paint) { + drawText(text.toCharArray(), start, end - start, x, y, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawRect(android.graphics.RectF, android.graphics.Paint) + */ + @Override + public void drawRect(RectF rect, Paint paint) { + doDrawRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawRect(float, float, float, float, android.graphics.Paint) + */ + @Override + public void drawRect(float left, float top, float right, float bottom, Paint paint) { + doDrawRect((int)left, (int)top, (int)(right-left), (int)(bottom-top), paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawRect(android.graphics.Rect, android.graphics.Paint) + */ + @Override + public void drawRect(Rect r, Paint paint) { + doDrawRect(r.left, r.top, r.width(), r.height(), paint); + } + + private final void doDrawRect(int left, int top, int width, int height, Paint paint) { + // get current graphisc + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + Style style = paint.getStyle(); + + // draw + if (style == Style.FILL || style == Style.FILL_AND_STROKE) { + g.fillRect(left, top, width, height); + } + + if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { + g.drawRect(left, top, width, height); + } + + // dispose Graphics2D object + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint) + */ + @Override + public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { + // get current graphisc + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + Style style = paint.getStyle(); + + // draw + + int arcWidth = (int)(rx * 2); + int arcHeight = (int)(ry * 2); + + if (style == Style.FILL || style == Style.FILL_AND_STROKE) { + g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), + arcWidth, arcHeight); + } + + if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { + g.drawRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), + arcWidth, arcHeight); + } + + // dispose Graphics2D object + g.dispose(); + } + + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawLine(float, float, float, float, android.graphics.Paint) + */ + @Override + public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { + // get current graphisc + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY); + + // dispose Graphics2D object + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawLines(float[], int, int, android.graphics.Paint) + */ + @Override + public void drawLines(float[] pts, int offset, int count, Paint paint) { + // get current graphisc + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + for (int i = 0 ; i < count ; i += 4) { + g.drawLine((int)pts[i + offset], (int)pts[i + offset + 1], + (int)pts[i + offset + 2], (int)pts[i + offset + 3]); + } + + // dispose Graphics2D object + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawLines(float[], android.graphics.Paint) + */ + @Override + public void drawLines(float[] pts, Paint paint) { + drawLines(pts, 0, pts.length, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawCircle(float, float, float, android.graphics.Paint) + */ + @Override + public void drawCircle(float cx, float cy, float radius, Paint paint) { + // get current graphisc + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + Style style = paint.getStyle(); + + int size = (int)(radius * 2); + + // draw + if (style == Style.FILL || style == Style.FILL_AND_STROKE) { + g.fillOval((int)(cx - radius), (int)(cy - radius), size, size); + } + + if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { + g.drawOval((int)(cx - radius), (int)(cy - radius), size, size); + } + + // dispose Graphics2D object + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawOval(android.graphics.RectF, android.graphics.Paint) + */ + @Override + public void drawOval(RectF oval, Paint paint) { + // get current graphics + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + Style style = paint.getStyle(); + + // draw + if (style == Style.FILL || style == Style.FILL_AND_STROKE) { + g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); + } + + if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { + g.drawOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); + } + + // dispose Graphics2D object + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPath(android.graphics.Path, android.graphics.Paint) + */ + @Override + public void drawPath(Path path, Paint paint) { + // get current graphics + Graphics2D g = getGraphics2d(); + + g = getNewGraphics(paint, g); + + Style style = paint.getStyle(); + + // draw + if (style == Style.FILL || style == Style.FILL_AND_STROKE) { + g.fill(path.getAwtShape()); + } + + if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { + g.draw(path.getAwtShape()); + } + + // dispose Graphics2D object + g.dispose(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#setMatrix(android.graphics.Matrix) + */ + @Override + public void setMatrix(Matrix matrix) { + // since SetMatrix *replaces* all the other transformation, we have to restore/save + restore(); + save(); + + // get the new current graphics + Graphics2D g = getGraphics2d(); + + // and apply the matrix + g.setTransform(matrix.getTransform()); + + if (mLogger != null && matrix.hasPerspective()) { + mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor."); + } + } + + // -------------------- + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipPath(android.graphics.Path, android.graphics.Region.Op) + */ + @Override + public boolean clipPath(Path path, Op op) { + // TODO Auto-generated method stub + return super.clipPath(path, op); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipPath(android.graphics.Path) + */ + @Override + public boolean clipPath(Path path) { + // TODO Auto-generated method stub + return super.clipPath(path); + } + + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRegion(android.graphics.Region, android.graphics.Region.Op) + */ + @Override + public boolean clipRegion(Region region, Op op) { + // TODO Auto-generated method stub + return super.clipRegion(region, op); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#clipRegion(android.graphics.Region) + */ + @Override + public boolean clipRegion(Region region) { + // TODO Auto-generated method stub + return super.clipRegion(region); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#concat(android.graphics.Matrix) + */ + @Override + public void concat(Matrix matrix) { + // TODO Auto-generated method stub + super.concat(matrix); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint) + */ + @Override + public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, + Paint paint) { + // TODO Auto-generated method stub + super.drawArc(oval, startAngle, sweepAngle, useCenter, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint) + */ + @Override + public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, + int vertOffset, int[] colors, int colorOffset, Paint paint) { + // TODO Auto-generated method stub + super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.Rect) + */ + @Override + public void drawPicture(Picture picture, Rect dst) { + // TODO Auto-generated method stub + super.drawPicture(picture, dst); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.RectF) + */ + @Override + public void drawPicture(Picture picture, RectF dst) { + // TODO Auto-generated method stub + super.drawPicture(picture, dst); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPicture(android.graphics.Picture) + */ + @Override + public void drawPicture(Picture picture) { + // TODO Auto-generated method stub + super.drawPicture(picture); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPoint(float, float, android.graphics.Paint) + */ + @Override + public void drawPoint(float x, float y, Paint paint) { + // TODO Auto-generated method stub + super.drawPoint(x, y, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPoints(float[], int, int, android.graphics.Paint) + */ + @Override + public void drawPoints(float[] pts, int offset, int count, Paint paint) { + // TODO Auto-generated method stub + super.drawPoints(pts, offset, count, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPoints(float[], android.graphics.Paint) + */ + @Override + public void drawPoints(float[] pts, Paint paint) { + // TODO Auto-generated method stub + super.drawPoints(pts, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPosText(char[], int, int, float[], android.graphics.Paint) + */ + @Override + public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { + // TODO Auto-generated method stub + super.drawPosText(text, index, count, pos, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawPosText(java.lang.String, float[], android.graphics.Paint) + */ + @Override + public void drawPosText(String text, float[] pos, Paint paint) { + // TODO Auto-generated method stub + super.drawPosText(text, pos, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint) + */ + @Override + public void drawTextOnPath(char[] text, int index, int count, Path path, float offset, + float offset2, Paint paint) { + // TODO Auto-generated method stub + super.drawTextOnPath(text, index, count, path, offset, offset2, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint) + */ + @Override + public void drawTextOnPath(String text, Path path, float offset, float offset2, Paint paint) { + // TODO Auto-generated method stub + super.drawTextOnPath(text, path, offset, offset2, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#drawVertices(android.graphics.Canvas.VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint) + */ + @Override + public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, + float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, + int indexOffset, int indexCount, Paint paint) { + // TODO Auto-generated method stub + super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, colorOffset, + indices, indexOffset, indexCount, paint); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#getDrawFilter() + */ + @Override + public DrawFilter getDrawFilter() { + // TODO Auto-generated method stub + return super.getDrawFilter(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#getGL() + */ + @Override + public GL getGL() { + // TODO Auto-generated method stub + return super.getGL(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#getMatrix() + */ + @Override + public Matrix getMatrix() { + // TODO Auto-generated method stub + return super.getMatrix(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#getMatrix(android.graphics.Matrix) + */ + @Override + public void getMatrix(Matrix ctm) { + // TODO Auto-generated method stub + super.getMatrix(ctm); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#isOpaque() + */ + @Override + public boolean isOpaque() { + // TODO Auto-generated method stub + return super.isOpaque(); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#saveLayer(float, float, float, float, android.graphics.Paint, int) + */ + @Override + public int saveLayer(float left, float top, float right, float bottom, Paint paint, + int saveFlags) { + // TODO Auto-generated method stub + return super.saveLayer(left, top, right, bottom, paint, saveFlags); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#saveLayer(android.graphics.RectF, android.graphics.Paint, int) + */ + @Override + public int saveLayer(RectF bounds, Paint paint, int saveFlags) { + // TODO Auto-generated method stub + return super.saveLayer(bounds, paint, saveFlags); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int) + */ + @Override + public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, + int saveFlags) { + // TODO Auto-generated method stub + return super.saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#saveLayerAlpha(android.graphics.RectF, int, int) + */ + @Override + public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { + // TODO Auto-generated method stub + return super.saveLayerAlpha(bounds, alpha, saveFlags); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#setDrawFilter(android.graphics.DrawFilter) + */ + @Override + public void setDrawFilter(DrawFilter filter) { + // TODO Auto-generated method stub + super.setDrawFilter(filter); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#setViewport(int, int) + */ + @Override + public void setViewport(int width, int height) { + // TODO Auto-generated method stub + super.setViewport(width, height); + } + + /* (non-Javadoc) + * @see android.graphics.Canvas#skew(float, float) + */ + @Override + public void skew(float sx, float sy) { + // TODO Auto-generated method stub + super.skew(sx, sy); + } + + + +} diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix.java b/tools/layoutlib/bridge/src/android/graphics/Matrix.java index 18c0e17..3974e08 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix.java +++ b/tools/layoutlib/bridge/src/android/graphics/Matrix.java @@ -17,6 +17,7 @@ package android.graphics; import java.awt.geom.AffineTransform; +import java.awt.geom.NoninvertibleTransformException; /** @@ -747,7 +748,24 @@ public class Matrix extends _Original_Matrix { * inverted, ignore inverse and return false. */ public boolean invert(Matrix inverse) { - throw new UnsupportedOperationException("STUB NEEDED"); + if (inverse == null) { + return false; + } + + try { + AffineTransform affineTransform = getTransform(); + AffineTransform inverseTransform = affineTransform.createInverse(); + inverse.mValues[0] = (float)inverseTransform.getScaleX(); + inverse.mValues[1] = (float)inverseTransform.getShearX(); + inverse.mValues[2] = (float)inverseTransform.getTranslateX(); + inverse.mValues[3] = (float)inverseTransform.getScaleX(); + inverse.mValues[4] = (float)inverseTransform.getShearY(); + inverse.mValues[5] = (float)inverseTransform.getTranslateY(); + + return true; + } catch (NoninvertibleTransformException e) { + return false; + } } @Override @@ -770,7 +788,19 @@ public class Matrix extends _Original_Matrix { public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, int pointCount) { checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); - throw new UnsupportedOperationException("STUB NEEDED"); + + for (int i = 0 ; i < pointCount ; i++) { + // just in case we are doing in place, we better put this in temp vars + float x = mValues[0] * src[i + srcIndex] + + mValues[1] * src[i + srcIndex + 1] + + mValues[2]; + float y = mValues[3] * src[i + srcIndex] + + mValues[4] * src[i + srcIndex + 1] + + mValues[5]; + + dst[i + dstIndex] = x; + dst[i + dstIndex + 1] = y; + } } /** @@ -858,7 +888,26 @@ public class Matrix extends _Original_Matrix { if (dst == null || src == null) { throw new NullPointerException(); } - throw new UnsupportedOperationException("STUB NEEDED"); + + // array with 4 corners + float[] corners = new float[] { + src.left, src.top, + src.right, src.top, + src.right, src.bottom, + src.left, src.bottom, + }; + + // apply the transform to them. + mapPoints(corners); + + // now put the result in the rect. We take the min/max of Xs and min/max of Ys + dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6])); + dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6])); + + dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7])); + dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); + + return rectStaysRect(); } /** diff --git a/tools/layoutlib/bridge/src/android/os/ServiceManager.java b/tools/layoutlib/bridge/src/android/os/ServiceManager.java new file mode 100644 index 0000000..6a68ee2 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/os/ServiceManager.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 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.os; + +import java.util.Map; + +public final class ServiceManager { + + /** + * Returns a reference to a service with the given name. + * + * @param name the name of the service to get + * @return a reference to the service, or null if the service doesn't exist + */ + public static IBinder getService(String name) { + return null; + } + + /** + * Place a new @a service called @a name into the service + * manager. + * + * @param name the name of the new service + * @param service the service object + */ + public static void addService(String name, IBinder service) { + // pass + } + + /** + * Retrieve an existing service called @a name from the + * service manager. Non-blocking. + */ + public static IBinder checkService(String name) { + return null; + } + + /** + * Return a list of all currently running services. + */ + public static String[] listServices() throws RemoteException { + // actual implementation returns null sometimes, so it's ok + // to return null instead of an empty list. + return null; + } + + /** + * This is only intended to be called when the process is first being brought + * up and bound by the activity manager. There is only one thread in the process + * at that time, so no locking is done. + * + * @param cache the cache of service references + * @hide + */ + public static void initServiceCache(Map cache) { + // pass + } +} diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java new file mode 100644 index 0000000..251c053 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2009 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.view.accessibility; + +import android.content.Context; +import android.content.pm.ServiceInfo; + +import java.util.Collections; +import java.util.List; + +/** + * System level service that serves as an event dispatch for {@link AccessibilityEvent}s. + * Such events are generated when something notable happens in the user interface, + * for example an {@link android.app.Activity} starts, the focus or selection of a + * {@link android.view.View} changes etc. Parties interested in handling accessibility + * events implement and register an accessibility service which extends + * {@link android.accessibilityservice.AccessibilityService}. + * + * @see AccessibilityEvent + * @see android.accessibilityservice.AccessibilityService + * @see android.content.Context#getSystemService + */ +public final class AccessibilityManager { + private static AccessibilityManager sInstance = new AccessibilityManager(); + + /** + * Get an AccessibilityManager instance (create one if necessary). + * + * @hide + */ + public static AccessibilityManager getInstance(Context context) { + return sInstance; + } + + /** + * Create an instance. + * + * @param context A {@link Context}. + */ + private AccessibilityManager() { + } + + /** + * Returns if the {@link AccessibilityManager} is enabled. + * + * @return True if this {@link AccessibilityManager} is enabled, false otherwise. + */ + public boolean isEnabled() { + return false; + } + + /** + * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not + * enabled the call is a NOOP. + * + * @param event The {@link AccessibilityEvent}. + * + * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent} + * while accessibility is not enabled. + */ + public void sendAccessibilityEvent(AccessibilityEvent event) { + } + + /** + * Requests interruption of the accessibility feedback from all accessibility services. + */ + public void interrupt() { + } + + /** + * Returns the {@link ServiceInfo}s of the installed accessibility services. + * + * @return An unmodifiable list with {@link ServiceInfo}s. + */ + public List getAccessibilityServiceList() { + // normal implementation does this in some case, so let's do the same + // (unmodifiableList wrapped around null). + List services = null; + return Collections.unmodifiableList(services); + } +} 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 fd77d51..145a045 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -31,6 +31,7 @@ import com.android.tools.layoutlib.create.MethodAdapter; import com.android.tools.layoutlib.create.OverrideMethod; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Typeface; @@ -358,7 +359,7 @@ public final class Bridge implements ILayoutBridge { windowBackground = context.findItemInStyle(currentTheme, "windowBackground"); windowBackground = context.resolveResValue(windowBackground); - screenOffset = getScreenOffset(currentTheme, context); + screenOffset = getScreenOffset(frameworkResources, currentTheme, context); } // we need to make sure the Looper has been initialized for this thread. @@ -401,8 +402,7 @@ public final class Bridge implements ILayoutBridge { view.layout(0, screenOffset, screenWidth, screenHeight); // draw them - BridgeCanvas canvas = new BridgeCanvas(screenWidth, screenHeight - screenOffset, - logger); + Canvas canvas = new Canvas(screenWidth, screenHeight - screenOffset, logger); root.draw(canvas); canvas.dispose(); @@ -673,9 +673,13 @@ public final class Bridge implements ILayoutBridge { /** * Returns the top screen offset. This depends on whether the current theme defines the user * of the title and status bars. + * @param frameworkResources The framework resources + * @param currentTheme The current theme + * @param context The context * @return the pixel height offset */ - private int getScreenOffset(IStyleResourceValue currentTheme, BridgeContext context) { + private int getScreenOffset(Map> frameworkResources, + IStyleResourceValue currentTheme, BridgeContext context) { int offset = 0; // get the title bar flag from the current theme. @@ -687,22 +691,25 @@ public final class Bridge implements ILayoutBridge { // if there's a value and it's true (default is false) if (value == null || value.getValue() == null || XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) { + // default size of the window title bar + int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT; + // get value from the theme. value = context.findItemInStyle(currentTheme, "windowTitleSize"); // resolve it value = context.resolveResValue(value); - // default value - offset = DEFAULT_TITLE_BAR_HEIGHT; - - // get the real value; if (value != null) { + // get the numerical value, if available TypedValue typedValue = ResourceHelper.getValue(value.getValue()); if (typedValue != null) { - offset = (int)typedValue.getDimension(context.getResources().mMetrics); + // compute the pixel value based on the display metrics + defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics); } } + + offset += defaultOffset; } // get the fullscreen flag from the current theme. @@ -713,8 +720,25 @@ public final class Bridge implements ILayoutBridge { if (value == null || value.getValue() == null || XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) { - // FIXME: Right now this is hard-coded in the platform, but once there's a constant, we'll need to use it. - offset += DEFAULT_STATUS_BAR_HEIGHT; + + // default value + int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT; + + // get the real value, first the list of Dimensions from the framework map + Map dimens = frameworkResources.get(BridgeConstants.RES_DIMEN); + + // now get the value + value = dimens.get("status_bar_height"); + if (value != null) { + TypedValue typedValue = ResourceHelper.getValue(value.getValue()); + if (typedValue != null) { + // compute the pixel value based on the display metrics + defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics); + } + } + + // add the computed offset. + offset += defaultOffset; } return offset; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeCanvas.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeCanvas.java deleted file mode 100644 index 4710691..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeCanvas.java +++ /dev/null @@ -1,1099 +0,0 @@ -/* - * 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.layoutlib.bridge; - -import com.android.layoutlib.api.ILayoutLog; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.DrawFilter; -import android.graphics.LinearGradient; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Picture; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.Region; -import android.graphics.Shader; -import android.graphics.Xfermode; -import android.graphics.Paint.Align; -import android.graphics.Paint.Style; -import android.graphics.Region.Op; - -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.util.Stack; - -import javax.microedition.khronos.opengles.GL; - -/** - * Re-implementation of the Canvas, 100% in java on top of a BufferedImage. - */ -public class BridgeCanvas extends Canvas { - - private BufferedImage mBufferedImage; - private final Stack mGraphicsStack = new Stack(); - private final ILayoutLog mLogger; - - public BridgeCanvas(int width, int height, ILayoutLog logger) { - mLogger = logger; - mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); - mGraphicsStack.push(mBufferedImage.createGraphics()); - } - - public BridgeCanvas(int width, int height) { - this(width, height, null /* logger*/); - } - - public BufferedImage getImage() { - return mBufferedImage; - } - - Graphics2D getGraphics2d() { - return mGraphicsStack.peek(); - } - - void dispose() { - while (mGraphicsStack.size() > 0) { - mGraphicsStack.pop().dispose(); - } - } - - /** - * Creates a new {@link Graphics2D} based on the {@link Paint} parameters. - *

The object must be disposed ({@link Graphics2D#dispose()}) after being used. - */ - private Graphics2D getNewGraphics(Paint paint, Graphics2D g) { - // make new one - g = (Graphics2D)g.create(); - g.setColor(new Color(paint.getColor())); - int alpha = paint.getAlpha(); - float falpha = alpha / 255.f; - - Xfermode xfermode = paint.getXfermode(); - if (xfermode instanceof PorterDuffXfermode) { - PorterDuff.Mode mode = ((PorterDuffXfermode)xfermode).getMode(); - - setModeInGraphics(mode, g, falpha); - } else { - if (mLogger != null && xfermode != null) { - mLogger.warning(String.format( - "Xfermode '%1$s' is not supported in the Layout Editor.", - xfermode.getClass().getCanonicalName())); - } - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); - } - - Shader shader = paint.getShader(); - if (shader instanceof LinearGradient) { - g.setPaint(((LinearGradient)shader).getPaint()); - } else { - if (mLogger != null && shader != null) { - mLogger.warning(String.format( - "Shader '%1$s' is not supported in the Layout Editor.", - shader.getClass().getCanonicalName())); - } - } - - return g; - } - - private void setModeInGraphics(PorterDuff.Mode mode, Graphics2D g, float falpha) { - switch (mode) { - case CLEAR: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha)); - break; - case DARKEN: - break; - case DST: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, falpha)); - break; - case DST_ATOP: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha)); - break; - case DST_IN: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha)); - break; - case DST_OUT: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha)); - break; - case DST_OVER: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha)); - break; - case LIGHTEN: - break; - case MULTIPLY: - break; - case SCREEN: - break; - case SRC: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, falpha)); - break; - case SRC_ATOP: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha)); - break; - case SRC_IN: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha)); - break; - case SRC_OUT: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha)); - break; - case SRC_OVER: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); - break; - case XOR: - g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, falpha)); - break; - } - } - - // -------------------- - - @Override - public void finalize() throws Throwable { - // pass - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#translate(float, float) - */ - @Override - public void translate(float dx, float dy) { - getGraphics2d().translate(dx, dy); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#save() - */ - @Override - public int save() { - Graphics2D g = (Graphics2D)getGraphics2d().create(); - mGraphicsStack.push(g); - - return mGraphicsStack.size() - 1; - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#save(int) - */ - @Override - public int save(int saveFlags) { - // For now we ignore saveFlags - return save(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#restore() - */ - @Override - public void restore() { - mGraphicsStack.pop(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#restoreToCount(int) - */ - @Override - public void restoreToCount(int saveCount) { - while (mGraphicsStack.size() > saveCount) { - mGraphicsStack.pop(); - } - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#getSaveCount() - */ - @Override - public int getSaveCount() { - return mGraphicsStack.size() - 1; - } - - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(float, float, float, float, android.graphics.Region.Op) - */ - @Override - public boolean clipRect(float left, float top, float right, float bottom, Op op) { - return clipRect(left, top, right, bottom); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(float, float, float, float) - */ - @Override - public boolean clipRect(float left, float top, float right, float bottom) { - getGraphics2d().clipRect((int)left, (int)top, (int)(right-left), (int)(bottom-top)); - return true; - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(int, int, int, int) - */ - @Override - public boolean clipRect(int left, int top, int right, int bottom) { - getGraphics2d().clipRect(left, top, right-left, bottom-top); - return true; - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(android.graphics.Rect, android.graphics.Region.Op) - */ - @Override - public boolean clipRect(Rect rect, Op op) { - return clipRect(rect.left, rect.top, rect.right, rect.bottom); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(android.graphics.Rect) - */ - @Override - public boolean clipRect(Rect rect) { - return clipRect(rect.left, rect.top, rect.right, rect.bottom); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(android.graphics.RectF, android.graphics.Region.Op) - */ - @Override - public boolean clipRect(RectF rect, Op op) { - return clipRect(rect.left, rect.top, rect.right, rect.bottom); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRect(android.graphics.RectF) - */ - @Override - public boolean clipRect(RectF rect) { - return clipRect(rect.left, rect.top, rect.right, rect.bottom); - } - - @Override - public boolean quickReject(RectF rect, EdgeType type) { - return false; - } - - @Override - public boolean quickReject(Path path, EdgeType type) { - return false; - } - - @Override - public boolean quickReject(float left, float top, float right, float bottom, - EdgeType type) { - return false; - } - - /** - * Retrieve the clip bounds, returning true if they are non-empty. - * - * @param bounds Return the clip bounds here. If it is null, ignore it but - * still return true if the current clip is non-empty. - * @return true if the current clip is non-empty. - */ - @Override - public boolean getClipBounds(Rect bounds) { - Rectangle rect = getGraphics2d().getClipBounds(); - if (rect != null) { - bounds.left = rect.x; - bounds.top = rect.y; - bounds.right = rect.x + rect.width; - bounds.bottom = rect.y + rect.height; - return true; - } - return false; - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawColor(int, android.graphics.PorterDuff.Mode) - */ - @Override - public void drawColor(int color, PorterDuff.Mode mode) { - Graphics2D g = getGraphics2d(); - - // save old color - Color c = g.getColor(); - - Composite composite = g.getComposite(); - - // get the alpha from the color - int alpha = color >>> 24; - float falpha = alpha / 255.f; - - setModeInGraphics(mode, g, falpha); - - g.setColor(new Color(color)); - - getGraphics2d().fillRect(0, 0, getWidth(), getHeight()); - - g.setComposite(composite); - - // restore color - g.setColor(c); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawColor(int) - */ - @Override - public void drawColor(int color) { - drawColor(color, PorterDuff.Mode.SRC_OVER); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawARGB(int, int, int, int) - */ - @Override - public void drawARGB(int a, int r, int g, int b) { - drawColor(a << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawRGB(int, int, int) - */ - @Override - public void drawRGB(int r, int g, int b) { - drawColor(0xFF << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); - } - - - /* (non-Javadoc) - * @see android.graphics.Canvas#getWidth() - */ - @Override - public int getWidth() { - return mBufferedImage.getWidth(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#getHeight() - */ - @Override - public int getHeight() { - return mBufferedImage.getHeight(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPaint(android.graphics.Paint) - */ - @Override - public void drawPaint(Paint paint) { - drawColor(paint.getColor()); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint) - */ - @Override - public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { - drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), - (int)left, (int)top, - (int)left+bitmap.getWidth(), (int)top+bitmap.getHeight(), paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint) - */ - @Override - public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { - throw new UnsupportedOperationException(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint) - */ - @Override - public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { - if (src == null) { - drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), - dst.left, dst.top, dst.right, dst.bottom, paint); - } else { - drawBitmap(bitmap, src.left, src.top, src.width(), src.height(), - dst.left, dst.top, dst.right, dst.bottom, paint); - } - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint) - */ - @Override - public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { - if (src == null) { - drawBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), - (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint); - } else { - drawBitmap(bitmap, src.left, src.top, src.width(), src.height(), - (int)dst.left, (int)dst.top, (int)dst.right, (int)dst.bottom, paint); - } - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint) - */ - @Override - public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width, - int height, boolean hasAlpha, Paint paint) { - throw new UnsupportedOperationException(); - } - - private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft, - int dtop, int dright, int dbottom, Paint paint) { - BufferedImage image = bitmap.getImage(); - - Graphics2D g = getGraphics2d(); - - Composite c = null; - - if (paint.isFilterBitmap()) { - g = (Graphics2D)g.create(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, - RenderingHints.VALUE_INTERPOLATION_BILINEAR); - } - - if (paint.getAlpha() != 0xFF) { - c = g.getComposite(); - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, - paint.getAlpha()/255.f)); - } - - g.drawImage(image, dleft, dtop, dright, dbottom, - sleft, stop, sright, sbottom, null); - - if (paint.isFilterBitmap()) { - g.dispose(); - } - - if (c != null) { - g.setComposite(c); - } - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#rotate(float, float, float) - */ - @Override - public void rotate(float degrees, float px, float py) { - if (degrees != 0) { - Graphics2D g = getGraphics2d(); - g.translate(px, py); - g.rotate(Math.toRadians(degrees)); - g.translate(-px, -py); - } - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#rotate(float) - */ - @Override - public void rotate(float degrees) { - getGraphics2d().rotate(Math.toRadians(degrees)); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#scale(float, float, float, float) - */ - @Override - public void scale(float sx, float sy, float px, float py) { - Graphics2D g = getGraphics2d(); - g.translate(px, py); - g.scale(sx, sy); - g.translate(-px, -py); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#scale(float, float) - */ - @Override - public void scale(float sx, float sy) { - getGraphics2d().scale(sx, sy); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint) - */ - @Override - public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { - Graphics2D g = getGraphics2d(); - - g = (Graphics2D)g.create(); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - - g.setFont(paint.getFont()); - - // set the color. because this only handles RGB we have to handle the alpha separately - g.setColor(new Color(paint.getColor())); - int alpha = paint.getAlpha(); - float falpha = alpha / 255.f; - g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); - - // Paint.TextAlign indicates how the text is positioned relative to X. - // LEFT is the default and there's nothing to do. - if (paint.getTextAlign() != Align.LEFT) { - float m = paint.measureText(text, index, count); - if (paint.getTextAlign() == Align.CENTER) { - x -= m / 2; - } else if (paint.getTextAlign() == Align.RIGHT) { - x -= m; - } - } - - g.drawChars(text, index, count, (int)x, (int)y); - - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint) - */ - @Override - public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) { - drawText(text.toString().toCharArray(), start, end - start, x, y, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawText(java.lang.String, float, float, android.graphics.Paint) - */ - @Override - public void drawText(String text, float x, float y, Paint paint) { - drawText(text.toCharArray(), 0, text.length(), x, y, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawText(java.lang.String, int, int, float, float, android.graphics.Paint) - */ - @Override - public void drawText(String text, int start, int end, float x, float y, Paint paint) { - drawText(text.toCharArray(), start, end - start, x, y, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawRect(android.graphics.RectF, android.graphics.Paint) - */ - @Override - public void drawRect(RectF rect, Paint paint) { - doDrawRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawRect(float, float, float, float, android.graphics.Paint) - */ - @Override - public void drawRect(float left, float top, float right, float bottom, Paint paint) { - doDrawRect((int)left, (int)top, (int)(right-left), (int)(bottom-top), paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawRect(android.graphics.Rect, android.graphics.Paint) - */ - @Override - public void drawRect(Rect r, Paint paint) { - doDrawRect(r.left, r.top, r.width(), r.height(), paint); - } - - private final void doDrawRect(int left, int top, int width, int height, Paint paint) { - // get current graphisc - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - Style style = paint.getStyle(); - - // draw - if (style == Style.FILL || style == Style.FILL_AND_STROKE) { - g.fillRect(left, top, width, height); - } - - if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { - g.drawRect(left, top, width, height); - } - - // dispose Graphics2D object - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint) - */ - @Override - public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { - // get current graphisc - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - Style style = paint.getStyle(); - - // draw - - int arcWidth = (int)(rx * 2); - int arcHeight = (int)(ry * 2); - - if (style == Style.FILL || style == Style.FILL_AND_STROKE) { - g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), - arcWidth, arcHeight); - } - - if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { - g.drawRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), - arcWidth, arcHeight); - } - - // dispose Graphics2D object - g.dispose(); - } - - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawLine(float, float, float, float, android.graphics.Paint) - */ - @Override - public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { - // get current graphisc - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY); - - // dispose Graphics2D object - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawLines(float[], int, int, android.graphics.Paint) - */ - @Override - public void drawLines(float[] pts, int offset, int count, Paint paint) { - // get current graphisc - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - for (int i = 0 ; i < count ; i += 4) { - g.drawLine((int)pts[i + offset], (int)pts[i + offset + 1], - (int)pts[i + offset + 2], (int)pts[i + offset + 3]); - } - - // dispose Graphics2D object - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawLines(float[], android.graphics.Paint) - */ - @Override - public void drawLines(float[] pts, Paint paint) { - drawLines(pts, 0, pts.length, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawCircle(float, float, float, android.graphics.Paint) - */ - @Override - public void drawCircle(float cx, float cy, float radius, Paint paint) { - // get current graphisc - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - Style style = paint.getStyle(); - - int size = (int)(radius * 2); - - // draw - if (style == Style.FILL || style == Style.FILL_AND_STROKE) { - g.fillOval((int)(cx - radius), (int)(cy - radius), size, size); - } - - if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { - g.drawOval((int)(cx - radius), (int)(cy - radius), size, size); - } - - // dispose Graphics2D object - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawOval(android.graphics.RectF, android.graphics.Paint) - */ - @Override - public void drawOval(RectF oval, Paint paint) { - // get current graphics - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - Style style = paint.getStyle(); - - // draw - if (style == Style.FILL || style == Style.FILL_AND_STROKE) { - g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); - } - - if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { - g.drawOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); - } - - // dispose Graphics2D object - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPath(android.graphics.Path, android.graphics.Paint) - */ - @Override - public void drawPath(Path path, Paint paint) { - // get current graphics - Graphics2D g = getGraphics2d(); - - g = getNewGraphics(paint, g); - - Style style = paint.getStyle(); - - // draw - if (style == Style.FILL || style == Style.FILL_AND_STROKE) { - g.fill(path.getAwtShape()); - } - - if (style == Style.STROKE || style == Style.FILL_AND_STROKE) { - g.draw(path.getAwtShape()); - } - - // dispose Graphics2D object - g.dispose(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#setMatrix(android.graphics.Matrix) - */ - @Override - public void setMatrix(Matrix matrix) { - // since SetMatrix *replaces* all the other transformation, we have to restore/save - restore(); - save(); - - // get the new current graphics - Graphics2D g = getGraphics2d(); - - // and apply the matrix - g.setTransform(matrix.getTransform()); - - if (mLogger != null && matrix.hasPerspective()) { - mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor."); - } - } - - // -------------------- - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipPath(android.graphics.Path, android.graphics.Region.Op) - */ - @Override - public boolean clipPath(Path path, Op op) { - // TODO Auto-generated method stub - return super.clipPath(path, op); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipPath(android.graphics.Path) - */ - @Override - public boolean clipPath(Path path) { - // TODO Auto-generated method stub - return super.clipPath(path); - } - - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRegion(android.graphics.Region, android.graphics.Region.Op) - */ - @Override - public boolean clipRegion(Region region, Op op) { - // TODO Auto-generated method stub - return super.clipRegion(region, op); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#clipRegion(android.graphics.Region) - */ - @Override - public boolean clipRegion(Region region) { - // TODO Auto-generated method stub - return super.clipRegion(region); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#concat(android.graphics.Matrix) - */ - @Override - public void concat(Matrix matrix) { - // TODO Auto-generated method stub - super.concat(matrix); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint) - */ - @Override - public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, - Paint paint) { - // TODO Auto-generated method stub - super.drawArc(oval, startAngle, sweepAngle, useCenter, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint) - */ - @Override - public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, - int vertOffset, int[] colors, int colorOffset, Paint paint) { - // TODO Auto-generated method stub - super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.Rect) - */ - @Override - public void drawPicture(Picture picture, Rect dst) { - // TODO Auto-generated method stub - super.drawPicture(picture, dst); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPicture(android.graphics.Picture, android.graphics.RectF) - */ - @Override - public void drawPicture(Picture picture, RectF dst) { - // TODO Auto-generated method stub - super.drawPicture(picture, dst); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPicture(android.graphics.Picture) - */ - @Override - public void drawPicture(Picture picture) { - // TODO Auto-generated method stub - super.drawPicture(picture); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPoint(float, float, android.graphics.Paint) - */ - @Override - public void drawPoint(float x, float y, Paint paint) { - // TODO Auto-generated method stub - super.drawPoint(x, y, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPoints(float[], int, int, android.graphics.Paint) - */ - @Override - public void drawPoints(float[] pts, int offset, int count, Paint paint) { - // TODO Auto-generated method stub - super.drawPoints(pts, offset, count, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPoints(float[], android.graphics.Paint) - */ - @Override - public void drawPoints(float[] pts, Paint paint) { - // TODO Auto-generated method stub - super.drawPoints(pts, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPosText(char[], int, int, float[], android.graphics.Paint) - */ - @Override - public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) { - // TODO Auto-generated method stub - super.drawPosText(text, index, count, pos, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawPosText(java.lang.String, float[], android.graphics.Paint) - */ - @Override - public void drawPosText(String text, float[] pos, Paint paint) { - // TODO Auto-generated method stub - super.drawPosText(text, pos, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawTextOnPath(char[], int, int, android.graphics.Path, float, float, android.graphics.Paint) - */ - @Override - public void drawTextOnPath(char[] text, int index, int count, Path path, float offset, - float offset2, Paint paint) { - // TODO Auto-generated method stub - super.drawTextOnPath(text, index, count, path, offset, offset2, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawTextOnPath(java.lang.String, android.graphics.Path, float, float, android.graphics.Paint) - */ - @Override - public void drawTextOnPath(String text, Path path, float offset, float offset2, Paint paint) { - // TODO Auto-generated method stub - super.drawTextOnPath(text, path, offset, offset2, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#drawVertices(android.graphics.Canvas.VertexMode, int, float[], int, float[], int, int[], int, short[], int, int, android.graphics.Paint) - */ - @Override - public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset, - float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices, - int indexOffset, int indexCount, Paint paint) { - // TODO Auto-generated method stub - super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, colorOffset, - indices, indexOffset, indexCount, paint); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#getDrawFilter() - */ - @Override - public DrawFilter getDrawFilter() { - // TODO Auto-generated method stub - return super.getDrawFilter(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#getGL() - */ - @Override - public GL getGL() { - // TODO Auto-generated method stub - return super.getGL(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#getMatrix() - */ - @Override - public Matrix getMatrix() { - // TODO Auto-generated method stub - return super.getMatrix(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#getMatrix(android.graphics.Matrix) - */ - @Override - public void getMatrix(Matrix ctm) { - // TODO Auto-generated method stub - super.getMatrix(ctm); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#isOpaque() - */ - @Override - public boolean isOpaque() { - // TODO Auto-generated method stub - return super.isOpaque(); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#saveLayer(float, float, float, float, android.graphics.Paint, int) - */ - @Override - public int saveLayer(float left, float top, float right, float bottom, Paint paint, - int saveFlags) { - // TODO Auto-generated method stub - return super.saveLayer(left, top, right, bottom, paint, saveFlags); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#saveLayer(android.graphics.RectF, android.graphics.Paint, int) - */ - @Override - public int saveLayer(RectF bounds, Paint paint, int saveFlags) { - // TODO Auto-generated method stub - return super.saveLayer(bounds, paint, saveFlags); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int) - */ - @Override - public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, - int saveFlags) { - // TODO Auto-generated method stub - return super.saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#saveLayerAlpha(android.graphics.RectF, int, int) - */ - @Override - public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) { - // TODO Auto-generated method stub - return super.saveLayerAlpha(bounds, alpha, saveFlags); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#setBitmap(android.graphics.Bitmap) - */ - @Override - public void setBitmap(Bitmap bitmap) { - // TODO Auto-generated method stub - super.setBitmap(bitmap); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#setDrawFilter(android.graphics.DrawFilter) - */ - @Override - public void setDrawFilter(DrawFilter filter) { - // TODO Auto-generated method stub - super.setDrawFilter(filter); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#setViewport(int, int) - */ - @Override - public void setViewport(int width, int height) { - // TODO Auto-generated method stub - super.setViewport(width, height); - } - - /* (non-Javadoc) - * @see android.graphics.Canvas#skew(float, float) - */ - @Override - public void skew(float sx, float sy) { - // TODO Auto-generated method stub - super.skew(sx, sy); - } - - - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java index b426247..b5b7ceb 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java @@ -45,11 +45,12 @@ public class BridgeConstants { public final static String PREFIX_RESOURCE_REF = "@"; public final static String PREFIX_ANDROID_THEME_REF = "?android:"; public final static String PREFIX_THEME_REF = "?"; - + public final static String PREFIX_ANDROID = "android:"; - + public final static String RES_STYLE = "style"; public final static String RES_ATTR = "attr"; + public final static String RES_DIMEN = "dimen"; public final static String RES_DRAWABLE = "drawable"; public final static String RES_COLOR = "color"; public final static String RES_LAYOUT = "layout"; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java index 69f3d9c..f48c8db 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java @@ -64,7 +64,7 @@ import java.util.Map.Entry; * Custom implementation of Context to handle non compiled resources. */ public final class BridgeContext extends Context { - + private Resources mResources; private Theme mTheme; private HashMap mViewKeyMap = new HashMap(); @@ -73,12 +73,12 @@ public final class BridgeContext extends Context { private Map> mProjectResources; private Map> mFrameworkResources; private Map mStyleInheritanceMap; - + // maps for dynamically generated id representing style objects (IStyleResourceValue) private Map mDynamicIdToStyleMap; private Map mStyleToDynamicIdMap; private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style - + // cache for TypedArray generated from IStyleResourceValue object private Map> mTypedArrayCache; private BridgeInflater mInflater; @@ -112,7 +112,7 @@ public final class BridgeContext extends Context { mProjectCallback = customViewLoader; mLogger = logger; Configuration config = new Configuration(); - + AssetManager assetManager = BridgeAssetManager.initSystem(); mResources = BridgeResources.initSystem( this, @@ -120,19 +120,19 @@ public final class BridgeContext extends Context { metrics, config, customViewLoader); - + mTheme = mResources.newTheme(); - + mThemeValues = currentTheme; mProjectResources = projectResources; mFrameworkResources = frameworkResources; mStyleInheritanceMap = styleInheritanceMap; } - + public void setBridgeInflater(BridgeInflater inflater) { mInflater = inflater; } - + public void addViewKey(View view, Object viewKey) { mViewKeyMap.put(view, viewKey); } @@ -140,19 +140,19 @@ public final class BridgeContext extends Context { public Object getViewKey(View view) { return mViewKeyMap.get(view); } - + public Object getProjectKey() { return mProjectKey; } - + public IProjectCallback getProjectCallback() { return mProjectCallback; } - + public ILayoutLog getLogger() { return mLogger; } - + // ------------ Context methods @Override @@ -169,14 +169,14 @@ public final class BridgeContext extends Context { public ClassLoader getClassLoader() { return this.getClass().getClassLoader(); } - + @Override public Object getSystemService(String service) { if (LAYOUT_INFLATER_SERVICE.equals(service)) { return mInflater; } - - // AutoCompleteTextView and MultiAutoCompleteTextView want a window + + // AutoCompleteTextView and MultiAutoCompleteTextView want a window // service. We don't have any but it's not worth an exception. if (WINDOW_SERVICE.equals(service)) { return null; @@ -196,38 +196,38 @@ public final class BridgeContext extends Context { throws Resources.NotFoundException { // get the IStyleResourceValue based on the resId; IStyleResourceValue style = getStyleByDynamicId(resid); - + if (style == null) { throw new Resources.NotFoundException(); } if (mTypedArrayCache == null) { mTypedArrayCache = new HashMap>(); - + Map map = new HashMap(); mTypedArrayCache.put(attrs, map); BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs); map.put(resid, ta); - + return ta; } - + // get the 2nd map Map map = mTypedArrayCache.get(attrs); if (map == null) { map = new HashMap(); mTypedArrayCache.put(attrs, map); } - + // get the array from the 2nd map TypedArray ta = map.get(resid); - + if (ta == null) { ta = createStyleBasedTypedArray(style, attrs); map.put(resid, ta); } - + return ta; } @@ -235,11 +235,11 @@ public final class BridgeContext extends Context { public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) { return obtainStyledAttributes(set, attrs, 0, 0); } - + @Override public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { - + // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java BridgeXmlBlockParser parser = null; if (set instanceof BridgeXmlBlockParser) { @@ -252,10 +252,10 @@ public final class BridgeContext extends Context { boolean[] frameworkAttributes = new boolean[1]; TreeMap styleNameMap = searchAttrs(attrs, frameworkAttributes); - + BridgeTypedArray ta = ((BridgeResources) mResources).newTypeArray(attrs.length, parser.isPlatformFile()); - + // resolve the defStyleAttr value into a IStyleResourceValue IStyleResourceValue defStyleValues = null; if (defStyleAttr != 0) { @@ -265,7 +265,7 @@ public final class BridgeContext extends Context { // look for the style in the current theme, and its parent: if (mThemeValues != null) { IResourceValue item = findItemInStyle(mThemeValues, defStyleName); - + if (item != null) { // item is a reference to a style entry. Search for it. item = findResValue(item.getValue()); @@ -279,12 +279,12 @@ public final class BridgeContext extends Context { } } } - + if (defStyleRes != 0) { // FIXME: See what we need to do with this. throw new UnsupportedOperationException(); } - + String namespace = BridgeConstants.NS_RESOURCES; if (frameworkAttributes[0] == false) { // need to use the application namespace @@ -294,32 +294,32 @@ public final class BridgeContext extends Context { if (styleNameMap != null) { for (Entry styleAttribute : styleNameMap.entrySet()) { int index = styleAttribute.getKey().intValue(); - + String name = styleAttribute.getValue(); String value = parser.getAttributeValue(namespace, name); - + // if there's no direct value for this attribute in the XML, we look for default // values in the widget defStyle, and then in the theme. if (value == null) { IResourceValue resValue = null; - + // look for the value in the defStyle first (and its parent if needed) if (defStyleValues != null) { resValue = findItemInStyle(defStyleValues, name); } - + // if the item is not present in the defStyle, we look in the main theme (and // its parent themes) if (resValue == null && mThemeValues != null) { resValue = findItemInStyle(mThemeValues, name); } - + // if we found a value, we make sure this doesn't reference another value. // So we resolve it. if (resValue != null) { resValue = resolveResValue(resValue); } - + ta.bridgeSetValue(index, name, resValue); } else { // there is a value in the XML, but we need to resolve it in case it's @@ -328,15 +328,20 @@ public final class BridgeContext extends Context { } } } - + ta.sealArray(); - + return ta; } - - + + @Override + public Looper getMainLooper() { + return Looper.myLooper(); + } + + // ------------- private new methods - + /** * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the * values found in the given style. @@ -345,30 +350,30 @@ public final class BridgeContext extends Context { private BridgeTypedArray createStyleBasedTypedArray(IStyleResourceValue style, int[] attrs) throws Resources.NotFoundException { TreeMap styleNameMap = searchAttrs(attrs, null); - + BridgeTypedArray ta = ((BridgeResources) mResources).newTypeArray(attrs.length, false /* platformResourceFlag */); - + // loop through all the values in the style map, and init the TypedArray with // the style we got from the dynamic id for (Entry styleAttribute : styleNameMap.entrySet()) { int index = styleAttribute.getKey().intValue(); String name = styleAttribute.getValue(); - + // get the value from the style, or its parent styles. IResourceValue resValue = findItemInStyle(style, name); - + // resolve it to make sure there are no references left. ta.bridgeSetValue(index, name, resolveResValue(resValue)); } - + ta.sealArray(); return ta; } - + /** * Resolves the value of a resource, if the value references a theme or resource value. *

@@ -391,13 +396,13 @@ public final class BridgeContext extends Context { // get the IResourceValue referenced by this value IResourceValue resValue = findResValue(value); - + // if resValue is null, but value is not null, this means it was not a reference. // we return the name/value wrapper in a IResourceValue if (resValue == null) { return new ResourceValue(type, name, value); } - + // we resolved a first reference, but we need to make sure this isn't a reference also. return resolveResValue(resValue); } @@ -411,7 +416,7 @@ public final class BridgeContext extends Context { *

* If a value that does not need to be resolved is given, the method will return the input * value. - * + * * @param value the value containing the reference to resolve. * @return a {@link IResourceValue} object or null */ @@ -419,7 +424,7 @@ public final class BridgeContext extends Context { if (value == null) { return null; } - + // if the resource value is a style, we simply return it. if (value instanceof IStyleResourceValue) { return value; @@ -436,7 +441,7 @@ public final class BridgeContext extends Context { // otherwise, we attempt to resolve this new value as well return resolveResValue(resolvedValue); } - + /** * Searches for, and returns a {@link IResourceValue} by its reference. *

@@ -451,7 +456,7 @@ public final class BridgeContext extends Context { *

* The actual format of a reference is

@[namespace:]resType/resName
but this method * only support the android namespace. - * + * * @param reference the resource reference to search for. * @return a {@link IResourceValue} or null. */ @@ -481,7 +486,7 @@ public final class BridgeContext extends Context { // we look for the referenced item name. String referenceName = null; - + if (segments.length == 2) { // there was a resType in the reference. If it's attr, we ignore it // else, we assert for now. @@ -495,7 +500,7 @@ public final class BridgeContext extends Context { // it's just an item name. referenceName = segments[0]; } - + // now we look for android: in the referenceName in order to support format // such as: ?attr/android:name if (referenceName.startsWith(BridgeConstants.PREFIX_ANDROID)) { @@ -512,9 +517,9 @@ public final class BridgeContext extends Context { return findItemInStyle(mThemeValues, referenceName); } else if (reference.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) { boolean frameworkOnly = false; - + // check for the specific null reference value. - if (BridgeConstants.REFERENCE_NULL.equals(reference)) { + if (BridgeConstants.REFERENCE_NULL.equals(reference)) { return null; } @@ -526,20 +531,20 @@ public final class BridgeContext extends Context { } else { reference = reference.substring(BridgeConstants.PREFIX_RESOURCE_REF.length()); } - + // at this point, value contains type/[android:]name (drawable/foo for instance) String[] segments = reference.split("\\/"); - + // now we look for android: in the resource name in order to support format // such as: @drawable/android:name if (segments[1].startsWith(BridgeConstants.PREFIX_ANDROID)) { frameworkOnly = true; segments[1] = segments[1].substring(BridgeConstants.PREFIX_ANDROID.length()); } - + return findResValue(segments[0], segments[1], frameworkOnly); } - + // Looks like the value didn't reference anything. Return null. return null; } @@ -565,7 +570,7 @@ public final class BridgeContext extends Context { } } } - + // now search in the framework resources. typeMap = mFrameworkResources.get(resType); if (typeMap != null) { @@ -574,11 +579,11 @@ public final class BridgeContext extends Context { return item; } } - + // didn't find the resource anywhere. return null; } - + /** * Returns a framework resource by type and name. The returned resource is resolved. * @param resourceType the type of the resource @@ -587,7 +592,7 @@ public final class BridgeContext extends Context { public IResourceValue getFrameworkResource(String resourceType, String resourceName) { return getResource(resourceType, resourceName, mFrameworkResources); } - + /** * Returns a project resource by type and name. The returned resource is resolved. * @param resourceType the type of the resource @@ -596,7 +601,7 @@ public final class BridgeContext extends Context { public IResourceValue getProjectResource(String resourceType, String resourceName) { return getResource(resourceType, resourceName, mProjectResources); } - + IResourceValue getResource(String resourceType, String resourceName, Map> resourceRepository) { Map typeMap = resourceRepository.get(resourceType); @@ -607,12 +612,12 @@ public final class BridgeContext extends Context { return item; } } - + // didn't find the resource anywhere. return null; - + } - + /** * Returns the {@link IResourceValue} matching a given name in a given style. If the * item is not directly available in the style, the method looks in its parent style. @@ -622,7 +627,7 @@ public final class BridgeContext extends Context { */ IResourceValue findItemInStyle(IStyleResourceValue style, String itemName) { IResourceValue item = style.findItem(itemName); - + // if we didn't find it, we look in the parent style (if applicable) if (item == null && mStyleInheritanceMap != null) { IStyleResourceValue parentStyle = mStyleInheritanceMap.get(style); @@ -630,7 +635,7 @@ public final class BridgeContext extends Context { return findItemInStyle(parentStyle, itemName); } } - + return item; } @@ -642,7 +647,7 @@ public final class BridgeContext extends Context { * attrs == com.android.internal.R.styleable.View, this returns the list of the "xyz" where * there's a field com.android.internal.R.styleable.View_xyz and the field value is the index * that is used to reference the attribute later in the TypedArray. - * + * * @param attrs An attribute array reference given to obtainStyledAttributes. * @return A sorted map Attribute-Value to Attribute-Name for all attributes declared by the * attribute array. Returns null if nothing is found. @@ -662,14 +667,14 @@ public final class BridgeContext extends Context { attributes.put(i, null); } } - + if (outFrameworkFlag != null) { outFrameworkFlag[0] = true; } - + return attributes; } - + // if the name was not found in the framework resources, look in the project // resources arrayName = mProjectCallback.resolveResourceValue(attrs); @@ -697,7 +702,7 @@ public final class BridgeContext extends Context { /** * Searches for the attribute referenced by its internal id. - * + * * @param attr An attribute reference given to obtainStyledAttributes such as defStyle. * @return The unique name of the attribute, if found, e.g. "buttonStyle". Returns null * if nothing is found. @@ -707,12 +712,12 @@ public final class BridgeContext extends Context { if (info != null) { return info[0]; } - + info = mProjectCallback.resolveResourceValue(attr); if (info != null) { return info[0]; } - + return null; } @@ -722,27 +727,27 @@ public final class BridgeContext extends Context { mDynamicIdToStyleMap = new HashMap(); mStyleToDynamicIdMap = new HashMap(); } - + // look for an existing id Integer id = mStyleToDynamicIdMap.get(resValue); - + if (id == null) { // generate a new id id = Integer.valueOf(++mDynamicIdGenerator); - + // and add it to the maps. mDynamicIdToStyleMap.put(id, resValue); mStyleToDynamicIdMap.put(resValue, id); } - + return id; } - + private IStyleResourceValue getStyleByDynamicId(int i) { if (mDynamicIdToStyleMap != null) { return mDynamicIdToStyleMap.get(i); } - + return null; } @@ -751,10 +756,10 @@ public final class BridgeContext extends Context { if (value != null) { return value.intValue(); } - + return defValue; } - + int getProjectIdValue(String idName, int defValue) { if (mProjectCallback != null) { Integer value = mProjectCallback.getResourceValue(BridgeConstants.RES_ID, idName); @@ -762,7 +767,7 @@ public final class BridgeContext extends Context { return value.intValue(); } } - + return defValue; } @@ -820,7 +825,7 @@ public final class BridgeContext extends Context { @Override public void clearWallpaper() { // TODO Auto-generated method stub - + } @Override @@ -850,46 +855,46 @@ public final class BridgeContext extends Context { @Override public void enforceCallingOrSelfPermission(String arg0, String arg1) { // TODO Auto-generated method stub - + } @Override public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1, String arg2) { // TODO Auto-generated method stub - + } @Override public void enforceCallingPermission(String arg0, String arg1) { // TODO Auto-generated method stub - + } @Override public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) { // TODO Auto-generated method stub - + } @Override public void enforcePermission(String arg0, int arg1, int arg2, String arg3) { // TODO Auto-generated method stub - + } @Override public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3, String arg4) { // TODO Auto-generated method stub - + } @Override public void enforceUriPermission(Uri arg0, String arg1, String arg2, int arg3, int arg4, int arg5, String arg6) { // TODO Auto-generated method stub - + } @Override @@ -965,7 +970,7 @@ public final class BridgeContext extends Context { // TODO Auto-generated method stub return null; } - + @Override public String getPackageResourcePath() { // TODO Auto-generated method stub @@ -1003,7 +1008,7 @@ public final class BridgeContext extends Context { @Override public void grantUriPermission(String arg0, Uri arg1, int arg2) { // TODO Auto-generated method stub - + } @SuppressWarnings("unused") @@ -1051,31 +1056,31 @@ public final class BridgeContext extends Context { @Override public void removeStickyBroadcast(Intent arg0) { // TODO Auto-generated method stub - + } @Override public void revokeUriPermission(Uri arg0, int arg1) { // TODO Auto-generated method stub - + } @Override public void sendBroadcast(Intent arg0) { // TODO Auto-generated method stub - + } @Override public void sendBroadcast(Intent arg0, String arg1) { // TODO Auto-generated method stub - + } @Override public void sendOrderedBroadcast(Intent arg0, String arg1) { // TODO Auto-generated method stub - + } @Override @@ -1083,39 +1088,39 @@ public final class BridgeContext extends Context { BroadcastReceiver arg2, Handler arg3, int arg4, String arg5, Bundle arg6) { // TODO Auto-generated method stub - + } @Override public void sendStickyBroadcast(Intent arg0) { // TODO Auto-generated method stub - + } @Override public void setTheme(int arg0) { // TODO Auto-generated method stub - + } @SuppressWarnings("unused") @Override public void setWallpaper(Bitmap arg0) throws IOException { // TODO Auto-generated method stub - + } @SuppressWarnings("unused") @Override public void setWallpaper(InputStream arg0) throws IOException { // TODO Auto-generated method stub - + } @Override public void startActivity(Intent arg0) { // TODO Auto-generated method stub - + } @Override @@ -1140,20 +1145,15 @@ public final class BridgeContext extends Context { @Override public void unbindService(ServiceConnection arg0) { // TODO Auto-generated method stub - + } @Override public void unregisterReceiver(BroadcastReceiver arg0) { // TODO Auto-generated method stub - - } - @Override - public Looper getMainLooper() { - throw new UnsupportedOperationException(); } - + @Override public Context getApplicationContext() { throw new UnsupportedOperationException(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java index 0bcc7fd..2b0100b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java @@ -43,14 +43,14 @@ import java.io.FileReader; import java.io.InputStream; /** - * + * */ public final class BridgeResources extends Resources { private BridgeContext mContext; private IProjectCallback mProjectCallback; private boolean[] mPlatformResourceFlag = new boolean[1]; - + /** * This initializes the static field {@link Resources#mSystem} which is used * by methods who get global resources using {@link Resources#getSystem()}. @@ -59,7 +59,7 @@ public final class BridgeResources extends Resources { *

* {@link Bridge} calls this method after setting up a new bridge. */ - /*package*/ static Resources initSystem(BridgeContext context, + /*package*/ static Resources initSystem(BridgeContext context, AssetManager assets, DisplayMetrics metrics, Configuration config, @@ -73,7 +73,7 @@ public final class BridgeResources extends Resources { } return Resources.mSystem; } - + /** * Clears the static {@link Resources#mSystem} to make sure we don't leave objects * around that would prevent us from unloading the library. @@ -92,15 +92,15 @@ public final class BridgeResources extends Resources { mContext = context; mProjectCallback = projectCallback; } - + public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) { return new BridgeTypedArray(this, mContext, numEntries, platformFile); } - + private IResourceValue getResourceValue(int id, boolean[] platformResFlag_out) { // first get the String related to this id in the framework String[] resourceInfo = Bridge.resolveResourceValue(id); - + if (resourceInfo != null) { platformResFlag_out[0] = true; return mContext.getFrameworkResource(resourceInfo[1], resourceInfo[0]); @@ -109,7 +109,7 @@ public final class BridgeResources extends Resources { // didn't find a match in the framework? look in the project. if (mProjectCallback != null) { resourceInfo = mProjectCallback.resolveResourceValue(id); - + if (resourceInfo != null) { platformResFlag_out[0] = false; return mContext.getProjectResource(resourceInfo[1], resourceInfo[0]); @@ -118,26 +118,26 @@ public final class BridgeResources extends Resources { return null; } - + @Override public Drawable getDrawable(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null) { return ResourceHelper.getDrawable(value.getValue(), mContext, value.isFramework()); } - + // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return null; } - + @Override public int getColor(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null) { try { return ResourceHelper.getColor(value.getValue()); @@ -145,18 +145,18 @@ public final class BridgeResources extends Resources { return 0; } } - + // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return 0; } - + @Override public ColorStateList getColorStateList(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null) { try { int color = ResourceHelper.getColor(value.getValue()); @@ -165,33 +165,33 @@ public final class BridgeResources extends Resources { return null; } } - + // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return null; } - + @Override public CharSequence getText(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null) { return value.getValue(); } - + // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return null; } - + @Override public XmlResourceParser getLayout(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null) { File xml = new File(value.getValue()); if (xml.isFile()) { @@ -201,7 +201,7 @@ public final class BridgeResources extends Resources { KXmlParser parser = new KXmlParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); parser.setInput(new FileReader(xml)); - + return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } catch (XmlPullParserException e) { mContext.getLogger().error(e); @@ -215,22 +215,22 @@ public final class BridgeResources extends Resources { // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return null; } - + @Override public TypedArray obtainAttributes(AttributeSet set, int[] attrs) { return mContext.obtainStyledAttributes(set, attrs); } - + @Override public TypedArray obtainTypedArray(int id) throws NotFoundException { throw new UnsupportedOperationException(); } - - + + @Override public float getDimension(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); @@ -244,7 +244,7 @@ public final class BridgeResources extends Resources { } else if (v.equals(BridgeConstants.WRAP_CONTENT)) { return LayoutParams.WRAP_CONTENT; } - + if (ResourceHelper.stringToFloat(v, mTmpValue) && mTmpValue.type == TypedValue.TYPE_DIMENSION) { return mTmpValue.getDimension(mMetrics); @@ -254,7 +254,7 @@ public final class BridgeResources extends Resources { // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return 0; } @@ -276,7 +276,7 @@ public final class BridgeResources extends Resources { // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return 0; } @@ -298,7 +298,7 @@ public final class BridgeResources extends Resources { // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return 0; } @@ -306,7 +306,7 @@ public final class BridgeResources extends Resources { @Override public int getInteger(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null && value.getValue() != null) { String v = value.getValue(); int radix = 10; @@ -320,10 +320,10 @@ public final class BridgeResources extends Resources { // return exception below } } - + // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return 0; } @@ -348,12 +348,12 @@ public final class BridgeResources extends Resources { String s = getString(id); if (s != null) { return String.format(s, formatArgs); - + } // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return null; } @@ -361,14 +361,14 @@ public final class BridgeResources extends Resources { @Override public String getString(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); - + if (value != null && value.getValue() != null) { return value.getValue(); } // id was not found or not resolved. Throw a NotFoundException. throwException(id); - + // this is not used since the method above always throws return null; } @@ -385,6 +385,11 @@ public final class BridgeResources extends Resources { if (ResourceHelper.stringToFloat(v, outValue)) { return; } + + // else it's a string + outValue.type = TypedValue.TYPE_STRING; + outValue.string = v; + return; } } @@ -413,7 +418,7 @@ public final class BridgeResources extends Resources { KXmlParser parser = new KXmlParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); parser.setInput(new FileReader(f)); - + return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); } catch (XmlPullParserException e) { NotFoundException newE = new NotFoundException(); @@ -436,6 +441,33 @@ public final class BridgeResources extends Resources { } @Override + public XmlResourceParser loadXmlResourceParser(String file, int id, + int assetCookie, String type) throws NotFoundException { + // even though we know the XML file to load directly, we still need to resolve the + // id so that we can know if it's a platform or project resource. + // (mPlatformResouceFlag will get the result and will be used later). + getResourceValue(id, mPlatformResourceFlag); + + File f = new File(file); + try { + KXmlParser parser = new KXmlParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + parser.setInput(new FileReader(f)); + + return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]); + } catch (XmlPullParserException e) { + NotFoundException newE = new NotFoundException(); + newE.initCause(e); + throw newE; + } catch (FileNotFoundException e) { + NotFoundException newE = new NotFoundException(); + newE.initCause(e); + throw newE; + } + } + + + @Override public InputStream openRawResource(int id) throws NotFoundException { IResourceValue value = getResourceValue(id, mPlatformResourceFlag); @@ -465,6 +497,24 @@ public final class BridgeResources extends Resources { } @Override + public InputStream openRawResource(int id, TypedValue value) throws NotFoundException { + getValue(id, value, true); + + File f = new File(value.string.toString()); + if (f.isFile()) { + try { + return new FileInputStream(f); + } catch (FileNotFoundException e) { + NotFoundException exception = new NotFoundException(); + exception.initCause(e); + throw exception; + } + } + + throw new NotFoundException(); + } + + @Override public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException { throw new UnsupportedOperationException(); } @@ -482,7 +532,7 @@ public final class BridgeResources extends Resources { if (resourceInfo == null && mProjectCallback != null) { resourceInfo = mProjectCallback.resolveResourceValue(id); } - + String message = null; if (resourceInfo != null) { message = String.format( @@ -492,7 +542,7 @@ public final class BridgeResources extends Resources { message = String.format( "Could not resolve resource value: 0x%1$X.", id); } - + throw new NotFoundException(message); } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java index 5f0852e..abbf2f0 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java @@ -30,17 +30,17 @@ public class NinePatchDrawable extends Drawable { NinePatchDrawable(NinePatch ninePatch) { m9Patch = ninePatch; } - + @Override public int getMinimumWidth() { return m9Patch.getWidth(); } - + @Override public int getMinimumHeight() { return m9Patch.getHeight(); } - + /** * Return the intrinsic width of the underlying drawable object. Returns * -1 if it has no intrinsic width, such as with a solid color. @@ -58,7 +58,7 @@ public class NinePatchDrawable extends Drawable { public int getIntrinsicHeight() { return m9Patch.getHeight(); } - + /** * Return in padding the insets suggested by this Drawable for placing * content inside the drawable's bounds. Positive values move toward the @@ -76,24 +76,18 @@ public class NinePatchDrawable extends Drawable { padding.bottom = padd[3]; return true; } - + @Override public void draw(Canvas canvas) { - if (canvas instanceof BridgeCanvas) { - BridgeCanvas bridgeCanvas = (BridgeCanvas)canvas; - - Rect r = getBounds(); - m9Patch.draw(bridgeCanvas.getGraphics2d(), r.left, r.top, r.width(), r.height()); - - return; - } - - throw new UnsupportedOperationException(); + Rect r = getBounds(); + m9Patch.draw(canvas.getGraphics2d(), r.left, r.top, r.width(), r.height()); + + return; } - + // ----------- Not implemented methods --------------- - + @Override public int getOpacity() { 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 76bd8d4..47184f1 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 @@ -40,7 +40,7 @@ public class Main { for (String path : osJarPath) { log.info("Input : %1$s", path); } - + try { AsmGenerator agen = new AsmGenerator(log, osDestJar[0], new Class[] { // classes to inject in the final JAR @@ -54,20 +54,23 @@ public class Main { }, new String[] { // classes to rename (so that we can replace them in layoutlib) // original-platform-class-name ======> renamed-class-name + "android.graphics.Bitmap", "android.graphics._Original_Bitmap", + "android.graphics.BitmapShader", "android.graphics._Original_BitmapShader", + "android.graphics.Canvas", "android.graphics._Original_Canvas", + "android.graphics.ComposeShader", "android.graphics._Original_ComposeShader", + "android.graphics.LinearGradient", "android.graphics._Original_LinearGradient", "android.graphics.Matrix", "android.graphics._Original_Matrix", "android.graphics.Paint", "android.graphics._Original_Paint", - "android.graphics.Typeface", "android.graphics._Original_Typeface", - "android.graphics.Bitmap", "android.graphics._Original_Bitmap", "android.graphics.Path", "android.graphics._Original_Path", "android.graphics.PorterDuffXfermode", "android.graphics._Original_PorterDuffXfermode", - "android.graphics.Shader", "android.graphics._Original_Shader", - "android.graphics.LinearGradient", "android.graphics._Original_LinearGradient", - "android.graphics.BitmapShader", "android.graphics._Original_BitmapShader", - "android.graphics.ComposeShader", "android.graphics._Original_ComposeShader", "android.graphics.RadialGradient", "android.graphics._Original_RadialGradient", + "android.graphics.Shader", "android.graphics._Original_Shader", "android.graphics.SweepGradient", "android.graphics._Original_SweepGradient", + "android.graphics.Typeface", "android.graphics._Original_Typeface", + "android.os.ServiceManager", "android.os._Original_ServiceManager", "android.util.FloatMath", "android.util._Original_FloatMath", "android.view.SurfaceView", "android.view._Original_SurfaceView", + "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager", }, new String[] { // methods deleted from their return type. "android.graphics.Paint", // class to delete method from @@ -101,7 +104,7 @@ public class Main { }); aa.analyze(); agen.generate(); - + // Throw an error if any class failed to get renamed by the generator // // IMPORTANT: if you're building the platform and you get this error message, @@ -123,7 +126,7 @@ public class Main { } System.exit(1); } - + System.exit(0); } catch (IOException e) { log.exception(e, "Failed to load jar"); @@ -158,7 +161,7 @@ public class Main { return false; } } - + if (osJarPath.isEmpty()) { log.error("Missing parameter: path to input jar"); return false; diff --git a/tools/preload/20090811.compiled b/tools/preload/20090811.compiled new file mode 100644 index 0000000..6dbeca0 Binary files /dev/null and b/tools/preload/20090811.compiled differ diff --git a/tools/preload/Android.mk b/tools/preload/Android.mk index e6fa103..f325870 100644 --- a/tools/preload/Android.mk +++ b/tools/preload/Android.mk @@ -3,13 +3,13 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - ClassRank.java \ Compile.java \ LoadedClass.java \ MemoryUsage.java \ Operation.java \ Policy.java \ PrintCsv.java \ + PrintHtmlDiff.java \ PrintPsTree.java \ Proc.java \ Record.java \ diff --git a/tools/preload/ClassRank.java b/tools/preload/ClassRank.java deleted file mode 100644 index 3699b89..0000000 --- a/tools/preload/ClassRank.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -import java.util.Comparator; - -/** - * Ranks classes for preloading based on how long their operations took - * and how early the operations happened. Higher ranked classes come first. - */ -class ClassRank implements Comparator { - - /** - * Increase this number to add more weight to classes which were loaded - * earlier. - */ - static final int SEQUENCE_WEIGHT = 500; // 5 ms - - static final int BUCKET_SIZE = 5; - - public int compare(Operation a, Operation b) { - // Higher ranked operations should come first. - int result = rankOf(b) - rankOf(a); - if (result != 0) { - return result; - } - - // Make sure we don't drop one of two classes w/ the same rank. - // If a load and an initialization have the same rank, it's OK - // to treat the operations equally. - return a.loadedClass.name.compareTo(b.loadedClass.name); - } - - /** Ranks the given operation. */ - private static int rankOf(Operation o) { - return o.medianExclusiveTimeMicros() - + SEQUENCE_WEIGHT / (o.index / BUCKET_SIZE + 1); - } -} - - diff --git a/tools/preload/LoadedClass.java b/tools/preload/LoadedClass.java index 5782807..86e5dfc 100644 --- a/tools/preload/LoadedClass.java +++ b/tools/preload/LoadedClass.java @@ -15,10 +15,7 @@ */ import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; +import java.util.*; /** * A loaded class. @@ -54,7 +51,7 @@ class LoadedClass implements Serializable, Comparable { } void measureMemoryUsage() { - this.memoryUsage = MemoryUsage.forClass(name); + this.memoryUsage = MemoryUsage.forClass(name); } int mlt = -1; @@ -79,6 +76,10 @@ class LoadedClass implements Serializable, Comparable { return mit = calculateMedian(initializations); } + int medianTimeMicros() { + return medianInitTimeMicros() + medianLoadTimeMicros(); + } + /** Calculates the median duration for a list of operations. */ private static int calculateMedian(List operations) { int size = operations.size(); @@ -102,31 +103,20 @@ class LoadedClass implements Serializable, Comparable { } } - /** - * Counts loads by apps. - */ - int appLoads() { - return operationsByApps(loads); + /** Returns names of processes that loaded this class. */ + Set processNames() { + Set names = new HashSet(); + addProcessNames(loads, names); + addProcessNames(initializations, names); + return names; } - /** - * Counts inits by apps. - */ - int appInits() { - return operationsByApps(initializations); - } - - /** - * Counts number of app operations in the given list. - */ - private static int operationsByApps(List operations) { - int byApps = 0; - for (Operation operation : operations) { - if (operation.process.isApplication()) { - byApps++; + private void addProcessNames(List ops, Set names) { + for (Operation operation : ops) { + if (operation.process.fromZygote()) { + names.add(operation.process.name); } } - return byApps; } public int compareTo(LoadedClass o) { @@ -137,27 +127,4 @@ class LoadedClass implements Serializable, Comparable { public String toString() { return name; } - - /** - * Returns true if this class's initialization causes the given class to - * initialize. - */ - public boolean initializes(LoadedClass clazz, Set visited) { - // Avoid infinite recursion. - if (!visited.add(this)) { - return false; - } - - if (clazz == this) { - return true; - } - - for (Operation initialization : initializations) { - if (initialization.loadedClass.initializes(clazz, visited)) { - return true; - } - } - - return false; - } } diff --git a/tools/preload/MemoryUsage.java b/tools/preload/MemoryUsage.java index e5dfb2a..bc21b6f 100644 --- a/tools/preload/MemoryUsage.java +++ b/tools/preload/MemoryUsage.java @@ -34,8 +34,8 @@ class MemoryUsage implements Serializable { static final MemoryUsage NOT_AVAILABLE = new MemoryUsage(); static int errorCount = 0; - static final int MAXIMUM_ERRORS = 10; // give up after this many fails + // These values are in 1kB increments (not 4kB like you'd expect). final int nativeSharedPages; final int javaSharedPages; final int otherSharedPages; @@ -123,15 +123,24 @@ class MemoryUsage implements Serializable { return allocSize - freedSize; } + int totalHeap() { + return javaHeapSize() + (int) nativeHeapSize; + } + int javaPagesInK() { - return (javaSharedPages + javaPrivatePages) * 4; + return javaSharedPages + javaPrivatePages; } int nativePagesInK() { - return (nativeSharedPages + nativePrivatePages) * 4; + return nativeSharedPages + nativePrivatePages; } int otherPagesInK() { - return (otherSharedPages + otherPrivatePages) * 4; + return otherSharedPages + otherPrivatePages; + } + + int totalPages() { + return javaSharedPages + javaPrivatePages + nativeSharedPages + + nativePrivatePages + otherSharedPages + otherPrivatePages; } /** @@ -163,13 +172,6 @@ class MemoryUsage implements Serializable { * Measures memory usage for the given class. */ static MemoryUsage forClass(String className) { - - // This is a coarse approximation for determining that no device is connected, - // or that the communication protocol has changed, but we'll keep going and stop whining. - if (errorCount >= MAXIMUM_ERRORS) { - return NOT_AVAILABLE; - } - MeasureWithTimeout measurer = new MeasureWithTimeout(className); new Thread(measurer).start(); @@ -280,4 +282,17 @@ class MemoryUsage implements Serializable { e.printStackTrace(); } } + + /** Measures memory usage information and stores it in the model. */ + public static void main(String[] args) throws IOException, + ClassNotFoundException { + Root root = Root.fromFile(args[0]); + root.baseline = baseline(); + for (LoadedClass loadedClass : root.loadedClasses.values()) { + if (loadedClass.systemClass) { + loadedClass.measureMemoryUsage(); + } + } + root.toFile(args[0]); + } } diff --git a/tools/preload/Policy.java b/tools/preload/Policy.java index 554966b..7a190ac 100644 --- a/tools/preload/Policy.java +++ b/tools/preload/Policy.java @@ -19,52 +19,43 @@ import java.util.HashSet; import java.util.Set; /** - * This is not instantiated - we just provide data for other classes to use + * Policy that governs which classes are preloaded. */ public class Policy { - - /** - * This location (in the build system) of the preloaded-classes file. - */ - private static final String PRELOADED_CLASS_FILE = "frameworks/base/preloaded-classes"; - + /** - * The internal process name of the system process. Note, this also shows up as - * "system_process", e.g. in ddms. + * No constructor - use static methods only */ - private static final String SYSTEM_SERVER_PROCESS_NAME = "system_server"; + private Policy() {} - /** - * Names of non-application processes - these will not be checked for preloaded classes. - * - * TODO: Replace this hardcoded list with a walk up the parent chain looking for zygote. + /** + * This location (in the build system) of the preloaded-classes file. */ - private static final Set NOT_FROM_ZYGOTE = new HashSet(Arrays.asList( - "zygote", - "dexopt", - "unknown", - SYSTEM_SERVER_PROCESS_NAME, - "com.android.development", - "app_process" // am & other shell commands - )); + static final String PRELOADED_CLASS_FILE + = "frameworks/base/preloaded-classes"; - /** - * Long running services. These are restricted in their contribution to the preloader - * because their launch time is less critical. + /** + * Long running services. These are restricted in their contribution to the + * preloader because their launch time is less critical. */ + // TODO: Generate this automatically from package manager. private static final Set SERVICES = new HashSet(Arrays.asList( - SYSTEM_SERVER_PROCESS_NAME, - "com.android.acore", - // Commented out to make sure DefaultTimeZones gets preloaded. - // "com.android.phone", - "com.google.process.content", - "android.process.media" + "system_server", + "com.google.process.content", + "android.process.media", + "com.android.phone", + "com.google.android.apps.maps.FriendService", + "com.google.android.apps.maps.LocationFriendService", + "com.google.android.googleapps", + "com.google.process.gapps", + "android.tts" )); /** * Classes which we shouldn't load from the Zygote. */ - private static final Set EXCLUDED_CLASSES = new HashSet(Arrays.asList( + private static final Set EXCLUDED_CLASSES + = new HashSet(Arrays.asList( // Binders "android.app.AlarmManager", "android.app.SearchManager", @@ -75,40 +66,18 @@ public class Policy { "android.os.AsyncTask", "android.pim.ContactsAsyncHelper", "java.lang.ProcessManager" - )); /** - * No constructor - use static methods only - */ - private Policy() {} - - /** - * Returns the path/file name of the preloaded classes file that will be written - * by WritePreloadedClassFile. - */ - public static String getPreloadedClassFileName() { - return PRELOADED_CLASS_FILE; - } - - /** - * Reports if a given process name was created from zygote - */ - public static boolean isFromZygote(String processName) { - return !NOT_FROM_ZYGOTE.contains(processName); - } - - /** - * Reports if the given process name is a "long running" process or service + * Returns true if the given process name is a "long running" process or + * service. */ public static boolean isService(String processName) { return SERVICES.contains(processName); } - - /** - * Reports if the given class should never be preloaded - */ - public static boolean isPreloadableClass(String className) { - return !EXCLUDED_CLASSES.contains(className); + + /**Reports if the given class should be preloaded. */ + public static boolean isPreloadable(LoadedClass clazz) { + return clazz.systemClass && !EXCLUDED_CLASSES.contains(clazz.name); } } diff --git a/tools/preload/PrintCsv.java b/tools/preload/PrintCsv.java index 9f2a318..1820830 100644 --- a/tools/preload/PrintCsv.java +++ b/tools/preload/PrintCsv.java @@ -18,6 +18,12 @@ import java.io.IOException; import java.io.FileInputStream; import java.io.ObjectInputStream; import java.io.BufferedInputStream; +import java.io.Writer; +import java.io.PrintStream; +import java.util.Set; +import java.util.HashSet; +import java.util.TreeSet; +import java.util.Iterator; /** * Prints raw information in CSV format. @@ -33,10 +39,25 @@ public class PrintCsv { Root root = Root.fromFile(args[0]); - System.out.println("Name" + printHeaders(System.out); + + MemoryUsage baseline = MemoryUsage.baseline(); + + for (LoadedClass loadedClass : root.loadedClasses.values()) { + if (!loadedClass.systemClass) { + continue; + } + + printRow(System.out, baseline, loadedClass); + } + } + + static void printHeaders(PrintStream out) { + out.println("Name" + ",Preloaded" + ",Median Load Time (us)" + ",Median Init Time (us)" + + ",Process Names" + ",Load Count" + ",Init Count" + ",Managed Heap (B)" @@ -44,46 +65,63 @@ public class PrintCsv { + ",Managed Pages (kB)" + ",Native Pages (kB)" + ",Other Pages (kB)"); + } - MemoryUsage baseline = root.baseline; + static void printRow(PrintStream out, MemoryUsage baseline, + LoadedClass loadedClass) { + out.print(loadedClass.name); + out.print(','); + out.print(loadedClass.preloaded); + out.print(','); + out.print(loadedClass.medianLoadTimeMicros()); + out.print(','); + out.print(loadedClass.medianInitTimeMicros()); + out.print(','); + out.print('"'); - for (LoadedClass loadedClass : root.loadedClasses.values()) { - if (!loadedClass.systemClass) { - continue; - } + Set procNames = new TreeSet(); + for (Operation op : loadedClass.loads) + procNames.add(op.process.name); + for (Operation op : loadedClass.initializations) + procNames.add(op.process.name); - System.out.print(loadedClass.name); - System.out.print(','); - System.out.print(loadedClass.preloaded); - System.out.print(','); - System.out.print(loadedClass.medianLoadTimeMicros()); - System.out.print(','); - System.out.print(loadedClass.medianInitTimeMicros()); - System.out.print(','); - System.out.print(loadedClass.loads.size()); - System.out.print(','); - System.out.print(loadedClass.initializations.size()); - - if (loadedClass.memoryUsage.isAvailable()) { - MemoryUsage subtracted - = loadedClass.memoryUsage.subtract(baseline); - - System.out.print(','); - System.out.print(subtracted.javaHeapSize()); - System.out.print(','); - System.out.print(subtracted.nativeHeapSize); - System.out.print(','); - System.out.print(subtracted.javaPagesInK()); - System.out.print(','); - System.out.print(subtracted.nativePagesInK()); - System.out.print(','); - System.out.print(subtracted.otherPagesInK()); - - } else { - System.out.print(",n/a,n/a,n/a,n/a,n/a"); + if (procNames.size() <= 3) { + for (String name : procNames) { + out.print(name + "\n"); } + } else { + Iterator i = procNames.iterator(); + out.print(i.next() + "\n"); + out.print(i.next() + "\n"); + out.print("...and " + (procNames.size() - 2) + + " others."); + } + + out.print('"'); + out.print(','); + out.print(loadedClass.loads.size()); + out.print(','); + out.print(loadedClass.initializations.size()); + + if (loadedClass.memoryUsage.isAvailable()) { + MemoryUsage subtracted + = loadedClass.memoryUsage.subtract(baseline); - System.out.println(); + out.print(','); + out.print(subtracted.javaHeapSize()); + out.print(','); + out.print(subtracted.nativeHeapSize); + out.print(','); + out.print(subtracted.javaPagesInK()); + out.print(','); + out.print(subtracted.nativePagesInK()); + out.print(','); + out.print(subtracted.otherPagesInK()); + + } else { + out.print(",n/a,n/a,n/a,n/a,n/a"); } + + out.println(); } } diff --git a/tools/preload/PrintHtmlDiff.java b/tools/preload/PrintHtmlDiff.java new file mode 100644 index 0000000..b101c85 --- /dev/null +++ b/tools/preload/PrintHtmlDiff.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2009 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. + */ + +import java.io.IOException; +import java.io.FileReader; +import java.io.BufferedReader; +import java.io.PrintStream; +import java.util.Set; +import java.util.TreeSet; +import java.util.HashSet; +import java.util.Iterator; + +/** + * Prints HTML containing removed and added files. + */ +public class PrintHtmlDiff { + + private static final String OLD_PRELOADED_CLASSES + = "old-preloaded-classes"; + + public static void main(String[] args) throws IOException, + ClassNotFoundException { + Root root = Root.fromFile(args[0]); + + BufferedReader oldClasses = new BufferedReader( + new FileReader(OLD_PRELOADED_CLASSES)); + + // Classes loaded implicitly by the zygote. + Set zygote = new HashSet(); + for (Proc proc : root.processes.values()) { + if (proc.name.equals("zygote")) { + for (Operation op : proc.operations) { + zygote.add(op.loadedClass); + } + break; + } + } + + Set removed = new TreeSet(); + Set added = new TreeSet(); + + for (LoadedClass loadedClass : root.loadedClasses.values()) { + if (loadedClass.preloaded && !zygote.contains(loadedClass)) { + added.add(loadedClass); + } + } + + String line; + while ((line = oldClasses.readLine()) != null) { + line = line.trim(); + LoadedClass clazz = root.loadedClasses.get(line); + if (clazz != null) { + added.remove(clazz); + if (!clazz.preloaded) removed.add(clazz); + } + } + + PrintStream out = System.out; + + out.println(""); + out.println(""); + out.println(""); + out.println("

Removed"); + out.println("

Added

"); + printTable(out, root.baseline, added); + out.println("

Removed

"); + printTable(out, root.baseline, removed); + out.println(""); + } + + static void printTable(PrintStream out, MemoryUsage baseline, + Iterable classes) { + out.println(""); + + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + out.println(""); + + for (LoadedClass clazz : classes) { + out.println(""); + out.println(""); + out.println(""); + + out.println(""); + + if (clazz.memoryUsage.isAvailable()) { + MemoryUsage subtracted + = clazz.memoryUsage.subtract(baseline); + + out.println(""); + out.println(""); + } else { + for (int i = 0; i < 2; i++) { + out.println(""); + } + } + + out.println(""); + } + + out.println("
NameLoad Time (us)Loaded ByHeap (B)Pages
" + clazz.name + "" + clazz.medianTimeMicros() + ""); + Set procNames = new TreeSet(); + for (Operation op : clazz.loads) procNames.add(op.process.name); + for (Operation op : clazz.initializations) { + procNames.add(op.process.name); + } + if (procNames.size() <= 3) { + for (String name : procNames) { + out.print(name + "
"); + } + } else { + Iterator i = procNames.iterator(); + out.print(i.next() + "
"); + out.print(i.next() + "
"); + out.print("...and " + (procNames.size() - 2) + + " others."); + } + out.println("
" + (subtracted.javaHeapSize() + + subtracted.nativeHeapSize) + "" + subtracted.totalPages() + "n/a
"); + } +} diff --git a/tools/preload/Proc.java b/tools/preload/Proc.java index 22697f8..2105021 100644 --- a/tools/preload/Proc.java +++ b/tools/preload/Proc.java @@ -14,16 +14,11 @@ * limitations under the License. */ -import java.util.Set; -import java.util.HashSet; -import java.util.Arrays; import java.util.List; import java.util.ArrayList; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; -import java.util.Collections; -import java.util.TreeSet; import java.io.Serializable; /** @@ -33,16 +28,6 @@ class Proc implements Serializable { private static final long serialVersionUID = 0; - /** - * Default percentage of time to cut off of app class loading times. - */ - static final int PERCENTAGE_TO_PRELOAD = 75; - - /** - * Maximum number of classes to preload for a given process. - */ - static final int MAX_TO_PRELOAD = 100; - /** Parent process. */ final Proc parent; @@ -88,89 +73,11 @@ class Proc implements Serializable { } /** - * Returns the percentage of time we should cut by preloading for this - * app. - */ - int percentageToPreload() { - return PERCENTAGE_TO_PRELOAD; - } - - /** - * Returns a list of classes which should be preloaded. - * - * @param takeAllClasses forces all classes to be taken (irrespective of ranking) - */ - List highestRankedClasses(boolean takeAllClasses) { - if (!isApplication()) { - return Collections.emptyList(); - } - - // Sort by rank. - Operation[] ranked = new Operation[operations.size()]; - ranked = operations.toArray(ranked); - Arrays.sort(ranked, new ClassRank()); - - // The percentage of time to save by preloading. - int timeToSave = totalTimeMicros() * percentageToPreload() / 100; - int timeSaved = 0; - - boolean service = Policy.isService(this.name); - - List highest = new ArrayList(); - for (Operation operation : ranked) { - - // These are actual ranking decisions, which can be overridden - if (!takeAllClasses) { - if (highest.size() >= MAX_TO_PRELOAD) { - System.out.println(name + " got " - + (timeSaved * 100 / timeToSave) + "% through"); - break; - } - - if (timeSaved >= timeToSave) { - break; - } - } - - // The remaining rules apply even to wired-down processes - if (!Policy.isPreloadableClass(operation.loadedClass.name)) { - continue; - } - - if (!operation.loadedClass.systemClass) { - continue; - } - - // Only load java.* class for services. - if (!service || operation.loadedClass.name.startsWith("java.")) { - highest.add(operation.loadedClass); - } - - // For services, still count the time even if it's not in java.* - timeSaved += operation.medianExclusiveTimeMicros(); - } - - return highest; - } - - /** - * Total time spent class loading and initializing. - */ - int totalTimeMicros() { - int totalTime = 0; - for (Operation operation : operations) { - totalTime += operation.medianExclusiveTimeMicros(); - } - return totalTime; - } - - /** - * Returns true if this process is an app. - * - * TODO: Replace the hardcoded list with a walk up the parent chain looking for zygote. + * Returns true if this process comes from the zygote. */ - public boolean isApplication() { - return Policy.isFromZygote(name); + public boolean fromZygote() { + return parent != null && parent.name.equals("zygote") + && !name.equals("com.android.development"); } /** diff --git a/tools/preload/Root.java b/tools/preload/Root.java index 949f9b7..0bc29bf 100644 --- a/tools/preload/Root.java +++ b/tools/preload/Root.java @@ -46,7 +46,7 @@ public class Root implements Serializable { final Map loadedClasses = new HashMap(); - final MemoryUsage baseline = MemoryUsage.baseline(); + MemoryUsage baseline = MemoryUsage.baseline(); /** * Records class loads and initializations. diff --git a/tools/preload/WritePreloadedClassFile.java b/tools/preload/WritePreloadedClassFile.java index d87b1f0..96c539b 100644 --- a/tools/preload/WritePreloadedClassFile.java +++ b/tools/preload/WritePreloadedClassFile.java @@ -20,83 +20,125 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; import java.util.Set; import java.util.TreeSet; /** - * Writes /frameworks/base/preloaded-classes. Also updates LoadedClass.preloaded - * fields and writes over compiled log file. + * Writes /frameworks/base/preloaded-classes. Also updates + * {@link LoadedClass#preloaded} fields and writes over compiled log file. */ public class WritePreloadedClassFile { - public static void main(String[] args) throws IOException, ClassNotFoundException { - - // Process command-line arguments first - List wiredProcesses = new ArrayList(); - String inputFileName = null; - int argOffset = 0; - try { - while ("--preload-all-process".equals(args[argOffset])) { - argOffset++; - wiredProcesses.add(args[argOffset++]); - } - - inputFileName = args[argOffset++]; - } catch (RuntimeException e) { - System.err.println("Usage: WritePreloadedClassFile " + - "[--preload-all-process process-name] " + - "[compiled log file]"); - System.exit(0); - } + /** + * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us. + */ + static final int MIN_LOAD_TIME_MICROS = 1250; - Root root = Root.fromFile(inputFileName); + public static void main(String[] args) throws IOException, + ClassNotFoundException { + if (args.length != 1) { + System.err.println("Usage: WritePreloadedClassFile [compiled log]"); + System.exit(-1); + } + String rootFile = args[0]; + Root root = Root.fromFile(rootFile); + // No classes are preloaded to start. for (LoadedClass loadedClass : root.loadedClasses.values()) { loadedClass.preloaded = false; } + // Open preloaded-classes file for output. Writer out = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(Policy.getPreloadedClassFileName()), + new FileOutputStream(Policy.PRELOADED_CLASS_FILE), Charset.forName("US-ASCII"))); - out.write("# Classes which are preloaded by com.android.internal.os.ZygoteInit.\n"); - out.write("# Automatically generated by /frameworks/base/tools/preload.\n"); - out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD + ", weight=" - + ClassRank.SEQUENCE_WEIGHT - + ", bucket_size=" + ClassRank.BUCKET_SIZE - + "\n"); - for (String wiredProcess : wiredProcesses) { - out.write("# forcing classes loaded by: " + wiredProcess + "\n"); - } + out.write("# Classes which are preloaded by" + + " com.android.internal.os.ZygoteInit.\n"); + out.write("# Automatically generated by frameworks/base/tools/preload/" + + WritePreloadedClassFile.class.getSimpleName() + ".java.\n"); + out.write("# MIN_LOAD_TIME_MICROS=" + MIN_LOAD_TIME_MICROS + "\n"); - Set highestRanked = new TreeSet(); - for (Proc proc : root.processes.values()) { - // test to see if this is one of the wired-down ("take all classes") processes - boolean isWired = wiredProcesses.contains(proc.name); - - List highestForProc = proc.highestRankedClasses(isWired); + /* + * The set of classes to preload. We preload a class if: + * + * a) it's loaded in the bootclasspath (i.e., is a system class) + * b) it takes > MIN_LOAD_TIME_MICROS us to load, and + * c) it's loaded by more than one process, or it's loaded by an + * application (i.e., not a long running service) + */ + Set toPreload = new TreeSet(); - System.out.println(proc.name + ": " + highestForProc.size()); + // Preload classes that were loaded by at least 2 processes. Hopefully, + // the memory associated with these classes will be shared. + for (LoadedClass loadedClass : root.loadedClasses.values()) { + Set names = loadedClass.processNames(); + if (shouldPreload(loadedClass) && names.size() > 1) { + toPreload.add(loadedClass); + } + } + + int initialSize = toPreload.size(); + System.out.println(initialSize + + " classses were loaded by more than one app."); - for (LoadedClass loadedClass : highestForProc) { - loadedClass.preloaded = true; + // Preload eligable classes from applications (not long-running + // services). + for (Proc proc : root.processes.values()) { + if (proc.fromZygote() && !Policy.isService(proc.name)) { + for (Operation operation : proc.operations) { + LoadedClass loadedClass = operation.loadedClass; + if (shouldPreload(loadedClass)) { + toPreload.add(loadedClass); + } + } } - highestRanked.addAll(highestForProc); } - for (LoadedClass loadedClass : highestRanked) { - out.write(loadedClass.name); - out.write('\n'); + System.out.println("Added " + (toPreload.size() - initialSize) + + " more to speed up applications."); + + System.out.println(toPreload.size() + + " total classes will be preloaded."); + + // Make classes that were implicitly loaded by the zygote explicit. + // This adds minimal overhead but avoid confusion about classes not + // appearing in the list. + addAllClassesFrom("zygote", root, toPreload); + + for (LoadedClass loadedClass : toPreload) { + out.write(loadedClass.name + "\n"); } out.close(); - System.out.println(highestRanked.size() - + " classes will be preloaded."); - // Update data to reflect LoadedClass.preloaded changes. - root.toFile(inputFileName); + for (LoadedClass loadedClass : toPreload) { + loadedClass.preloaded = true; + } + root.toFile(rootFile); + } + + private static void addAllClassesFrom(String processName, Root root, + Set toPreload) { + for (Proc proc : root.processes.values()) { + if (proc.name.equals(processName)) { + for (Operation operation : proc.operations) { + boolean preloadable + = Policy.isPreloadable(operation.loadedClass); + if (preloadable) { + toPreload.add(operation.loadedClass); + } + } + } + } + } + + /** + * Returns true if the class should be preloaded. + */ + private static boolean shouldPreload(LoadedClass clazz) { + return Policy.isPreloadable(clazz) + && clazz.medianTimeMicros() > MIN_LOAD_TIME_MICROS; } } diff --git a/tools/preload/loadclass/LoadClass.java b/tools/preload/loadclass/LoadClass.java index 471cc84..a71b6a8 100644 --- a/tools/preload/loadclass/LoadClass.java +++ b/tools/preload/loadclass/LoadClass.java @@ -35,7 +35,11 @@ class LoadClass { if (args.length > 0) { try { + long start = System.currentTimeMillis(); Class.forName(args[0]); + long elapsed = System.currentTimeMillis() - start; + Log.i("LoadClass", "Loaded " + args[0] + " in " + elapsed + + "ms."); } catch (ClassNotFoundException e) { Log.w("LoadClass", e); return; diff --git a/tools/preload/preload.iml b/tools/preload/preload.iml index d1fab57..2d87c55 100644 --- a/tools/preload/preload.iml +++ b/tools/preload/preload.iml @@ -1,15 +1,14 @@ - + + - - diff --git a/tools/preload/preload.ipr b/tools/preload/preload.ipr index c5613ad..0c9621c 100644 --- a/tools/preload/preload.ipr +++ b/tools/preload/preload.ipr @@ -25,7 +25,28 @@