am 8a70bcef: resolved conflicts for merge 5a7b3b65 to jb-dev-plus-aosp

* commit '8a70bcef5a724906e3c35c58cb2266ee9c9e1b78':
  Remove references to non-std Java classes. [DO NOT MERGE]
diff --git a/tools/layoutlib/create/.classpath b/tools/layoutlib/create/.classpath
index dbc4cfd..cd8bb0d 100644
--- a/tools/layoutlib/create/.classpath
+++ b/tools/layoutlib/create/.classpath
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
 	<classpathentry kind="src" path="src"/>
-	<classpathentry excluding="mock_android/" kind="src" path="tests"/>
+	<classpathentry excluding="mock_data/" kind="src" path="tests"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
-	<classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar"/>
+	<classpathentry kind="var" path="ANDROID_SRC/prebuilts/tools/common/asm-tools/asm-4.0.jar" sourcepath="/ANDROID_PLAT/prebuilts/tools/common/asm-tools/src-4.0.zip"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/create/README.txt b/tools/layoutlib/create/README.txt
index 894611b..e490ac5 100644
--- a/tools/layoutlib/create/README.txt
+++ b/tools/layoutlib/create/README.txt
@@ -71,6 +71,9 @@
 and "." and "$" are interpreted as-is).
 In practice we almost but not quite request the inclusion of full packages.
 
+The analyzer is also given a list of classes to exclude. A fake implementation of these
+classes is injected by the Generator.
+
 With this information, the analyzer parses the input zip to find all the classes.
 All classes deriving from the requested bases classes are kept.
 All classes which name matched the glob pattern are kept.
@@ -93,6 +96,7 @@
 - specific methods for which to delegate calls.
 - specific methods to remove based on their return type.
 - specific classes to rename.
+- specific classes to refactor.
 
 Each of these are specific strategies we use to be able to modify the Android code
 to fit within the Eclipse renderer. These strategies are explained beow.
@@ -100,10 +104,7 @@
 The core method of the generator is transform(): it takes an input ASM ClassReader
 and modifies it to produce a byte array suitable for the final JAR file.
 
-The first step of the transformation is changing the name of the class in case
-we requested the class to be renamed. This uses the RenameClassAdapter to also rename
-all inner classes and references in methods and types. Note that other classes are
-not transformed and keep referencing the original name.
+The first step of the transformation is to implement the method delegates.
 
 The TransformClassAdapter is then used to process the potentially renamed class.
 All protected or private classes are market as public.
@@ -115,11 +116,25 @@
 The code of the methods is then kept as-is, except for native methods which are
 replaced by a stub. Methods that are to be overridden are also replaced by a stub.
 
-The transformed class is then fed through the DelegateClassAdapter to implement
-method delegates. 
-
 Finally fields are also visited and changed from protected/private to public.
 
+The next step of the transformation is changing the name of the class in case
+we requested the class to be renamed. This uses the RenameClassAdapter to also rename
+all inner classes and references in methods and types. Note that other classes are
+not transformed and keep referencing the original name.
+
+The class is then fed to RefactorClassAdapter which is like RenameClassAdapter but
+updates the references in all classes. This is used to update the references of classes
+in the java package that were added in the Dalvik VM but are not a part of the standard
+JVM. The existing classes are modified to update all references to these non-standard
+classes. An alternate implementation of these (com.android.tools.layoutlib.java.*) is
+injected.
+
+The ClassAdapters are chained together to achieve the desired output. (Look at section
+2.2.7 Transformation chains in the asm user guide, link in the References.) The order of
+execution of these is:
+ClassReader -> [DelegateClassAdapter] -> TransformClassAdapter -> [RenameClassAdapter] ->
+RefactorClassAdapter -> ClassWriter
 
 - Method stubs
 --------------
@@ -141,19 +156,28 @@
 - Strategies
 ------------
 
-We currently have 4 strategies to deal with overriding the rendering code
+We currently have 6 strategies to deal with overriding the rendering code
 and make it run in Eclipse. Most of these strategies are implemented hand-in-hand
 by the bridge (which runs in Eclipse) and the generator.
 
 
 1- Class Injection
 
-This is the easiest: we currently inject 4 classes, namely:
+This is the easiest: we currently inject the following classes:
 - OverrideMethod and its associated MethodListener and MethodAdapter are used
   to intercept calls to some specific methods that are stubbed out and change
   their return value.
 - CreateInfo class, which configured the generator. Not used yet, but could
   in theory help us track what the generator changed.
+- AutoCloseable is part of Java 7. To enable us to still run on Java 6, a new class is
+  injected. The implementation for the class has been taken from Android's libcore
+  (platform/libcore/luni/src/main/java/java/lang/AutoCloseable.java).
+- Charsets, ModifiedUtf8, IntegralToString and UnsafeByteSequence are not part of the
+  standard JAVA VM.
+  They are added to the Dalvik VM for performance reasons. An implementation that is very
+  close to the original (which is at platform/libcore/luni/src/main/java/...) is injected.
+  Since these classees were in part of the java package, where we can't inject classes,
+  all references to these have been updated (See strategy 4- Refactoring Classes).
 
 
 2- Overriding methods
@@ -189,7 +213,15 @@
 This won't rename/replace the inner static methods of a given class.
 
 
-4- Method erasure based on return type
+4- Refactoring classes
+
+This is very similar to the Renaming classes except that it also updates the reference in
+all classes. This is done for classes which are added to the Dalvik VM for performance
+reasons but are not present in the Standard Java VM. An implementation for these classes
+is also injected.
+
+
+5- Method erasure based on return type
 
 This is mostly an implementation detail of the bridge: in the Paint class
 mentioned above, some inner static classes are used to pass around
@@ -201,7 +233,7 @@
 bridge will provide its own implementation.
 
 
-5- Method Delegates
+6- Method Delegates
 
 This strategy is used to override method implementations.
 Given a method SomeClass.MethodName(), 1 or 2 methods are generated:
@@ -233,7 +265,7 @@
   http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
 
 ASM user guide:
