From cc5e69e4fed8bb797dc3f83c1de32eaf4a52f324 Mon Sep 17 00:00:00 2001 From: Deepanshu Gupta Date: Wed, 20 May 2015 14:51:37 -0700 Subject: Inject anonymous inner classes of injected classes [DO NOT MERGE] When injecting classes in LayoutLib (eg. CreateInfo), so that LayoutLib can refer back to the changes, also inject the anonymous inner classes. Without this, the injected classes are not loadable. Although, LayoutLib itself doesn't load these classes, but some tests do. Change-Id: Ib5f6b779ef4d79dec8d614d3dbb26eeac88a1064 (cherry picked from commit bfc9c3bcbe3b7056d3330f754811c1506f181b88) --- .../tools/layoutlib/create/AsmGenerator.java | 28 +++++++++++++++------- .../android/tools/layoutlib/create/CreateInfo.java | 3 ++- .../tools/layoutlib/create/ICreateInfo.java | 8 ++++++- .../layoutlib/create/InjectMethodRunnables.java | 4 +++- 4 files changed, 32 insertions(+), 11 deletions(-) (limited to 'tools') 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 3aa7cdf..f6c2626 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 @@ -24,9 +24,11 @@ import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; @@ -86,7 +88,23 @@ public class AsmGenerator { public AsmGenerator(Log log, String osDestJar, ICreateInfo createInfo) { mLog = log; mOsDestJar = osDestJar; - mInjectClasses = createInfo.getInjectedClasses(); + ArrayList> injectedClasses = + new ArrayList>(Arrays.asList(createInfo.getInjectedClasses())); + // Search for and add anonymous inner classes also. + ListIterator> iter = injectedClasses.listIterator(); + while (iter.hasNext()) { + Class clazz = iter.next(); + try { + int i = 1; + while(i < 100) { + iter.add(Class.forName(clazz.getName() + "$" + i)); + i++; + } + } catch (ClassNotFoundException ignored) { + // Expected. + } + } + mInjectClasses = injectedClasses.toArray(new Class[0]); mStubMethods = new HashSet(Arrays.asList(createInfo.getOverriddenMethods())); // Create the map/set of methods to change to delegates @@ -290,13 +308,7 @@ public class AsmGenerator { * e.g. it returns something like "com/foo/OuterClass$InnerClass1$InnerClass2.class" */ private String classToEntryPath(Class clazz) { - String name = ""; - Class parent; - while ((parent = clazz.getEnclosingClass()) != null) { - name = "$" + clazz.getSimpleName() + name; - clazz = parent; - } - return classNameToEntryPath(clazz.getCanonicalName() + name); + return classNameToEntryPath(clazz.getName()); } /** diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index f7139e9..506aa7c 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -136,6 +136,8 @@ public final class CreateInfo implements ICreateInfo { ICreateInfo.class, CreateInfo.class, LayoutlibDelegate.class, + InjectMethodRunnable.class, + InjectMethodRunnables.class, /* Java package classes */ AutoCloseable.class, Objects.class, @@ -304,4 +306,3 @@ public final class CreateInfo implements ICreateInfo { InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER); }}; } - diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java index ac10639..54b1fe6 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java @@ -85,6 +85,12 @@ public interface ICreateInfo { Map getInjectedMethodsMap(); abstract class InjectMethodRunnable { - public abstract void generateMethods(ClassVisitor cv); + /** + * @param cv Must be {@link ClassVisitor}. However, the param type is object so that when + * loading the class, ClassVisitor is not loaded. This is because when injecting + * CreateInfo in LayoutLib (see {@link #getInjectedClasses()}, we don't want to inject + * asm classes also, but still keep CreateInfo loadable. + */ + public abstract void generateMethods(Object cv); } } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java index 39d46d7..37fc096 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java @@ -30,7 +30,9 @@ public class InjectMethodRunnables { public static final ICreateInfo.InjectMethodRunnable CONTEXT_GET_FRAMEWORK_CLASS_LOADER = new InjectMethodRunnable() { @Override - public void generateMethods(ClassVisitor cv) { + public void generateMethods(Object classVisitor) { + assert classVisitor instanceof ClassVisitor; + ClassVisitor cv = (ClassVisitor) classVisitor; // generated by compiling the class: // class foo { public ClassLoader getFrameworkClassLoader() { return getClass().getClassLoader(); } } // and then running ASMifier on it: -- cgit v1.1