summaryrefslogtreecommitdiffstats
path: root/tools/layoutlib/create
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:23 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:23 -0800
commitb798689749c64baba81f02e10cf2157c747d6b46 (patch)
treeda394a395ddb1a6cf69193314846b03fe47a397e /tools/layoutlib/create
parentf013e1afd1e68af5e3b868c26a653bbfb39538f8 (diff)
downloadframeworks_base-b798689749c64baba81f02e10cf2157c747d6b46.zip
frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.tar.gz
frameworks_base-b798689749c64baba81f02e10cf2157c747d6b46.tar.bz2
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'tools/layoutlib/create')
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java3
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java4
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java91
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java76
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java102
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java97
6 files changed, 326 insertions, 47 deletions
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index b4e2c2b..1adcc17 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -68,7 +68,8 @@ public class AsmGenerator {
*
* @param log Output logger.
* @param osDestJar The path of the destination JAR to create.
- * @param stubMethods The list of methods to stub out
+ * @param stubMethods The list of methods to stub out. Each entry must be in the form
+ * "package.package.OuterClass$InnerClass#MethodName".
* @param renameClasses The list of classes to rename, must be an even list: the binary FQCN
* of class to replace followed by the new FQCN.
* @param deleteReturns List of classes for which the methods returning them should be deleted.
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 13443d5..76bd8d4 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -45,9 +45,11 @@ public class Main {
AsmGenerator agen = new AsmGenerator(log, osDestJar[0],
new Class<?>[] { // classes to inject in the final JAR
OverrideMethod.class,
- OverrideMethod.MethodListener.class
+ MethodListener.class,
+ MethodAdapter.class
},
new String[] { // methods to force override
+ "android.view.View#isInEditMode",
"android.content.res.Resources$Theme#obtainStyledAttributes",
},
new String[] { // classes to rename (so that we can replace them in layoutlib)
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java
new file mode 100644
index 0000000..627ea17
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+
+/**
+ * An adapter to make it easier to use {@link MethodListener}.
+ * <p/>
+ * The adapter calls the void {@link #onInvokeV(String, boolean, Object)} listener
+ * for all types (I, L, F, D and A), returning 0 or null as appropriate.
+ */
+public class MethodAdapter implements MethodListener {
+ /**
+ * A stub method is being invoked.
+ * <p/>
+ * Known limitation: caller arguments are not available.
+ *
+ * @param signature The signature of the method being invoked, composed of the
+ * binary class name followed by the method descriptor (aka argument
+ * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
+ * @param isNative True if the method was a native method.
+ * @param caller The calling object. Null for static methods, "this" for instance methods.
+ */
+ public void onInvokeV(String signature, boolean isNative, Object caller) {
+ }
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return an integer, or a boolean, or a short or a byte.
+ */
+ public int onInvokeI(String signature, boolean isNative, Object caller) {
+ onInvokeV(signature, isNative, caller);
+ return 0;
+ }
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return a long.
+ */
+ public long onInvokeL(String signature, boolean isNative, Object caller) {
+ onInvokeV(signature, isNative, caller);
+ return 0;
+ }
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return a float.
+ */
+ public float onInvokeF(String signature, boolean isNative, Object caller) {
+ onInvokeV(signature, isNative, caller);
+ return 0;
+ }
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return a double.
+ */
+ public double onInvokeD(String signature, boolean isNative, Object caller) {
+ onInvokeV(signature, isNative, caller);
+ return 0;
+ }
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return an object.
+ */
+ public Object onInvokeA(String signature, boolean isNative, Object caller) {
+ onInvokeV(signature, isNative, caller);
+ return null;
+ }
+}
+
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java
new file mode 100644
index 0000000..6fc2b24
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tools.layoutlib.create;
+
+
+/**
+ * Interface to allow a method invocation to be listened upon.
+ * <p/>
+ * This is used by {@link OverrideMethod} to register a listener for methods that
+ * have been stubbed by the {@link AsmGenerator}. At runtime the stub will call either a
+ * default global listener or a specific listener based on the method signature.
+ */
+public interface MethodListener {
+ /**
+ * A stub method is being invoked.
+ * <p/>
+ * Known limitation: caller arguments are not available.
+ *
+ * @param signature The signature of the method being invoked, composed of the
+ * binary class name followed by the method descriptor (aka argument
+ * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
+ * @param isNative True if the method was a native method.
+ * @param caller The calling object. Null for static methods, "this" for instance methods.
+ */
+ public void onInvokeV(String signature, boolean isNative, Object caller);
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return an integer, or a boolean, or a short or a byte.
+ */
+ public int onInvokeI(String signature, boolean isNative, Object caller);
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return a long.
+ */
+ public long onInvokeL(String signature, boolean isNative, Object caller);
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return a float.
+ */
+ public float onInvokeF(String signature, boolean isNative, Object caller);
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return a double.
+ */
+ public double onInvokeD(String signature, boolean isNative, Object caller);
+
+ /**
+ * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object.
+ * @see #onInvokeV(String, boolean, Object)
+ * @return an object.
+ */
+ public Object onInvokeA(String signature, boolean isNative, Object caller);
+}
+
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java
index b061a15..a6aff99 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java
@@ -20,27 +20,13 @@ import java.util.HashMap;
/**
* Allows stub methods from LayoutLib to be overriden at runtime.
+ * <p/>
+ * Implementation note: all types required by this class(inner/outer classes & interfaces)
+ * must be referenced by the injectClass argument to {@link AsmGenerator} in Main.java;
+ * Otherwise they won't be accessible in layoutlib.jar at runtime.
*/
public final class OverrideMethod {
- /**
- * Interface to allow a method invocation to be listend upon.
- */
- public interface MethodListener {
- /**
- * A stub method is being invoked.
- * <p/>
- * Known limitation: caller arguments are not available. Return value cannot be set.
- *
- * @param signature The signature of the method being invoked, composed of the
- * binary class name followed by the method descriptor (aka argument
- * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
- * @param isNative True if the method was a native method.
- * @param caller The calling object. Null for static methods, "this" for instance methods.
- */
- public void onInvoke(String signature, boolean isNative, Object caller);
- }
-
/** Map of method overridden. */
private static HashMap<String, MethodListener> sMethods = new HashMap<String, MethodListener>();
/** Default listener for all method not listed in sMethods. Nothing if null. */
@@ -71,7 +57,9 @@ public final class OverrideMethod {
}
/**
- * Invoke the specific listener for the given signature or the default one if defined.
+ * Invokes the specific listener for the given signature or the default one if defined.
+ * <p/>
+ * This version invokes the method listener for the void return type.
* <p/>
* Note: this is not intended to be used by the LayoutLib Bridge. It is intended to be called
* by the stubbed methods generated by the LayoutLib_create tool.
@@ -82,12 +70,82 @@ public final class OverrideMethod {
* @param isNative True if the method was a native method.
* @param caller The calling object. Null for static methods, "this" for instance methods.
*/
- public static void invoke(String signature, boolean isNative, Object caller) {
+ public static void invokeV(String signature, boolean isNative, Object caller) {
+ MethodListener i = sMethods.get(signature);
+ if (i != null) {
+ i.onInvokeV(signature, isNative, caller);
+ } else if (sDefaultListener != null) {
+ sDefaultListener.onInvokeV(signature, isNative, caller);
+ }
+ }
+
+ /**
+ * Invokes the specific listener for the int return type.
+ * @see #invokeV(String, boolean, Object)
+ */
+ public static int invokeI(String signature, boolean isNative, Object caller) {
+ MethodListener i = sMethods.get(signature);
+ if (i != null) {
+ return i.onInvokeI(signature, isNative, caller);
+ } else if (sDefaultListener != null) {
+ return sDefaultListener.onInvokeI(signature, isNative, caller);
+ }
+ return 0;
+ }
+
+ /**
+ * Invokes the specific listener for the long return type.
+ * @see #invokeV(String, boolean, Object)
+ */
+ public static long invokeL(String signature, boolean isNative, Object caller) {
+ MethodListener i = sMethods.get(signature);
+ if (i != null) {
+ return i.onInvokeL(signature, isNative, caller);
+ } else if (sDefaultListener != null) {
+ return sDefaultListener.onInvokeL(signature, isNative, caller);
+ }
+ return 0;
+ }
+
+ /**
+ * Invokes the specific listener for the float return type.
+ * @see #invokeV(String, boolean, Object)
+ */
+ public static float invokeF(String signature, boolean isNative, Object caller) {
+ MethodListener i = sMethods.get(signature);
+ if (i != null) {
+ return i.onInvokeF(signature, isNative, caller);
+ } else if (sDefaultListener != null) {
+ return sDefaultListener.onInvokeF(signature, isNative, caller);
+ }
+ return 0;
+ }
+
+ /**
+ * Invokes the specific listener for the double return type.
+ * @see #invokeV(String, boolean, Object)
+ */
+ public static double invokeD(String signature, boolean isNative, Object caller) {
+ MethodListener i = sMethods.get(signature);
+ if (i != null) {
+ return i.onInvokeD(signature, isNative, caller);
+ } else if (sDefaultListener != null) {
+ return sDefaultListener.onInvokeD(signature, isNative, caller);
+ }
+ return 0;
+ }
+
+ /**
+ * Invokes the specific listener for the object return type.
+ * @see #invokeV(String, boolean, Object)
+ */
+ public static Object invokeA(String signature, boolean isNative, Object caller) {
MethodListener i = sMethods.get(signature);
if (i != null) {
- i.onInvoke(signature, isNative, caller);
+ return i.onInvokeA(signature, isNative, caller);
} else if (sDefaultListener != null) {
- sDefaultListener.onInvoke(signature, isNative, caller);
+ return sDefaultListener.onInvokeA(signature, isNative, caller);
}
+ return null;
}
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
index 9bb64bd..9a57a4a 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
@@ -74,23 +74,14 @@ class StubMethodAdapter implements MethodVisitor {
} else {
mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
}
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invoke",
- "(Ljava/lang/String;ZLjava/lang/Object;)V");
- }
- private void generateReturn() {
- /* Generates one of, depending on the return type:
- * return;
- * return 0;
- * return 0L;
- * return 0.0f;
- * return 0.0;
- * return null;
- */
- switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) {
+ int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID;
+ switch(sort) {
case Type.VOID:
+ mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "com/android/tools/layoutlib/create/OverrideMethod",
+ "invokeV",
+ "(Ljava/lang/String;ZLjava/lang/Object;)V");
mParentVisitor.visitInsn(Opcodes.RETURN);
break;
case Type.BOOLEAN:
@@ -98,27 +89,86 @@ class StubMethodAdapter implements MethodVisitor {
case Type.BYTE:
case Type.SHORT:
case Type.INT:
- mParentVisitor.visitInsn(Opcodes.ICONST_0);
+ mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "com/android/tools/layoutlib/create/OverrideMethod",
+ "invokeI",
+ "(Ljava/lang/String;ZLjava/lang/Object;)I");
+ switch(sort) {
+ case Type.BOOLEAN:
+ Label l1 = new Label();
+ mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1);
+ mParentVisitor.visitInsn(Opcodes.ICONST_1);
+ mParentVisitor.visitInsn(Opcodes.IRETURN);
+ mParentVisitor.visitLabel(l1);
+ mParentVisitor.visitInsn(Opcodes.ICONST_0);
+ break;
+ case Type.CHAR:
+ mParentVisitor.visitInsn(Opcodes.I2C);
+ break;
+ case Type.BYTE:
+ mParentVisitor.visitInsn(Opcodes.I2B);
+ break;
+ case Type.SHORT:
+ mParentVisitor.visitInsn(Opcodes.I2S);
+ break;
+ }
mParentVisitor.visitInsn(Opcodes.IRETURN);
break;
case Type.LONG:
- mParentVisitor.visitInsn(Opcodes.LCONST_0);
+ mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "com/android/tools/layoutlib/create/OverrideMethod",
+ "invokeL",
+ "(Ljava/lang/String;ZLjava/lang/Object;)J");
mParentVisitor.visitInsn(Opcodes.LRETURN);
break;
case Type.FLOAT:
- mParentVisitor.visitInsn(Opcodes.FCONST_0);
+ mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "com/android/tools/layoutlib/create/OverrideMethod",
+ "invokeF",
+ "(Ljava/lang/String;ZLjava/lang/Object;)F");
mParentVisitor.visitInsn(Opcodes.FRETURN);
break;
case Type.DOUBLE:
- mParentVisitor.visitInsn(Opcodes.DCONST_0);
+ mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "com/android/tools/layoutlib/create/OverrideMethod",
+ "invokeD",
+ "(Ljava/lang/String;ZLjava/lang/Object;)D");
mParentVisitor.visitInsn(Opcodes.DRETURN);
break;
case Type.ARRAY:
case Type.OBJECT:
- mParentVisitor.visitInsn(Opcodes.ACONST_NULL);
+ mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
+ "com/android/tools/layoutlib/create/OverrideMethod",
+ "invokeA",
+ "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;");
+ mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
mParentVisitor.visitInsn(Opcodes.ARETURN);
break;
}
+
+ }
+
+ private void generatePop() {
+ /* Pops the stack, depending on the return type.
+ */
+ switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) {
+ case Type.VOID:
+ break;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ case Type.FLOAT:
+ case Type.ARRAY:
+ case Type.OBJECT:
+ mParentVisitor.visitInsn(Opcodes.POP);
+ break;
+ case Type.LONG:
+ case Type.DOUBLE:
+ mParentVisitor.visitInsn(Opcodes.POP2);
+ break;
+ }
}
/* Pass down to visitor writer. In this implementation, either do nothing. */
@@ -134,7 +184,6 @@ class StubMethodAdapter implements MethodVisitor {
public void visitMaxs(int maxStack, int maxLocals) {
if (!mIsInitMethod && !mMessageGenerated) {
generateInvoke();
- generateReturn();
mMessageGenerated = true;
}
mParentVisitor.visitMaxs(maxStack, maxLocals);
@@ -148,7 +197,6 @@ class StubMethodAdapter implements MethodVisitor {
public void visitEnd() {
if (!mIsInitMethod && !mMessageGenerated) {
generateInvoke();
- generateReturn();
mMessageGenerated = true;
mParentVisitor.visitMaxs(1, 1);
}
@@ -198,10 +246,13 @@ class StubMethodAdapter implements MethodVisitor {
case Opcodes.FRETURN:
case Opcodes.IRETURN:
case Opcodes.LRETURN:
+ // Pop the last word from the stack since invoke will generate its own return.
+ generatePop();
generateInvoke();
mMessageGenerated = true;
+ default:
+ mParentVisitor.visitInsn(opcode);
}
- mParentVisitor.visitInsn(opcode);
}
}