-  http://download.forge.objectweb.org/asm/asm-guide.pdf
+  http://download.forge.objectweb.org/asm/asm4-guide.pdf
 
 
 --
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
new file mode 100644
index 0000000..b2caa25
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2013 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;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.signature.SignatureReader;
+import org.objectweb.asm.signature.SignatureVisitor;
+import org.objectweb.asm.signature.SignatureWriter;
+
+/**
+ * Provides the common code for RenameClassAdapter and RefactorClassAdapter. It
+ * goes through the complete class and finds references to other classes. It
+ * then calls {@link #renameInternalType(String)} to convert the className to
+ * the new value, if need be.
+ */
+public abstract class AbstractClassAdapter extends ClassVisitor {
+
+    /**
+     * Returns the new FQCN for the class, if the reference to this class needs
+     * to be updated. Else, it returns the same string.
+     * @param name Old FQCN
+     * @return New FQCN if it needs to be renamed, else the old FQCN
+     */
+    abstract String renameInternalType(String name);
+
+    public AbstractClassAdapter(ClassVisitor cv) {
+        super(Opcodes.ASM4, cv);
+    }
+
+    /**
+     * Renames a type descriptor, e.g. "Lcom.package.MyClass;"
+     * If the type doesn't need to be renamed, returns the input string as-is.
+     */
+    String renameTypeDesc(String desc) {
+        if (desc == null) {
+            return null;
+        }
+
+        return renameType(Type.getType(desc));
+    }
+
+    /**
+     * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
+     * object element, e.g. "[Lcom.package.MyClass;"
+     * If the type doesn't need to be renamed, returns the internal name of the input type.
+     */
+    String renameType(Type type) {
+        if (type == null) {
+            return null;
+        }
+
+        if (type.getSort() == Type.OBJECT) {
+            String in = type.getInternalName();
+            return "L" + renameInternalType(in) + ";";
+        } else if (type.getSort() == Type.ARRAY) {
+            StringBuilder sb = new StringBuilder();
+            for (int n = type.getDimensions(); n > 0; n--) {
+                sb.append('[');
+            }
+            sb.append(renameType(type.getElementType()));
+            return sb.toString();
+        }
+        return type.getDescriptor();
+    }
+
+    /**
+     * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
+     * object element, e.g. "[Lcom.package.MyClass;".
+     * This is like renameType() except that it returns a Type object.
+     * If the type doesn't need to be renamed, returns the input type object.
+     */
+    Type renameTypeAsType(Type type) {
+        if (type == null) {
+            return null;
+        }
+
+        if (type.getSort() == Type.OBJECT) {
+            String in = type.getInternalName();
+            String newIn = renameInternalType(in);
+            if (newIn != in) {
+                return Type.getType("L" + newIn + ";");
+            }
+        } else if (type.getSort() == Type.ARRAY) {
+            StringBuilder sb = new StringBuilder();
+            for (int n = type.getDimensions(); n > 0; n--) {
+                sb.append('[');
+            }
+            sb.append(renameType(type.getElementType()));
+            return Type.getType(sb.toString());
+        }
+        return type;
+    }
+
+    /**
+     * Renames a method descriptor, i.e. applies renameType to all arguments and to the
+     * return value.
+     */
+    String renameMethodDesc(String desc) {
+        if (desc == null) {
+            return null;
+        }
+
+        Type[] args = Type.getArgumentTypes(desc);
+
+        StringBuilder sb = new StringBuilder("(");
+        for (Type arg : args) {
+            String name = renameType(arg);
+            sb.append(name);
+        }
+        sb.append(')');
+
+        Type ret = Type.getReturnType(desc);
+        String name = renameType(ret);
+        sb.append(name);
+
+        return sb.toString();
+    }
+
+
+    /**
+     * Renames the ClassSignature handled by ClassVisitor.visit
+     * or the MethodTypeSignature handled by ClassVisitor.visitMethod.
+     */
+    String renameTypeSignature(String sig) {
+        if (sig == null) {
+            return null;
+        }
+        SignatureReader reader = new SignatureReader(sig);
+        SignatureWriter writer = new SignatureWriter();
+        reader.accept(new RenameSignatureAdapter(writer));
+        sig = writer.toString();
+        return sig;
+    }
+
+
+    /**
+     * Renames the FieldTypeSignature handled by ClassVisitor.visitField
+     * or MethodVisitor.visitLocalVariable.
+     */
+    String renameFieldSignature(String sig) {
+        return renameTypeSignature(sig);
+    }
+
+
+    //----------------------------------
+    // Methods from the ClassAdapter
+
+    @Override
+    public void visit(int version, int access, String name, String signature,
+            String superName, String[] interfaces) {
+        name = renameInternalType(name);
+        superName = renameInternalType(superName);
+        signature = renameTypeSignature(signature);
+        if (interfaces != null) {
+            for (int i = 0; i < interfaces.length; ++i) {
+                interfaces[i] = renameInternalType(interfaces[i]);
+            }
+        }
+
+        super.visit(version, access, name, signature, superName, interfaces);
+    }
+
+    @Override
+    public void visitInnerClass(String name, String outerName, String innerName, int access) {
+        name = renameInternalType(name);
+        outerName = renameInternalType(outerName);
+        super.visitInnerClass(name, outerName, innerName, access);
+    }
+
+    @Override
+    public void visitOuterClass(String owner, String name, String desc) {
+        super.visitOuterClass(renameInternalType(owner), name, renameTypeDesc(desc));
+    }
+
+    @Override
+    public MethodVisitor visitMethod(int access, String name, String desc,
+            String signature, String[] exceptions) {
+        desc = renameMethodDesc(desc);
+        signature = renameTypeSignature(signature);
+        MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
+        return new RenameMethodAdapter(mw);
+    }
+
+    @Override
+    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        desc = renameTypeDesc(desc);
+        return super.visitAnnotation(desc, visible);
+    }
+
+    @Override
+    public FieldVisitor visitField(int access, String name, String desc,
+            String signature, Object value) {
+        desc = renameTypeDesc(desc);
+        return super.visitField(access, name, desc, signature, value);
+    }
+
+
+    //----------------------------------
+
+    /**
+     * A method visitor that renames all references from an old class name to a new class name.
+     */
+    public class RenameMethodAdapter extends MethodVisitor {
+
+        /**
+         * Creates a method visitor that renames all references from a given old name to a given new
+         * name. The method visitor will also rename all inner classes.
+         * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass).
+         */
+        public RenameMethodAdapter(MethodVisitor mv) {
+            super(Opcodes.ASM4, mv);
+        }
+
+        @Override
+        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+            desc = renameTypeDesc(desc);
+
+            return super.visitAnnotation(desc, visible);
+        }
+
+        @Override
+        public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
+            desc = renameTypeDesc(desc);
+
+            return super.visitParameterAnnotation(parameter, desc, visible);
+        }
+
+        @Override
+        public void visitTypeInsn(int opcode, String type) {
+            // The type sometimes turns out to be a type descriptor. We try to detect it and fix.
+            if (type.indexOf(';') > 0) {
+                type = renameTypeDesc(type);
+            } else {
+                type = renameInternalType(type);
+            }
+            super.visitTypeInsn(opcode, type);
+        }
+
+        @Override
+        public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+            owner = renameInternalType(owner);
+            desc = renameTypeDesc(desc);
+
+            super.visitFieldInsn(opcode, owner, name, desc);
+        }
+
+        @Override
+        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+            // The owner sometimes turns out to be a type descriptor. We try to detect it and fix.
+            if (owner.indexOf(';') > 0) {
+                owner = renameTypeDesc(owner);
+            } else {
+                owner = renameInternalType(owner);
+            }
+            desc = renameMethodDesc(desc);
+
+            super.visitMethodInsn(opcode, owner, name, desc);
+        }
+
+        @Override
+        public void visitLdcInsn(Object cst) {
+            // If cst is a Type, this means the code is trying to pull the .class constant
+            // for this class, so it needs to be renamed too.
+            if (cst instanceof Type) {
+                cst = renameTypeAsType((Type) cst);
+            }
+            super.visitLdcInsn(cst);
+        }
+
+        @Override
+        public void visitMultiANewArrayInsn(String desc, int dims) {
+            desc = renameTypeDesc(desc);
+
+            super.visitMultiANewArrayInsn(desc, dims);
+        }
+
+        @Override
+        public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+            type = renameInternalType(type);
+
+            super.visitTryCatchBlock(start, end, handler, type);
+        }
+
+        @Override
+        public void visitLocalVariable(String name, String desc, String signature,
+                Label start, Label end, int index) {
+            desc = renameTypeDesc(desc);
+            signature = renameFieldSignature(signature);
+
+            super.visitLocalVariable(name, desc, signature, start, end, index);
+        }
+
+    }
+
+    //----------------------------------
+
+    public class RenameSignatureAdapter extends SignatureVisitor {
+
+        private final SignatureVisitor mSv;
+
+        public RenameSignatureAdapter(SignatureVisitor sv) {
+            super(Opcodes.ASM4);
+            mSv = sv;
+        }
+
+        @Override
+        public void visitClassType(String name) {
+            name = renameInternalType(name);
+            mSv.visitClassType(name);
+        }
+
+        @Override
+        public void visitInnerClassType(String name) {
+            name = renameInternalType(name);
+            mSv.visitInnerClassType(name);
+        }
+
+        @Override
+        public SignatureVisitor visitArrayType() {
+            SignatureVisitor sv = mSv.visitArrayType();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public void visitBaseType(char descriptor) {
+            mSv.visitBaseType(descriptor);
+        }
+
+        @Override
+        public SignatureVisitor visitClassBound() {
+            SignatureVisitor sv = mSv.visitClassBound();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public void visitEnd() {
+            mSv.visitEnd();
+        }
+
+        @Override
+        public SignatureVisitor visitExceptionType() {
+            SignatureVisitor sv = mSv.visitExceptionType();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public void visitFormalTypeParameter(String name) {
+            mSv.visitFormalTypeParameter(name);
+        }
+
+        @Override
+        public SignatureVisitor visitInterface() {
+            SignatureVisitor sv = mSv.visitInterface();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public SignatureVisitor visitInterfaceBound() {
+            SignatureVisitor sv = mSv.visitInterfaceBound();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public SignatureVisitor visitParameterType() {
+            SignatureVisitor sv = mSv.visitParameterType();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public SignatureVisitor visitReturnType() {
+            SignatureVisitor sv = mSv.visitReturnType();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public SignatureVisitor visitSuperclass() {
+            SignatureVisitor sv = mSv.visitSuperclass();
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public void visitTypeArgument() {
+            mSv.visitTypeArgument();
+        }
+
+        @Override
+        public SignatureVisitor visitTypeArgument(char wildcard) {
+            SignatureVisitor sv = mSv.visitTypeArgument(wildcard);
+            return new RenameSignatureAdapter(sv);
+        }
+
+        @Override
+        public void visitTypeVariable(String name) {
+            mSv.visitTypeVariable(name);
+        }
+
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index 412695f..1572a40 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -34,6 +34,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.TreeMap;
 import java.util.regex.Pattern;
 import java.util.zip.ZipEntry;
@@ -57,6 +58,8 @@
     private final String[] mDeriveFrom;
     /** Glob patterns of classes to keep, e.g. "com.foo.*" */
     private final String[] mIncludeGlobs;
+    /** The set of classes to exclude.*/
+    private final Set<String> mExcludedClasses;
 
     /**
      * Creates a new analyzer.
@@ -69,12 +72,13 @@
      *        ("*" does not matches dots whilst "**" does, "." and "$" are interpreted as-is)
      */
     public AsmAnalyzer(Log log, List<String> osJarPath, AsmGenerator gen,
-            String[] deriveFrom, String[] includeGlobs) {
+            String[] deriveFrom, String[] includeGlobs, Set<String> excludeClasses) {
         mLog = log;
         mGen = gen;
         mOsSourceJar = osJarPath != null ? osJarPath : new ArrayList<String>();
         mDeriveFrom = deriveFrom != null ? deriveFrom : new String[0];
         mIncludeGlobs = includeGlobs != null ? includeGlobs : new String[0];
+        mExcludedClasses = excludeClasses;
     }
 
     /**
@@ -82,9 +86,6 @@
      * Fills the generator with classes & dependencies found.
      */
     public void analyze() throws IOException, LogAbortException {
-
-        AsmAnalyzer visitor = this;
-
         Map<String, ClassReader> zipClasses = parseZip(mOsSourceJar);
         mLog.info("Found %d classes in input JAR%s.", zipClasses.size(),
                 mOsSourceJar.size() > 1 ? "s" : "");
@@ -232,7 +233,7 @@
      */
     void findClassesDerivingFrom(String super_name, Map<String, ClassReader> zipClasses,
             Map<String, ClassReader> inOutFound) throws LogAbortException {
-        ClassReader super_clazz = findClass(super_name, zipClasses, inOutFound);
+        findClass(super_name, zipClasses, inOutFound);
 
         for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
             String className = entry.getKey();
@@ -363,11 +364,12 @@
 
             className = internalToBinaryClassName(className);
 
-            // exclude classes that have already been found
+            // exclude classes that have already been found or are marked to be excluded
             if (mInKeep.containsKey(className) ||
                     mOutKeep.containsKey(className) ||
                     mInDeps.containsKey(className) ||
-                    mOutDeps.containsKey(className)) {
+                    mOutDeps.containsKey(className) ||
+                    mExcludedClasses.contains(getBaseName(className))) {
                 return;
             }
 
@@ -451,6 +453,13 @@
             }
         }
 
+        private String getBaseName(String className) {
+            int pos = className.indexOf('$');
+            if (pos > 0) {
+                return className.substring(0, pos);
+            }
+            return className;
+        }
 
         // ---------------------------------------------------
         // --- ClassVisitor, FieldVisitor
@@ -682,7 +691,7 @@
             }
 
             @Override
-            public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
+            public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
                 // pass -- table switch instruction
 
             }
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 a9ede26..b102561 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
@@ -65,6 +65,9 @@
     /** A map { FQCN => set { method names } } of methods to rewrite as delegates.
      *  The special name {@link DelegateClassAdapter#ALL_NATIVES} can be used as in internal set. */
     private final HashMap<String, Set<String>> mDelegateMethods;
+    /** FQCN Names of classes to refactor. All reference to old-FQCN will be updated to new-FQCN.
+     * map old-FQCN => new-FQCN */
+    private final HashMap<String, String> mRefactorClasses;
 
     /**
      * Creates a new generator that can generate the output JAR with the stubbed classes.
@@ -119,6 +122,17 @@
             mClassesNotRenamed.add(oldFqcn);
         }
 
+        // Create a map of classes to be refactored.
+        mRefactorClasses = new HashMap<String, String>();
+        String[] refactorClasses = createInfo.getJavaPkgClasses();
+        n = refactorClasses.length;
+        for (int i = 0; i < n; i += 2) {
+            assert i + 1 < n;
+            String oldFqcn = binaryToInternalClassName(refactorClasses[i]);
+            String newFqcn = binaryToInternalClassName(refactorClasses[i + 1]);
+            mRefactorClasses.put(oldFqcn, newFqcn);;
+        }
+
         // create the map of renamed class -> return type of method to delete.
         mDeleteReturns = new HashMap<String, Set<String>>();
         String[] deleteReturns = createInfo.getDeleteReturns();
@@ -308,14 +322,14 @@
         // original class reader.
         ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
 
-        ClassVisitor rv = cw;
+        ClassVisitor cv = new RefactorClassAdapter(cw, mRefactorClasses);
         if (newName != className) {
-            rv = new RenameClassAdapter(cw, className, newName);
+            cv = new RenameClassAdapter(cv, className, newName);
         }
 
-        ClassVisitor cv = new TransformClassAdapter(mLog, mStubMethods,
+        cv = new TransformClassAdapter(mLog, mStubMethods,
                 mDeleteReturns.get(className),
-                newName, rv,
+                newName, cv,
                 stubNativesOnly, stubNativesOnly || hasNativeMethods);
 
         Set<String> delegateMethods = mDelegateMethods.get(className);
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 fb8272a..e73d3cf 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
@@ -17,6 +17,11 @@
 package com.android.tools.layoutlib.create;
 
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import com.android.tools.layoutlib.java.AutoCloseable;
+import com.android.tools.layoutlib.java.ModifiedUtf8;
+import com.android.tools.layoutlib.java.Charsets;
+import com.android.tools.layoutlib.java.IntegralToString;
+import com.android.tools.layoutlib.java.UnsafeByteSequence;
 
 /**
  * Describes the work to be done by {@link AsmGenerator}.
@@ -84,6 +89,15 @@
         return DELETE_RETURNS;
     }
 
+    /**
+     * Returns the list of classes to refactor, must be an even list: the binary FQCN of class to
+     * replace followed by the new FQCN. All references to the old class should be updated to the
+     * new class. The list can be empty but must not be null.
+     */
+    @Override
+    public String[] getJavaPkgClasses() {
+      return JAVA_PKG_CLASSES;
+    }
     //-----
 
     /**
@@ -95,7 +109,13 @@
             MethodAdapter.class,
             ICreateInfo.class,
             CreateInfo.class,
-            LayoutlibDelegate.class
+            LayoutlibDelegate.class,
+            /* Java package classes */
+            AutoCloseable.class,
+            IntegralToString.class,
+            UnsafeByteSequence.class,
+            ModifiedUtf8.class,
+            Charsets.class,
         };
 
     /**
@@ -196,6 +216,20 @@
         };
 
     /**
+     * The list of class references to update, must be an even list: the binary
+     * FQCN of class to replace followed by the new FQCN. The classes to
+     * replace are to be excluded from the output.
+     */
+    private final static String[] JAVA_PKG_CLASSES =
+        new String[] {
+            "java.lang.AutoCloseable",                         "com.android.tools.layoutlib.java.AutoCloseable",
+            "java.nio.charset.ModifiedUtf8",                   "com.android.tools.layoutlib.java.ModifiedUtf8",
+            "java.nio.charset.Charsets",                       "com.android.tools.layoutlib.java.Charsets",
+            "java.lang.IntegralToString",                      "com.android.tools.layoutlib.java.IntegralToString",
+            "java.lang.UnsafeByteSequence",                    "com.android.tools.layoutlib.java.UnsafeByteSequence",
+        };
+
+    /**
      * List of classes for which the methods returning them should be deleted.
      * The array contains a list of null terminated section starting with the name of the class
      * to rename in which the methods are deleted, followed by a list of return types identifying
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 40c1706..9387814 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
@@ -62,4 +62,11 @@
      */
     public abstract String[] getDeleteReturns();
 
+    /**
+     * Returns the list of classes to refactor, must be an even list: the
+     * binary FQCN of class to replace followed by the new FQCN. All references
+     * to the old class should be updated to the new class.
+     * The list can be empty but must not be null.
+     */
+    public abstract String[] getJavaPkgClasses();
 }
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 9cd74db..11433aa 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
@@ -18,6 +18,7 @@
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -86,7 +87,9 @@
         }
 
         try {
-            AsmGenerator agen = new AsmGenerator(log, osDestJar, new CreateInfo());
+            CreateInfo info = new CreateInfo();
+            Set<String> excludeClasses = getExcludedClasses(info);
+            AsmGenerator agen = new AsmGenerator(log, osDestJar[0], info);
 
             AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
                     new String[] {                          // derived from
@@ -110,7 +113,8 @@
                         "android.pim.*", // for datepicker
                         "android.os.*",  // for android.os.Handler
                         "android.database.ContentObserver", // for Digital clock
-                        });
+                    },
+                    excludeClasses);
             aa.analyze();
             agen.generate();
 
@@ -162,6 +166,16 @@
         return 0;
     }
 
+    private static Set<String> getExcludedClasses(CreateInfo info) {
+        String[] refactoredClasses = info.getJavaPkgClasses();
+        Set<String> excludedClasses = new HashSet<String>(refactoredClasses.length);
+        for (int i = 0; i < refactoredClasses.length; i+=2) {
+            excludedClasses.add(refactoredClasses[i]);
+        }
+        return excludedClasses;
+
+    }
+
     /**
      * Returns true if args where properly parsed.
      * Returns false if program should exit with command-line usage.
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
new file mode 100644
index 0000000..91161f5
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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;
+
+import java.util.HashMap;
+
+import org.objectweb.asm.ClassVisitor;
+
+public class RefactorClassAdapter extends AbstractClassAdapter {
+
+    private final HashMap<String, String> mRefactorClasses;
+
+    RefactorClassAdapter(ClassVisitor cv, HashMap<String, String> refactorClasses) {
+        super(cv);
+        mRefactorClasses = refactorClasses;
+    }
+
+    @Override
+    protected String renameInternalType(String oldClassName) {
+        if (oldClassName != null) {
+            String newName = mRefactorClasses.get(oldClassName);
+            if (newName != null) {
+                return newName;
+            }
+            int pos = oldClassName.indexOf('$');
+            if (pos > 0) {
+                newName = mRefactorClasses.get(oldClassName.substring(0, pos));
+                if (newName != null) {
+                    return newName + oldClassName.substring(pos);
+                }
+            }
+        }
+        return oldClassName;
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java
index 383cbb8..661074c 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java
@@ -16,17 +16,7 @@
 
 package com.android.tools.layoutlib.create;
 
-import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.signature.SignatureReader;
-import org.objectweb.asm.signature.SignatureVisitor;
-import org.objectweb.asm.signature.SignatureWriter;
 
 /**
  * This class visitor renames a class from a given old name to a given new name.
@@ -36,7 +26,7 @@
  * For inner classes, this handles only the case where the outer class name changes.
  * The inner class name should remain the same.
  */
-public class RenameClassAdapter extends ClassVisitor {
+public class RenameClassAdapter extends AbstractClassAdapter {
 
 
     private final String mOldName;
@@ -49,8 +39,8 @@
      * The class visitor will also rename all inner classes and references in the methods.
      * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass).
      */
-    public RenameClassAdapter(ClassWriter cv, String oldName, String newName) {
-        super(Opcodes.ASM4, cv);
+    public RenameClassAdapter(ClassVisitor cv, String oldName, String newName) {
+        super(cv);
         mOldBase = mOldName = oldName;
         mNewBase = mNewName = newName;
 
@@ -66,71 +56,6 @@
         assert (mOldBase == null && mNewBase == null) || (mOldBase != null && mNewBase != null);
     }
 
-
-    /**
-     * Renames a type descriptor, e.g. "Lcom.package.MyClass;"
-     * If the type doesn't need to be renamed, returns the input string as-is.
-     */
-    String renameTypeDesc(String desc) {
-        if (desc == null) {
-            return null;
-        }
-
-        return renameType(Type.getType(desc));
-    }
-
-    /**
-     * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
-     * object element, e.g. "[Lcom.package.MyClass;"
-     * If the type doesn't need to be renamed, returns the internal name of the input type.
-     */
-    String renameType(Type type) {
-        if (type == null) {
-            return null;
-        }
-
-        if (type.getSort() == Type.OBJECT) {
-            String in = type.getInternalName();
-            return "L" + renameInternalType(in) + ";";
-        } else if (type.getSort() == Type.ARRAY) {
-            StringBuilder sb = new StringBuilder();
-            for (int n = type.getDimensions(); n > 0; n--) {
-                sb.append('[');
-            }
-            sb.append(renameType(type.getElementType()));
-            return sb.toString();
-        }
-        return type.getDescriptor();
-    }
-
-    /**
-     * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
-     * object element, e.g. "[Lcom.package.MyClass;".
-     * This is like renameType() except that it returns a Type object.
-     * If the type doesn't need to be renamed, returns the input type object.
-     */
-    Type renameTypeAsType(Type type) {
-        if (type == null) {
-            return null;
-        }
-
-        if (type.getSort() == Type.OBJECT) {
-            String in = type.getInternalName();
-            String newIn = renameInternalType(in);
-            if (newIn != in) {
-                return Type.getType("L" + newIn + ";");
-            }
-        } else if (type.getSort() == Type.ARRAY) {
-            StringBuilder sb = new StringBuilder();
-            for (int n = type.getDimensions(); n > 0; n--) {
-                sb.append('[');
-            }
-            sb.append(renameType(type.getElementType()));
-            return Type.getType(sb.toString());
-        }
-        return type;
-    }
-
     /**
      * Renames an internal type name, e.g. "com.package.MyClass".
      * If the type doesn't need to be renamed, returns the input string as-is.
@@ -138,7 +63,8 @@
      * The internal type of some of the MethodVisitor turns out to be a type
        descriptor sometimes so descriptors are renamed too.
      */
-    String renameInternalType(String type) {
+    @Override
+    protected String renameInternalType(String type) {
         if (type == null) {
             return null;
         }
@@ -155,309 +81,7 @@
         if (pos == mOldBase.length() && type.startsWith(mOldBase)) {
             return mNewBase + type.substring(pos);
         }
-
-        // The internal type of some of the MethodVisitor turns out to be a type
-        // descriptor sometimes. This is the case with visitTypeInsn(type) and
-        // visitMethodInsn(owner). We try to detect it and adjust it here.
-        if (type.indexOf(';') > 0) {
-            type = renameTypeDesc(type);
-        }
-
         return type;
     }
 
-    /**
-     * Renames a method descriptor, i.e. applies renameType to all arguments and to the
-     * return value.
-     */
-    String renameMethodDesc(String desc) {
-        if (desc == null) {
-            return null;
-        }
-
-        Type[] args = Type.getArgumentTypes(desc);
-
-        StringBuilder sb = new StringBuilder("(");
-        for (Type arg : args) {
-            String name = renameType(arg);
-            sb.append(name);
-        }
-        sb.append(')');
-
-        Type ret = Type.getReturnType(desc);
-        String name = renameType(ret);
-        sb.append(name);
-
-        return sb.toString();
-    }
-
-
-    /**
-     * Renames the ClassSignature handled by ClassVisitor.visit
-     * or the MethodTypeSignature handled by ClassVisitor.visitMethod.
-     */
-    String renameTypeSignature(String sig) {
-        if (sig == null) {
-            return null;
-        }
-        SignatureReader reader = new SignatureReader(sig);
-        SignatureWriter writer = new SignatureWriter();
-        reader.accept(new RenameSignatureAdapter(writer));
-        sig = writer.toString();
-        return sig;
-    }
-
-
-    /**
-     * Renames the FieldTypeSignature handled by ClassVisitor.visitField
-     * or MethodVisitor.visitLocalVariable.
-     */
-    String renameFieldSignature(String sig) {
-        if (sig == null) {
-            return null;
-        }
-        SignatureReader reader = new SignatureReader(sig);
-        SignatureWriter writer = new SignatureWriter();
-        reader.acceptType(new RenameSignatureAdapter(writer));
-        sig = writer.toString();
-        return sig;
-    }
-
-
-    //----------------------------------
-    // Methods from the ClassAdapter
-
-    @Override
-    public void visit(int version, int access, String name, String signature,
-            String superName, String[] interfaces) {
-        name = renameInternalType(name);
-        superName = renameInternalType(superName);
-        signature = renameTypeSignature(signature);
-
-        super.visit(version, access, name, signature, superName, interfaces);
-    }
-
-    @Override
-    public void visitInnerClass(String name, String outerName, String innerName, int access) {
-        assert outerName.equals(mOldName);
-        outerName = renameInternalType(outerName);
-        name = outerName + "$" + innerName;
-        super.visitInnerClass(name, outerName, innerName, access);
-    }
-
-    @Override
-    public MethodVisitor visitMethod(int access, String name, String desc,
-            String signature, String[] exceptions) {
-        desc = renameMethodDesc(desc);
-        signature = renameTypeSignature(signature);
-        MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
-        return new RenameMethodAdapter(mw);
-    }
-
-    @Override
-    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-        desc = renameTypeDesc(desc);
-        return super.visitAnnotation(desc, visible);
-    }
-
-    @Override
-    public FieldVisitor visitField(int access, String name, String desc,
-            String signature, Object value) {
-        desc = renameTypeDesc(desc);
-        signature = renameFieldSignature(signature);
-        return super.visitField(access, name, desc, signature, value);
-    }
-
-
-    //----------------------------------
-
-    /**
-     * A method visitor that renames all references from an old class name to a new class name.
-     */
-    public class RenameMethodAdapter extends MethodVisitor {
-
-        /**
-         * Creates a method visitor that renames all references from a given old name to a given new
-         * name. The method visitor will also rename all inner classes.
-         * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass).
-         */
-        public RenameMethodAdapter(MethodVisitor mv) {
-            super(Opcodes.ASM4, mv);
-        }
-
-        @Override
-        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-            desc = renameTypeDesc(desc);
-
-            return super.visitAnnotation(desc, visible);
-        }
-
-        @Override
-        public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
-            desc = renameTypeDesc(desc);
-
-            return super.visitParameterAnnotation(parameter, desc, visible);
-        }
-
-        @Override
-        public void visitTypeInsn(int opcode, String type) {
-            type = renameInternalType(type);
-
-            super.visitTypeInsn(opcode, type);
-        }
-
-        @Override
-        public void visitFieldInsn(int opcode, String owner, String name, String desc) {
-            owner = renameInternalType(owner);
-            desc = renameTypeDesc(desc);
-
-            super.visitFieldInsn(opcode, owner, name, desc);
-        }
-
-        @Override
-        public void visitMethodInsn(int opcode, String owner, String name, String desc) {
-            owner = renameInternalType(owner);
-            desc = renameMethodDesc(desc);
-
-            super.visitMethodInsn(opcode, owner, name, desc);
-        }
-
-        @Override
-        public void visitLdcInsn(Object cst) {
-            // If cst is a Type, this means the code is trying to pull the .class constant
-            // for this class, so it needs to be renamed too.
-            if (cst instanceof Type) {
-                cst = renameTypeAsType((Type) cst);
-            }
-            super.visitLdcInsn(cst);
-        }
-
-        @Override
-        public void visitMultiANewArrayInsn(String desc, int dims) {
-            desc = renameTypeDesc(desc);
-
-            super.visitMultiANewArrayInsn(desc, dims);
-        }
-
-        @Override
-        public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
-            type = renameInternalType(type);
-
-            super.visitTryCatchBlock(start, end, handler, type);
-        }
-
-        @Override
-        public void visitLocalVariable(String name, String desc, String signature,
-                Label start, Label end, int index) {
-            desc = renameTypeDesc(desc);
-            signature = renameFieldSignature(signature);
-
-            super.visitLocalVariable(name, desc, signature, start, end, index);
-        }
-
-    }
-
-    //----------------------------------
-
-    public class RenameSignatureAdapter extends SignatureVisitor {
-
-        private final SignatureVisitor mSv;
-
-        public RenameSignatureAdapter(SignatureVisitor sv) {
-            super(Opcodes.ASM4);
-            mSv = sv;
-        }
-
-        @Override
-        public void visitClassType(String name) {
-            name = renameInternalType(name);
-            mSv.visitClassType(name);
-        }
-
-        @Override
-        public void visitInnerClassType(String name) {
-            name = renameInternalType(name);
-            mSv.visitInnerClassType(name);
-        }
-
-        @Override
-        public SignatureVisitor visitArrayType() {
-            SignatureVisitor sv = mSv.visitArrayType();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public void visitBaseType(char descriptor) {
-            mSv.visitBaseType(descriptor);
-        }
-
-        @Override
-        public SignatureVisitor visitClassBound() {
-            SignatureVisitor sv = mSv.visitClassBound();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public void visitEnd() {
-            mSv.visitEnd();
-        }
-
-        @Override
-        public SignatureVisitor visitExceptionType() {
-            SignatureVisitor sv = mSv.visitExceptionType();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public void visitFormalTypeParameter(String name) {
-            mSv.visitFormalTypeParameter(name);
-        }
-
-        @Override
-        public SignatureVisitor visitInterface() {
-            SignatureVisitor sv = mSv.visitInterface();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public SignatureVisitor visitInterfaceBound() {
-            SignatureVisitor sv = mSv.visitInterfaceBound();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public SignatureVisitor visitParameterType() {
-            SignatureVisitor sv = mSv.visitParameterType();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public SignatureVisitor visitReturnType() {
-            SignatureVisitor sv = mSv.visitReturnType();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public SignatureVisitor visitSuperclass() {
-            SignatureVisitor sv = mSv.visitSuperclass();
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public void visitTypeArgument() {
-            mSv.visitTypeArgument();
-        }
-
-        @Override
-        public SignatureVisitor visitTypeArgument(char wildcard) {
-            SignatureVisitor sv = mSv.visitTypeArgument(wildcard);
-            return new RenameSignatureAdapter(sv);
-        }
-
-        @Override
-        public void visitTypeVariable(String name) {
-            mSv.visitTypeVariable(name);
-        }
-
-    }
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/java/AutoCloseable.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/AutoCloseable.java
new file mode 100644
index 0000000..ed2c128
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/AutoCloseable.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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.java;
+
+/**
+ * Defines the same interface as the java.lang.AutoCloseable which was added in
+ * Java 7. This hack makes it possible to run the Android code which uses Java 7
+ * features (API 18 and beyond) to run on Java 6.
+ * <p/>
+ * Extracted from API level 18, file:
+ * platform/libcore/luni/src/main/java/java/lang/AutoCloseable.java
+ */
+public interface AutoCloseable {
+    /**
+     * Closes the object and release any system resources it holds.
+     */
+    void close() throws Exception; }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/java/Charsets.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/Charsets.java
new file mode 100644
index 0000000..f73b06b
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/Charsets.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 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.java;
+
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * Defines the same class as the java.nio.charset.Charsets which was added in
+ * Dalvik VM. This hack, provides a replacement for that class which can't be
+ * loaded in the standard JVM since it's in the java package and standard JVM
+ * doesn't have it. An implementation of the native methods in the original
+ * class has been added.
+ * <p/>
+ * Extracted from API level 18, file:
+ * platform/libcore/luni/src/main/java/java/nio/charset/Charsets
+ */
+public final class Charsets {
+    /**
+     * A cheap and type-safe constant for the ISO-8859-1 Charset.
+     */
+    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+    /**
+     * A cheap and type-safe constant for the US-ASCII Charset.
+     */
+    public static final Charset US_ASCII = Charset.forName("US-ASCII");
+
+    /**
+     * A cheap and type-safe constant for the UTF-8 Charset.
+     */
+    public static final Charset UTF_8 = Charset.forName("UTF-8");
+
+    /**
+     * Returns a new byte array containing the bytes corresponding to the given characters,
+     * encoded in US-ASCII. Unrepresentable characters are replaced by (byte) '?'.
+     */
+    public static byte[] toAsciiBytes(char[] chars, int offset, int length) {
+        CharBuffer cb = CharBuffer.allocate(length);
+        cb.put(chars, offset, length);
+        return US_ASCII.encode(cb).array();
+    }
+
+    /**
+     * Returns a new byte array containing the bytes corresponding to the given characters,
+     * encoded in ISO-8859-1. Unrepresentable characters are replaced by (byte) '?'.
+     */
+    public static byte[] toIsoLatin1Bytes(char[] chars, int offset, int length) {
+        CharBuffer cb = CharBuffer.allocate(length);
+        cb.put(chars, offset, length);
+        return ISO_8859_1.encode(cb).array();
+    }
+
+    /**
+     * Returns a new byte array containing the bytes corresponding to the given characters,
+     * encoded in UTF-8. All characters are representable in UTF-8.
+     */
+    public static byte[] toUtf8Bytes(char[] chars, int offset, int length) {
+        CharBuffer cb = CharBuffer.allocate(length);
+        cb.put(chars, offset, length);
+        return UTF_8.encode(cb).array();
+    }
+
+    /**
+     * Returns a new byte array containing the bytes corresponding to the given characters,
+     * encoded in UTF-16BE. All characters are representable in UTF-16BE.
+     */
+    public static byte[] toBigEndianUtf16Bytes(char[] chars, int offset, int length) {
+        byte[] result = new byte[length * 2];
+        int end = offset + length;
+        int resultIndex = 0;
+        for (int i = offset; i < end; ++i) {
+            char ch = chars[i];
+            result[resultIndex++] = (byte) (ch >> 8);
+            result[resultIndex++] = (byte) ch;
+        }
+        return result;
+    }
+
+    /**
+     * Decodes the given US-ASCII bytes into the given char[]. Equivalent to but faster than:
+     *
+     * for (int i = 0; i < count; ++i) {
+     *     char ch = (char) (data[start++] & 0xff);
+     *     value[i] = (ch <= 0x7f) ? ch : REPLACEMENT_CHAR;
+     * }
+     */
+    public static void asciiBytesToChars(byte[] bytes, int offset, int length, char[] chars) {
+        if (bytes == null || chars == null) {
+            return;
+        }
+        final char REPLACEMENT_CHAR = (char)0xffd;
+        int start = offset;
+        for (int i = 0; i < length; ++i) {
+            char ch = (char) (bytes[start++] & 0xff);
+            chars[i] = (ch <= 0x7f) ? ch : REPLACEMENT_CHAR;
+        }
+    }
+
+    /**
+     * Decodes the given ISO-8859-1 bytes into the given char[]. Equivalent to but faster than:
+     *
+     * for (int i = 0; i < count; ++i) {
+     *     value[i] = (char) (data[start++] & 0xff);
+     * }
+     */
+    public static void isoLatin1BytesToChars(byte[] bytes, int offset, int length, char[] chars) {
+        if (bytes == null || chars == null) {
+            return;
+        }
+        int start = offset;
+        for (int i = 0; i < length; ++i) {
+            chars[i] = (char) (bytes[start++] & 0xff);
+        }
+    }
+
+    private Charsets() {
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/java/IntegralToString.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/IntegralToString.java
new file mode 100644
index 0000000..e6dd00a
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/IntegralToString.java
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2013 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.java;
+
+/**
+ * Defines the same class as the java.lang.IntegralToString which was added in
+ * Dalvik VM. This hack, provides a replacement for that class which can't be
+ * loaded in the standard JVM since it's in the java package and standard JVM
+ * doesn't have it. Since it's no longer in java.lang, access to package
+ * private methods and classes has been replaced by the closes matching public
+ * implementation.
+ * <p/>
+ * Extracted from API level 18, file:
+ * platform/libcore/luni/src/main/java/java/lang/IntegralToString.java
+ */
+public final class IntegralToString {
+    /**
+     * When appending to an AbstractStringBuilder, this thread-local char[] lets us avoid
+     * allocation of a temporary array. (We can't write straight into the AbstractStringBuilder
+     * because it's almost as expensive to work out the exact length of the result as it is to
+     * do the formatting. We could try being conservative and "delete"-ing the unused space
+     * afterwards, but then we'd need to duplicate convertInt and convertLong rather than share
+     * the code.)
+     */
+    private static final ThreadLocal<char[]> BUFFER = new ThreadLocal<char[]>() {
+        @Override protected char[] initialValue() {
+            return new char[20]; // Maximum length of a base-10 long.
+        }
+    };
+
+    /**
+     * These tables are used to special-case toString computation for
+     * small values.  This serves three purposes: it reduces memory usage;
+     * it increases performance for small values; and it decreases the
+     * number of comparisons required to do the length computation.
+     * Elements of this table are lazily initialized on first use.
+     * No locking is necessary, i.e., we use the non-volatile, racy
+     * single-check idiom.
+     */
+    private static final String[] SMALL_NONNEGATIVE_VALUES = new String[100];
+    private static final String[] SMALL_NEGATIVE_VALUES = new String[100];
+
+    /** TENS[i] contains the tens digit of the number i, 0 <= i <= 99. */
+    private static final char[] TENS = {
+        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
+        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
+        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
+        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
+        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
+        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
+        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
+        '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
+        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
+        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9'
+    };
+
+    /** Ones [i] contains the tens digit of the number i, 0 <= i <= 99. */
+    private static final char[] ONES = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+    };
+
+    /**
+     * Table for MOD / DIV 10 computation described in Section 10-21
+     * of Hank Warren's "Hacker's Delight" online addendum.
+     * http://www.hackersdelight.org/divcMore.pdf
+     */
+    private static final char[] MOD_10_TABLE = {
+        0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 0
+    };
+
+    /**
+     * The digits for every supported radix.
+     */
+    private static final char[] DIGITS = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
+        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
+        'u', 'v', 'w', 'x', 'y', 'z'
+    };
+
+    private static final char[] UPPER_CASE_DIGITS = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+        'U', 'V', 'W', 'X', 'Y', 'Z'
+    };
+
+    private IntegralToString() {
+    }
+
+    /**
+     * Equivalent to Integer.toString(i, radix).
+     */
+    public static String intToString(int i, int radix) {
+        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+            radix = 10;
+        }
+        if (radix == 10) {
+            return intToString(i);
+        }
+
+        /*
+         * If i is positive, negate it. This is the opposite of what one might
+         * expect. It is necessary because the range of the negative values is
+         * strictly larger than that of the positive values: there is no
+         * positive value corresponding to Integer.MIN_VALUE.
+         */
+        boolean negative = false;
+        if (i < 0) {
+            negative = true;
+        } else {
+            i = -i;
+        }
+
+        int bufLen = radix < 8 ? 33 : 12;  // Max chars in result (conservative)
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            int q = i / radix;
+            buf[--cursor] = DIGITS[radix * q - i];
+            i = q;
+        } while (i != 0);
+
+        if (negative) {
+            buf[--cursor] = '-';
+        }
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    /**
+     * Equivalent to Integer.toString(i).
+     */
+    public static String intToString(int i) {
+        return convertInt(null, i);
+    }
+
+    /**
+     * Equivalent to sb.append(Integer.toString(i)).
+     */
+    public static void appendInt(StringBuilder sb, int i) {
+        convertInt(sb, i);
+    }
+
+    /**
+     * Returns the string representation of i and leaves sb alone if sb is null.
+     * Returns null and appends the string representation of i to sb if sb is non-null.
+     */
+    private static String convertInt(StringBuilder sb, int i) {
+        boolean negative = false;
+        String quickResult = null;
+        if (i < 0) {
+            negative = true;
+            i = -i;
+            if (i < 100) {
+                if (i < 0) {
+                    // If -n is still negative, n is Integer.MIN_VALUE
+                    quickResult = "-2147483648";
+                } else {
+                    quickResult = SMALL_NEGATIVE_VALUES[i];
+                    if (quickResult == null) {
+                        SMALL_NEGATIVE_VALUES[i] = quickResult =
+                                i < 10 ? stringOf('-', ONES[i]) : stringOf('-', TENS[i], ONES[i]);
+                    }
+                }
+            }
+        } else {
+            if (i < 100) {
+                quickResult = SMALL_NONNEGATIVE_VALUES[i];
+                if (quickResult == null) {
+                    SMALL_NONNEGATIVE_VALUES[i] = quickResult =
+                            i < 10 ? stringOf(ONES[i]) : stringOf(TENS[i], ONES[i]);
+                }
+            }
+        }
+        if (quickResult != null) {
+            if (sb != null) {
+                sb.append(quickResult);
+                return null;
+            }
+            return quickResult;
+        }
+
+        int bufLen = 11; // Max number of chars in result
+        char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen];
+        int cursor = bufLen;
+
+        // Calculate digits two-at-a-time till remaining digits fit in 16 bits
+        while (i >= (1 << 16)) {
+            // Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8
+            int q = (int) ((0x51EB851FL * i) >>> 37);
+            int r = i - 100*q;
+            buf[--cursor] = ONES[r];
+            buf[--cursor] = TENS[r];
+            i = q;
+        }
+
+        // Calculate remaining digits one-at-a-time for performance
+        while (i != 0) {
+            // Compute q = n/10 and r = n % 10 as per "Hacker's Delight" 10-8
+            int q = (0xCCCD * i) >>> 19;
+            int r = i - 10*q;
+            buf[--cursor] = DIGITS[r];
+            i = q;
+        }
+
+        if (negative) {
+            buf[--cursor] = '-';
+        }
+
+        if (sb != null) {
+            sb.append(buf, cursor, bufLen - cursor);
+            return null;
+        } else {
+            return new String(buf, cursor, bufLen - cursor);
+        }
+    }
+
+    /**
+     * Equivalent to Long.toString(v, radix).
+     */
+    public static String longToString(long v, int radix) {
+        int i = (int) v;
+        if (i == v) {
+            return intToString(i, radix);
+        }
+
+        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
+            radix = 10;
+        }
+        if (radix == 10) {
+            return longToString(v);
+        }
+
+        /*
+         * If v is positive, negate it. This is the opposite of what one might
+         * expect. It is necessary because the range of the negative values is
+         * strictly larger than that of the positive values: there is no
+         * positive value corresponding to Integer.MIN_VALUE.
+         */
+        boolean negative = false;
+        if (v < 0) {
+            negative = true;
+        } else {
+            v = -v;
+        }
+
+        int bufLen = radix < 8 ? 65 : 23;  // Max chars in result (conservative)
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            long q = v / radix;
+            buf[--cursor] = DIGITS[(int) (radix * q - v)];
+            v = q;
+        } while (v != 0);
+
+        if (negative) {
+            buf[--cursor] = '-';
+        }
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    /**
+     * Equivalent to Long.toString(l).
+     */
+    public static String longToString(long l) {
+        return convertLong(null, l);
+    }
+
+    /**
+     * Equivalent to sb.append(Long.toString(l)).
+     */
+    public static void appendLong(StringBuilder sb, long l) {
+        convertLong(sb, l);
+    }
+
+    /**
+     * Returns the string representation of n and leaves sb alone if sb is null.
+     * Returns null and appends the string representation of n to sb if sb is non-null.
+     */
+    private static String convertLong(StringBuilder sb, long n) {
+        int i = (int) n;
+        if (i == n) {
+            return convertInt(sb, i);
+        }
+
+        boolean negative = (n < 0);
+        if (negative) {
+            n = -n;
+            if (n < 0) {
+                // If -n is still negative, n is Long.MIN_VALUE
+                String quickResult = "-9223372036854775808";
+                if (sb != null) {
+                    sb.append(quickResult);
+                    return null;
+                }
+                return quickResult;
+            }
+        }
+
+        int bufLen = 20; // Maximum number of chars in result
+        char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen];
+
+        int low = (int) (n % 1000000000); // Extract low-order 9 digits
+        int cursor = intIntoCharArray(buf, bufLen, low);
+
+        // Zero-pad Low order part to 9 digits
+        while (cursor != (bufLen - 9)) {
+            buf[--cursor] = '0';
+        }
+
+        /*
+         * The remaining digits are (n - low) / 1,000,000,000.  This
+         * "exact division" is done as per the online addendum to Hank Warren's
+         * "Hacker's Delight" 10-20, http://www.hackersdelight.org/divcMore.pdf
+         */
+        n = ((n - low) >>> 9) * 0x8E47CE423A2E9C6DL;
+
+        /*
+         * If the remaining digits fit in an int, emit them using a
+         * single call to intIntoCharArray. Otherwise, strip off the
+         * low-order digit, put it in buf, and then call intIntoCharArray
+         * on the remaining digits (which now fit in an int).
+         */
+        if ((n & (-1L << 32)) == 0) {
+            cursor = intIntoCharArray(buf, cursor, (int) n);
+        } else {
+            /*
+             * Set midDigit to n % 10
+             */
+            int lo32 = (int) n;
+            int hi32 = (int) (n >>> 32);
+
+            // midDigit = ((unsigned) low32) % 10, per "Hacker's Delight" 10-21
+            int midDigit = MOD_10_TABLE[(0x19999999 * lo32 + (lo32 >>> 1) + (lo32 >>> 3)) >>> 28];
+
+            // Adjust midDigit for hi32. (assert hi32 == 1 || hi32 == 2)
+            midDigit -= hi32 << 2;  // 1L << 32 == -4 MOD 10
+            if (midDigit < 0) {
+                midDigit += 10;
+            }
+            buf[--cursor] = DIGITS[midDigit];
+
+            // Exact division as per Warren 10-20
+            int rest = ((int) ((n - midDigit) >>> 1)) * 0xCCCCCCCD;
+            cursor = intIntoCharArray(buf, cursor, rest);
+        }
+
+        if (negative) {
+            buf[--cursor] = '-';
+        }
+        if (sb != null) {
+            sb.append(buf, cursor, bufLen - cursor);
+            return null;
+        } else {
+            return new String(buf, cursor, bufLen - cursor);
+        }
+    }
+
+    /**
+     * Inserts the unsigned decimal integer represented by n into the specified
+     * character array starting at position cursor.  Returns the index after
+     * the last character inserted (i.e., the value to pass in as cursor the
+     * next time this method is called). Note that n is interpreted as a large
+     * positive integer (not a negative integer) if its sign bit is set.
+     */
+    private static int intIntoCharArray(char[] buf, int cursor, int n) {
+        // Calculate digits two-at-a-time till remaining digits fit in 16 bits
+        while ((n & 0xffff0000) != 0) {
+            /*
+             * Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8.
+             * This computation is slightly different from the corresponding
+             * computation in intToString: the shifts before and after
+             * multiply can't be combined, as that would yield the wrong result
+             * if n's sign bit were set.
+             */
+            int q = (int) ((0x51EB851FL * (n >>> 2)) >>> 35);
+            int r = n - 100*q;
+            buf[--cursor] = ONES[r];
+            buf[--cursor] = TENS[r];
+            n = q;
+        }
+
+        // Calculate remaining digits one-at-a-time for performance
+        while (n != 0) {
+            // Compute q = n / 10 and r = n % 10 as per "Hacker's Delight" 10-8
+            int q = (0xCCCD * n) >>> 19;
+            int r = n - 10*q;
+            buf[--cursor] = DIGITS[r];
+            n = q;
+        }
+        return cursor;
+    }
+
+    public static String intToBinaryString(int i) {
+        int bufLen = 32;  // Max number of binary digits in an int
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            buf[--cursor] = DIGITS[i & 1];
+        }  while ((i >>>= 1) != 0);
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    public static String longToBinaryString(long v) {
+        int i = (int) v;
+        if (v >= 0 && i == v) {
+            return intToBinaryString(i);
+        }
+
+        int bufLen = 64;  // Max number of binary digits in a long
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            buf[--cursor] = DIGITS[((int) v) & 1];
+        }  while ((v >>>= 1) != 0);
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
+        sb.append(digits[(b >> 4) & 0xf]);
+        sb.append(digits[b & 0xf]);
+        return sb;
+    }
+
+    public static String byteToHexString(byte b, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
+        char[] buf = new char[2]; // We always want two digits.
+        buf[0] = digits[(b >> 4) & 0xf];
+        buf[1] = digits[b & 0xf];
+        return new String(buf, 0, 2);
+    }
+
+    public static String bytesToHexString(byte[] bytes, boolean upperCase) {
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
+        char[] buf = new char[bytes.length * 2];
+        int c = 0;
+        for (byte b : bytes) {
+            buf[c++] = digits[(b >> 4) & 0xf];
+            buf[c++] = digits[b & 0xf];
+        }
+        return new String(buf);
+    }
+
+    public static String intToHexString(int i, boolean upperCase, int minWidth) {
+        int bufLen = 8;  // Max number of hex digits in an int
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
+        do {
+            buf[--cursor] = digits[i & 0xf];
+        } while ((i >>>= 4) != 0 || (bufLen - cursor < minWidth));
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    public static String longToHexString(long v) {
+        int i = (int) v;
+        if (v >= 0 && i == v) {
+            return intToHexString(i, false, 0);
+        }
+
+        int bufLen = 16;  // Max number of hex digits in a long
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            buf[--cursor] = DIGITS[((int) v) & 0xF];
+        } while ((v >>>= 4) != 0);
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    public static String intToOctalString(int i) {
+        int bufLen = 11;  // Max number of octal digits in an int
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            buf[--cursor] = DIGITS[i & 7];
+        } while ((i >>>= 3) != 0);
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    public static String longToOctalString(long v) {
+        int i = (int) v;
+        if (v >= 0 && i == v) {
+            return intToOctalString(i);
+        }
+        int bufLen = 22;  // Max number of octal digits in a long
+        char[] buf = new char[bufLen];
+        int cursor = bufLen;
+
+        do {
+            buf[--cursor] = DIGITS[((int) v) & 7];
+        } while ((v >>>= 3) != 0);
+
+        return new String(buf, cursor, bufLen - cursor);
+    }
+
+    private static String stringOf(char... args) {
+        return new String(args, 0, args.length);
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/java/ModifiedUtf8.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/ModifiedUtf8.java
new file mode 100644
index 0000000..77c4f3a
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/ModifiedUtf8.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2013 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.java;
+
+import java.io.UTFDataFormatException;
+import java.nio.ByteOrder;
+
+/**
+ * Defines the same class as the java.nio.charset.ModifiedUtf8 which was added in
+ * Dalvik VM. This hack, provides a replacement for that class which can't be
+ * loaded in the standard JVM since it's in the java package and standard JVM
+ * doesn't have it. An implementation of the native methods in the original
+ * class has been added.
+ * <p/>
+ * Extracted from API level 17, file:
+ * platform/libcore/luni/src/main/java/java/nio/charset/ModifiedUtf8
+ */
+public class ModifiedUtf8 {
+    /**
+     * Decodes a byte array containing <i>modified UTF-8</i> bytes into a string.
+     *
+     * <p>Note that although this method decodes the (supposedly impossible) zero byte to U+0000,
+     * that's what the RI does too.
+     */
+    public static String decode(byte[] in, char[] out, int offset, int utfSize) throws UTFDataFormatException {
+        int count = 0, s = 0, a;
+        while (count < utfSize) {
+            if ((out[s] = (char) in[offset + count++]) < '\u0080') {
+                s++;
+            } else if (((a = out[s]) & 0xe0) == 0xc0) {
+                if (count >= utfSize) {
+                    throw new UTFDataFormatException("bad second byte at " + count);
+                }
+                int b = in[offset + count++];
+                if ((b & 0xC0) != 0x80) {
+                    throw new UTFDataFormatException("bad second byte at " + (count - 1));
+                }
+                out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+            } else if ((a & 0xf0) == 0xe0) {
+                if (count + 1 >= utfSize) {
+                    throw new UTFDataFormatException("bad third byte at " + (count + 1));
+                }
+                int b = in[offset + count++];
+                int c = in[offset + count++];
+                if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
+                    throw new UTFDataFormatException("bad second or third byte at " + (count - 2));
+                }
+                out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+            } else {
+                throw new UTFDataFormatException("bad byte at " + (count - 1));
+            }
+        }
+        return new String(out, 0, s);
+    }
+
+    /**
+     * Returns the number of bytes the modified UTF-8 representation of 's' would take. Note
+     * that this is just the space for the bytes representing the characters, not the length
+     * which precedes those bytes, because different callers represent the length differently,
+     * as two, four, or even eight bytes. If {@code shortLength} is true, we'll throw an
+     * exception if the string is too long for its length to be represented by a short.
+     */
+    public static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {
+        long result = 0;
+        final int length = s.length();
+        for (int i = 0; i < length; ++i) {
+            char ch = s.charAt(i);
+            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+                ++result;
+            } else if (ch <= 2047) {
+                result += 2;
+            } else {
+                result += 3;
+            }
+            if (shortLength && result > 65535) {
+                throw new UTFDataFormatException("String more than 65535 UTF bytes long");
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Encodes the <i>modified UTF-8</i> bytes corresponding to string {@code s} into the
+     * byte array {@code dst}, starting at the given {@code offset}.
+     */
+    public static void encode(byte[] dst, int offset, String s) {
+        final int length = s.length();
+        for (int i = 0; i < length; i++) {
+            char ch = s.charAt(i);
+            if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+                dst[offset++] = (byte) ch;
+            } else if (ch <= 2047) {
+                dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6)));
+                dst[offset++] = (byte) (0x80 | (0x3f & ch));
+            } else {
+                dst[offset++] = (byte) (0xe0 | (0x0f & (ch >> 12)));
+                dst[offset++] = (byte) (0x80 | (0x3f & (ch >> 6)));
+                dst[offset++] = (byte) (0x80 | (0x3f & ch));
+            }
+        }
+    }
+
+    /**
+     * Returns an array containing the <i>modified UTF-8</i> form of {@code s}, using a
+     * big-endian 16-bit length. Throws UTFDataFormatException if {@code s} is too long
+     * for a two-byte length.
+     */
+    public static byte[] encode(String s) throws UTFDataFormatException {
+        int utfCount = (int) ModifiedUtf8.countBytes(s, true);
+        // Original statement used libcore.io.SizeOf.SHORT. Since we don't have that, we
+        // substitute it's value directly, which is 2.
+        byte[] result = new byte[2 + utfCount];
+        // The original statement had libcore.io.Memory.pokeShort(). We provide it's implementation
+        // below in a private method.
+        pokeShort(result, 0, (short) utfCount, ByteOrder.BIG_ENDIAN);
+        ModifiedUtf8.encode(result, 2, s);
+        return result;
+    }
+
+    // Copied from libcore.io.Memory.pokeShort().
+    private static void pokeShort(byte[] dst, int offset, short value, ByteOrder order) {
+        if (order == ByteOrder.BIG_ENDIAN) {
+            dst[offset++] = (byte) ((value >> 8) & 0xff);
+            dst[offset  ] = (byte) ((value >> 0) & 0xff);
+        } else {
+            dst[offset++] = (byte) ((value >> 0) & 0xff);
+            dst[offset  ] = (byte) ((value >> 8) & 0xff);
+        }
+    }
+
+    private ModifiedUtf8() {
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/java/UnsafeByteSequence.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/UnsafeByteSequence.java
new file mode 100644
index 0000000..0e09080
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/java/UnsafeByteSequence.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 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.java;
+
+import java.nio.charset.Charset;
+
+/**
+ * Defines the same class as the java.lang.UnsafeByteSequence which was added in
+ * Dalvik VM. This hack, provides a replacement for that class which can't be
+ * loaded in the standard JVM since it's in the java package and standard JVM
+ * doesn't have it.
+ * <p/>
+ * Extracted from API level 18, file:
+ * platform/libcore/luni/src/main/java/java/lang/UnsafeByteSequence.java
+ */
+public class UnsafeByteSequence {
+    private byte[] bytes;
+    private int count;
+
+    public UnsafeByteSequence(int initialCapacity) {
+        this.bytes = new byte[initialCapacity];
+    }
+
+    public int size() {
+        return count;
+    }
+
+    /**
+     * Moves the write pointer back to the beginning of the sequence,
+     * but without resizing or reallocating the buffer.
+     */
+    public void rewind() {
+        count = 0;
+    }
+
+    public void write(byte[] buffer, int offset, int length) {
+        if (count + length >= bytes.length) {
+            byte[] newBytes = new byte[(count + length) * 2];
+            System.arraycopy(bytes, 0, newBytes, 0, count);
+            bytes = newBytes;
+        }
+        System.arraycopy(buffer, offset, bytes, count, length);
+        count += length;
+    }
+
+    public void write(int b) {
+        if (count == bytes.length) {
+            byte[] newBytes = new byte[count * 2];
+            System.arraycopy(bytes, 0, newBytes, 0, count);
+            bytes = newBytes;
+        }
+        bytes[count++] = (byte) b;
+    }
+
+    public byte[] toByteArray() {
+        if (count == bytes.length) {
+            return bytes;
+        }
+        byte[] result = new byte[count];
+        System.arraycopy(bytes, 0, result, 0, count);
+        return result;
+    }
+
+    public String toString(Charset cs) {
+        return new String(bytes, 0, count, cs);
+    }
+}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
index d6dba6a..005fc9d 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
@@ -31,7 +31,9 @@
 import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 /**
@@ -51,8 +53,10 @@
         mOsJarPath = new ArrayList<String>();
         mOsJarPath.add(url.getFile());
 
+        Set<String> excludeClasses = new HashSet<String>(1);
+        excludeClasses.add("java.lang.JavaClass");
         mAa = new AsmAnalyzer(mLog, mOsJarPath, null /* gen */,
-                null /* deriveFrom */, null /* includeGlobs */ );
+                null /* deriveFrom */, null /* includeGlobs */, excludeClasses);
     }
 
     @After
@@ -64,6 +68,7 @@
         Map<String, ClassReader> map = mAa.parseZip(mOsJarPath);
 
         assertArrayEquals(new String[] {
+                "java.lang.JavaClass",
                 "mock_android.dummy.InnerTest",
                 "mock_android.dummy.InnerTest$DerivingClass",
                 "mock_android.dummy.InnerTest$MyGenerics1",
@@ -221,7 +226,11 @@
         for (ClassReader cr2 : in_deps.values()) {
             cr2.accept(visitor, 0 /* flags */);
         }
+        keep.putAll(new_keep);
 
         assertArrayEquals(new String[] { }, out_deps.keySet().toArray());
+        assertArrayEquals(new String[] {
+                "mock_android.widget.TableLayout",
+        }, keep.keySet().toArray());
     }
 }
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index 7b76a5b..8a27173 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -19,16 +19,29 @@
 
 
 import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
 
 import java.io.File;
 import java.io.IOException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 /**
  * Unit tests for some methods of {@link AsmGenerator}.
@@ -40,6 +53,9 @@
     private String mOsDestJar;
     private File mTempFile;
 
+    // ASM internal name for the the class in java package that should be refactored.
+    private static final String JAVA_CLASS_NAME = "java/lang/JavaClass";
+
     @Before
     public void setUp() throws Exception {
         mLog = new MockLog();
@@ -48,7 +64,7 @@
         mOsJarPath = new ArrayList<String>();
         mOsJarPath.add(url.getFile());
 
-        mTempFile = File.createTempFile("mock", "jar");
+        mTempFile = File.createTempFile("mock", ".jar");
         mOsDestJar = mTempFile.getAbsolutePath();
         mTempFile.deleteOnExit();
     }
@@ -97,6 +113,11 @@
             }
 
             @Override
+            public String[] getJavaPkgClasses() {
+              return new String[0];
+            }
+
+            @Override
             public String[] getDeleteReturns() {
                  // methods deleted from their return type.
                 return new String[0];
@@ -109,11 +130,201 @@
                 null,                 // derived from
                 new String[] {        // include classes
                     "**"
-                });
+                },
+                new HashSet<String>(0) /* excluded classes */);
         aa.analyze();
         agen.generate();
 
         Set<String> notRenamed = agen.getClassesNotRenamed();
         assertArrayEquals(new String[] { "not/an/actual/ClassName" }, notRenamed.toArray());
+
+    }
+
+    @Test
+    public void testClassRefactoring() throws IOException, LogAbortException {
+        ICreateInfo ci = new ICreateInfo() {
+            @Override
+            public Class<?>[] getInjectedClasses() {
+                // classes to inject in the final JAR
+                return new Class<?>[] {
+                        com.android.tools.layoutlib.create.dataclass.JavaClass.class
+                };
+            }
+
+            @Override
+            public String[] getDelegateMethods() {
+                return new String[0];
+            }
+
+            @Override
+            public String[] getDelegateClassNatives() {
+                return new String[0];
+            }
+
+            @Override
+            public String[] getOverriddenMethods() {
+                // methods to force override
+                return new String[0];
+            }
+
+            @Override
+            public String[] getRenamedClasses() {
+                // classes to rename (so that we can replace them)
+                return new String[0];
+            }
+
+            @Override
+            public String[] getJavaPkgClasses() {
+             // classes to refactor (so that we can replace them)
+                return new String[] {
+                        "java.lang.JavaClass", "com.android.tools.layoutlib.create.dataclass.JavaClass",
+                };
+            }
+
+            @Override
+            public String[] getDeleteReturns() {
+                 // methods deleted from their return type.
+                return new String[0];
+            }
+        };
+
+        AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
+
+        AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
+                null,                 // derived from
+                new String[] {        // include classes
+                    "**"
+                },
+                new HashSet<String>(1));
+        aa.analyze();
+        agen.generate();
+        Map<String, ClassReader> output = parseZip(mOsDestJar);
+        boolean injectedClassFound = false;
+        for (ClassReader cr: output.values()) {
+            TestClassVisitor cv = new TestClassVisitor();
+            cr.accept(cv, 0);
+            injectedClassFound |= cv.mInjectedClassFound;
+        }
+        assertTrue(injectedClassFound);
+    }
+
+    private Map<String,ClassReader> parseZip(String jarPath) throws IOException {
+        TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>();
+
+            ZipFile zip = new ZipFile(jarPath);
+            Enumeration<? extends ZipEntry> entries = zip.entries();
+            ZipEntry entry;
+            while (entries.hasMoreElements()) {
+                entry = entries.nextElement();
+                if (entry.getName().endsWith(".class")) {
+                    ClassReader cr = new ClassReader(zip.getInputStream(entry));
+                    String className = classReaderToClassName(cr);
+                    classes.put(className, cr);
+                }
+            }
+
+        return classes;
+    }
+
+    private String classReaderToClassName(ClassReader classReader) {
+        if (classReader == null) {
+            return null;
+        } else {
+            return classReader.getClassName().replace('/', '.');
+        }
+    }
+
+    private class TestClassVisitor extends ClassVisitor {
+
+        boolean mInjectedClassFound = false;
+
+        TestClassVisitor() {
+            super(Opcodes.ASM4);
+        }
+
+        @Override
+        public void visit(int version, int access, String name, String signature,
+                String superName, String[] interfaces) {
+            assertTrue(!getBase(name).equals(JAVA_CLASS_NAME));
+            if (name.equals("com/android/tools/layoutlib/create/dataclass/JavaClass")) {
+                mInjectedClassFound = true;
+            }
+            super.visit(version, access, name, signature, superName, interfaces);
+        }
+
+        @Override
+        public FieldVisitor visitField(int access, String name, String desc,
+                String signature, Object value) {
+            assertTrue(testType(Type.getType(desc)));
+            return super.visitField(access, name, desc, signature, value);
+        }
+
+        @SuppressWarnings("hiding")
+        @Override
+        public MethodVisitor visitMethod(int access, String name, String desc,
+                String signature, String[] exceptions) {
+            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+            return new MethodVisitor(Opcodes.ASM4, mv) {
+
+                @Override
+                public void visitFieldInsn(int opcode, String owner, String name,
+                        String desc) {
+                    assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
+                    assertTrue(testType(Type.getType(desc)));
+                    super.visitFieldInsn(opcode, owner, name, desc);
+                }
+
+                @Override
+                public void visitLdcInsn(Object cst) {
+                    if (cst instanceof Type) {
+                        assertTrue(testType((Type)cst));
+                    }
+                    super.visitLdcInsn(cst);
+                }
+
+                @Override
+                public void visitTypeInsn(int opcode, String type) {
+                    assertTrue(!getBase(type).equals(JAVA_CLASS_NAME));
+                    super.visitTypeInsn(opcode, type);
+                }
+
+                @Override
+                public void visitMethodInsn(int opcode, String owner, String name,
+                        String desc) {
+                    assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
+                    assertTrue(testType(Type.getType(desc)));
+                    super.visitMethodInsn(opcode, owner, name, desc);
+                }
+
+            };
+        }
+
+        private boolean testType(Type type) {
+            int sort = type.getSort();
+            if (sort == Type.OBJECT) {
+                assertTrue(!getBase(type.getInternalName()).equals(JAVA_CLASS_NAME));
+            } else if (sort == Type.ARRAY) {
+                assertTrue(!getBase(type.getElementType().getInternalName())
+                        .equals(JAVA_CLASS_NAME));
+            } else if (sort == Type.METHOD) {
+                boolean r = true;
+                for (Type t : type.getArgumentTypes()) {
+                    r &= testType(t);
+                }
+                return r & testType(type.getReturnType());
+            }
+            return true;
+        }
+
+        private String getBase(String className) {
+            if (className == null) {
+                return null;
+            }
+            int pos = className.indexOf('$');
+            if (pos > 0) {
+                return className.substring(0, pos);
+            }
+            return className;
+        }
     }
 }
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java
index 90c6a9c..6211e73 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java
@@ -24,7 +24,7 @@
 import org.junit.Test;
 
 /**
- * 
+ *
  */
 public class RenameClassAdapterTest {
 
@@ -36,10 +36,10 @@
         mOuter = new RenameClassAdapter(null, // cv
                                          "com.pack.Old",
                                          "org.blah.New");
-        
+
         mInner = new RenameClassAdapter(null, // cv
                                          "com.pack.Old$Inner",
-                                         "org.blah.New$Inner"); 
+                                         "org.blah.New$Inner");
     }
 
     @After
@@ -72,7 +72,7 @@
         // arrays
         assertEquals("[Lorg.blah.New;",  mOuter.renameTypeDesc("[Lcom.pack.Old;"));
         assertEquals("[[Lorg.blah.New;", mOuter.renameTypeDesc("[[Lcom.pack.Old;"));
-        
+
         assertEquals("[Lorg.blah.New;",  mInner.renameTypeDesc("[Lcom.pack.Old;"));
         assertEquals("[[Lorg.blah.New;", mInner.renameTypeDesc("[[Lcom.pack.Old;"));
     }
@@ -93,10 +93,6 @@
      */
     @Test
     public void testRenameInternalType() {
-        // a descriptor is not left untouched
-        assertEquals("Lorg.blah.New;", mOuter.renameInternalType("Lcom.pack.Old;"));
-        assertEquals("Lorg.blah.New$Inner;", mOuter.renameInternalType("Lcom.pack.Old$Inner;"));
-
         // an actual FQCN
         assertEquals("org.blah.New", mOuter.renameInternalType("com.pack.Old"));
         assertEquals("org.blah.New$Inner", mOuter.renameInternalType("com.pack.Old$Inner"));
@@ -115,6 +111,6 @@
                mOuter.renameMethodDesc("(IDLcom.pack.Old;[Lcom.pack.Old$Inner;)Lcom.pack.Old$Other;"));
     }
 
-    
+
 
 }
diff --git a/tools/layoutlib/create/tests/mock_android/view/View.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/JavaClass.java
similarity index 75%
copy from tools/layoutlib/create/tests/mock_android/view/View.java
copy to tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/JavaClass.java
index a80a98d..9b5a918 100644
--- a/tools/layoutlib/create/tests/mock_android/view/View.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/JavaClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package mock_android.view;
+package com.android.tools.layoutlib.create.dataclass;
 
-public class View {
+public final class JavaClass {
 
+    public static final String test = "test";
 }
diff --git a/tools/layoutlib/create/tests/data/mock_android.jar b/tools/layoutlib/create/tests/data/mock_android.jar
index a7ea74f..60d8efb 100644
--- a/tools/layoutlib/create/tests/data/mock_android.jar
+++ b/tools/layoutlib/create/tests/data/mock_android.jar
Binary files differ
diff --git a/tools/layoutlib/create/tests/data/mock_android.jardesc b/tools/layoutlib/create/tests/data/mock_android.jardesc
deleted file mode 100644
index 95f7591..0000000
--- a/tools/layoutlib/create/tests/data/mock_android.jardesc
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="WINDOWS-1252" standalone="no"?>
-<jardesc>
-    <jar path="C:/ralf/google/src/raphael-lapdroid/device/tools/layoutlib/create/tests/data/mock_android.jar"/>
-    <options buildIfNeeded="true" compress="true" descriptionLocation="/layoutlib_create/tests/data/mock_android.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
-    <storedRefactorings deprecationInfo="true" structuralOnly="false"/>
-    <selectedProjects/>
-    <manifest generateManifest="true" manifestLocation="" manifestVersion="1.0" reuseManifest="false" saveManifest="false" usesManifest="true">
-        <sealing sealJar="false">
-            <packagesToSeal/>
-            <packagesToUnSeal/>
-        </sealing>
-    </manifest>
-    <selectedElements exportClassFiles="true" exportJavaFiles="false" exportOutputFolder="false">
-        <javaElement handleIdentifier="=layoutlib_create/tests&lt;mock_android.widget"/>
-        <javaElement handleIdentifier="=layoutlib_create/tests&lt;mock_android.view"/>
-        <javaElement handleIdentifier="=layoutlib_create/tests&lt;mock_android.dummy"/>
-    </selectedElements>
-</jardesc>
diff --git a/tools/layoutlib/create/tests/mock_android/view/View.java b/tools/layoutlib/create/tests/mock_data/java/lang/JavaClass.java
similarity index 80%
copy from tools/layoutlib/create/tests/mock_android/view/View.java
copy to tools/layoutlib/create/tests/mock_data/java/lang/JavaClass.java
index a80a98d..59612e9 100644
--- a/tools/layoutlib/create/tests/mock_android/view/View.java
+++ b/tools/layoutlib/create/tests/mock_data/java/lang/JavaClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  *
  * Licensed under the Eclipse Public License, Version 1.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package mock_android.view;
+package java.lang;
 
-public class View {
+public class JavaClass {
 
+    public static String test = "test";
 }
diff --git a/tools/layoutlib/create/tests/mock_android/dummy/InnerTest.java b/tools/layoutlib/create/tests/mock_data/mock_android/dummy/InnerTest.java
similarity index 89%
rename from tools/layoutlib/create/tests/mock_android/dummy/InnerTest.java
rename to tools/layoutlib/create/tests/mock_data/mock_android/dummy/InnerTest.java
index e355ead..d3a1d05 100644
--- a/tools/layoutlib/create/tests/mock_android/dummy/InnerTest.java
+++ b/tools/layoutlib/create/tests/mock_data/mock_android/dummy/InnerTest.java
@@ -19,6 +19,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 
 public class InnerTest {
 
@@ -66,13 +67,13 @@
         }
     }
     
-    public <X> void genericMethod1(X a, X[] a) {
+    public <X> void genericMethod1(X a, X[] b) {
     }
 
     public <X, Y> void genericMethod2(X a, List<Y> b) {
     }
 
-    public <X, Y> void genericMethod3(X a, List<Y extends InnerTest> b) {
+    public <X, Y extends InnerTest> void genericMethod3(X a, List<Y> b) {
     }
 
     public <T extends InnerTest> void genericMethod4(T[] a, Collection<T> b, Collection<?> c) {
@@ -85,6 +86,6 @@
         mInnerInstance = m;
         mTheIntEnum = null;
         mGeneric1 = new MyGenerics1();
-        genericMethod(new DerivingClass[0], new ArrayList<DerivingClass>(), new ArrayList<InnerTest>());
+        genericMethod4(new DerivingClass[0], new ArrayList<DerivingClass>(), new ArrayList<InnerTest>());
     }
 }
diff --git a/tools/layoutlib/create/tests/mock_android/view/View.java b/tools/layoutlib/create/tests/mock_data/mock_android/view/View.java
similarity index 91%
rename from tools/layoutlib/create/tests/mock_android/view/View.java
rename to tools/layoutlib/create/tests/mock_data/mock_android/view/View.java
index a80a98d..84ec8a9 100644
--- a/tools/layoutlib/create/tests/mock_android/view/View.java
+++ b/tools/layoutlib/create/tests/mock_data/mock_android/view/View.java
@@ -16,6 +16,10 @@
 
 package mock_android.view;
 
+import java.lang.JavaClass;
+
 public class View {
 
+        String x = JavaClass.test;
+
 }
diff --git a/tools/layoutlib/create/tests/mock_android/view/ViewGroup.java b/tools/layoutlib/create/tests/mock_data/mock_android/view/ViewGroup.java
similarity index 100%
rename from tools/layoutlib/create/tests/mock_android/view/ViewGroup.java
rename to tools/layoutlib/create/tests/mock_data/mock_android/view/ViewGroup.java
diff --git a/tools/layoutlib/create/tests/mock_android/widget/LinearLayout.java b/tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
similarity index 100%
rename from tools/layoutlib/create/tests/mock_android/widget/LinearLayout.java
rename to tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java
diff --git a/tools/layoutlib/create/tests/mock_android/widget/TableLayout.java b/tools/layoutlib/create/tests/mock_data/mock_android/widget/TableLayout.java
similarity index 100%
rename from tools/layoutlib/create/tests/mock_android/widget/TableLayout.java
rename to tools/layoutlib/create/tests/mock_data/mock_android/widget/TableLayout.java