1*fc3927beSAndroid Build Coastguard Worker# Copyright (C) 2008 The Android Open Source Project 2*fc3927beSAndroid Build Coastguard Worker 3*fc3927beSAndroid Build Coastguard Worker 4*fc3927beSAndroid Build Coastguard Worker- Description - 5*fc3927beSAndroid Build Coastguard Worker--------------- 6*fc3927beSAndroid Build Coastguard Worker 7*fc3927beSAndroid Build Coastguard WorkerLayoutlib_create generates a JAR library used by the Android Studio graphical layout editors to perform 8*fc3927beSAndroid Build Coastguard Workerlayout and rendering. 9*fc3927beSAndroid Build Coastguard Worker 10*fc3927beSAndroid Build Coastguard Worker 11*fc3927beSAndroid Build Coastguard Worker- Usage - 12*fc3927beSAndroid Build Coastguard Worker--------- 13*fc3927beSAndroid Build Coastguard Worker 14*fc3927beSAndroid Build Coastguard Worker ./layoutlib_create destination.jar path/to/android1.jar path/to/android2.jar 15*fc3927beSAndroid Build Coastguard Worker 16*fc3927beSAndroid Build Coastguard Worker 17*fc3927beSAndroid Build Coastguard Worker- Design Overview - 18*fc3927beSAndroid Build Coastguard Worker------------------- 19*fc3927beSAndroid Build Coastguard Worker 20*fc3927beSAndroid Build Coastguard WorkerLayoutlib_create uses a few jars from the framework containing the Java code used by Android as 21*fc3927beSAndroid Build Coastguard Workergenerated by the Android build, right before the classes are converted to a DEX format. 22*fc3927beSAndroid Build Coastguard Worker 23*fc3927beSAndroid Build Coastguard WorkerThese jars can't be used directly in Android Studio as: 24*fc3927beSAndroid Build Coastguard Worker- they contains references to native code (which we cannot support in Android Studio at the moment, but working on it), 25*fc3927beSAndroid Build Coastguard Worker- some classes need to be overridden, for example all the drawing code that is replaced by Java 2D 26*fc3927beSAndroid Build Coastguard Worker calls. 27*fc3927beSAndroid Build Coastguard Worker- some of the classes that need to be changed are final and/or we need access to their private 28*fc3927beSAndroid Build Coastguard Worker internal state. 29*fc3927beSAndroid Build Coastguard Worker 30*fc3927beSAndroid Build Coastguard WorkerConsequently this tool: 31*fc3927beSAndroid Build Coastguard Worker- parses the input JAR, 32*fc3927beSAndroid Build Coastguard Worker- modifies some of the classes directly using some bytecode manipulation, 33*fc3927beSAndroid Build Coastguard Worker- filters some packages and removes those we don't want in the output JAR, 34*fc3927beSAndroid Build Coastguard Worker- injects some new classes, 35*fc3927beSAndroid Build Coastguard Worker- generates a modified JAR file that is suitable for the Android Studio to perform 36*fc3927beSAndroid Build Coastguard Worker rendering. 37*fc3927beSAndroid Build Coastguard Worker 38*fc3927beSAndroid Build Coastguard WorkerThe ASM library is used to do the bytecode modification using its visitor pattern API. 39*fc3927beSAndroid Build Coastguard Worker 40*fc3927beSAndroid Build Coastguard WorkerThe layoutlib_create is *NOT* generic. There is no configuration file. Instead all the configuration 41*fc3927beSAndroid Build Coastguard Workeris done in the main() method and the CreateInfo structure is expected to change with the Android 42*fc3927beSAndroid Build Coastguard Workerplatform as new classes are added, changed or removed. See src/com/android/tools/layoutlib/create/CreateInfo.java 43*fc3927beSAndroid Build Coastguard Workerfor more details. Some configuration that may be platform dependent is also present elsewhere in code. 44*fc3927beSAndroid Build Coastguard Worker 45*fc3927beSAndroid Build Coastguard WorkerThe resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the platform, that 46*fc3927beSAndroid Build Coastguard Workerprovides all the necessary missing implementation for rendering graphics in Android Studio. 47*fc3927beSAndroid Build Coastguard Worker 48*fc3927beSAndroid Build Coastguard Worker 49*fc3927beSAndroid Build Coastguard Worker 50*fc3927beSAndroid Build Coastguard Worker- Implementation Notes - 51*fc3927beSAndroid Build Coastguard Worker------------------------ 52*fc3927beSAndroid Build Coastguard Worker 53*fc3927beSAndroid Build Coastguard WorkerThe tool works in two phases: 54*fc3927beSAndroid Build Coastguard Worker- first analyze the input jar (AsmAnalyzer class) 55*fc3927beSAndroid Build Coastguard Worker- then generate the output jar (AsmGenerator class), 56*fc3927beSAndroid Build Coastguard Worker 57*fc3927beSAndroid Build Coastguard Worker 58*fc3927beSAndroid Build Coastguard Worker- Analyzer 59*fc3927beSAndroid Build Coastguard Worker---------- 60*fc3927beSAndroid Build Coastguard Worker 61*fc3927beSAndroid Build Coastguard WorkerThe goal of the analyzer is to create a graph of all the classes from the input JAR with their 62*fc3927beSAndroid Build Coastguard Workerdependencies and then only keep the ones we want. 63*fc3927beSAndroid Build Coastguard Worker 64*fc3927beSAndroid Build Coastguard WorkerTo do that, the analyzer is created with a list of base classes to keep -- everything that derives 65*fc3927beSAndroid Build Coastguard Workerfrom these is kept. Currently the one such class is android.view.View: since we want to render 66*fc3927beSAndroid Build Coastguard Workerlayouts, anything that is sort of a view needs to be kept. 67*fc3927beSAndroid Build Coastguard Worker 68*fc3927beSAndroid Build Coastguard WorkerThe analyzer is also given a list of class names to keep in the output. This is done using 69*fc3927beSAndroid Build Coastguard Workershell-like glob patterns that filter on the fully-qualified class names, for example "android.*.R**" 70*fc3927beSAndroid Build Coastguard Worker("*" does not match dots whilst "**" does, and "." and "$" are interpreted as-is). In practice we 71*fc3927beSAndroid Build Coastguard Workeralmost but not quite request the inclusion of full packages. 72*fc3927beSAndroid Build Coastguard Worker 73*fc3927beSAndroid Build Coastguard WorkerThe analyzer is also given a list of classes to exclude. A fake implementation of these classes is 74*fc3927beSAndroid Build Coastguard Workerinjected by the Generator. 75*fc3927beSAndroid Build Coastguard Worker 76*fc3927beSAndroid Build Coastguard WorkerWith this information, the analyzer parses the input zip to find all the classes. All classes 77*fc3927beSAndroid Build Coastguard Workerderiving from the requested base classes are kept. All classes whose name match the glob pattern 78*fc3927beSAndroid Build Coastguard Workerare kept. The analysis then finds all the dependencies of the classes that are to be kept using an 79*fc3927beSAndroid Build Coastguard WorkerASM visitor on the class, the field types, the method types and annotations types. Classes that 80*fc3927beSAndroid Build Coastguard Workerbelong to the current JRE are excluded. 81*fc3927beSAndroid Build Coastguard Worker 82*fc3927beSAndroid Build Coastguard WorkerThe output of the analyzer is a set of ASM ClassReader instances which are then fed to the 83*fc3927beSAndroid Build Coastguard Workergenerator. 84*fc3927beSAndroid Build Coastguard Worker 85*fc3927beSAndroid Build Coastguard Worker 86*fc3927beSAndroid Build Coastguard Worker- Generator 87*fc3927beSAndroid Build Coastguard Worker----------- 88*fc3927beSAndroid Build Coastguard Worker 89*fc3927beSAndroid Build Coastguard WorkerThe generator is constructed from a CreateInfo struct that acts as a config file and lists: 90*fc3927beSAndroid Build Coastguard Worker- the classes to inject in the output JAR -- these classes are directly implemented in 91*fc3927beSAndroid Build Coastguard Worker layoutlib_create and will be used to interface with the Java 2D renderer. 92*fc3927beSAndroid Build Coastguard Worker- specific methods to override (see method stubs details below). 93*fc3927beSAndroid Build Coastguard Worker- specific methods for which to delegate calls. 94*fc3927beSAndroid Build Coastguard Worker- specific methods to remove based on their return type. 95*fc3927beSAndroid Build Coastguard Worker- specific classes to rename. 96*fc3927beSAndroid Build Coastguard Worker- specific classes to refactor. 97*fc3927beSAndroid Build Coastguard Worker 98*fc3927beSAndroid Build Coastguard WorkerEach of these are specific strategies we use to be able to modify the Android code to fit within the 99*fc3927beSAndroid Build Coastguard WorkerJava 2D renderer. These strategies are explained below. 100*fc3927beSAndroid Build Coastguard Worker 101*fc3927beSAndroid Build Coastguard WorkerThe core method of the generator is transform(): it takes an input ASM ClassReader and modifies it 102*fc3927beSAndroid Build Coastguard Workerto produce a byte array suitable for the final JAR file. 103*fc3927beSAndroid Build Coastguard Worker 104*fc3927beSAndroid Build Coastguard WorkerThe first step of the transformation is to implement the method delegates. 105*fc3927beSAndroid Build Coastguard Worker 106*fc3927beSAndroid Build Coastguard WorkerThe TransformClassAdapter is then used to process the potentially renamed class. All protected or 107*fc3927beSAndroid Build Coastguard Workerprivate classes are marked as public. All classes are made non-final. Interfaces are left as-is. 108*fc3927beSAndroid Build Coastguard Worker 109*fc3927beSAndroid Build Coastguard WorkerIf a method has a return type that must be erased, the whole method is skipped. Methods are also 110*fc3927beSAndroid Build Coastguard Workerchanged from protected/private to public. The code of the methods is then kept as-is, except for 111*fc3927beSAndroid Build Coastguard Workernative methods which are replaced by a stub. Methods that are to be overridden are also replaced by 112*fc3927beSAndroid Build Coastguard Workera stub. 113*fc3927beSAndroid Build Coastguard Worker 114*fc3927beSAndroid Build Coastguard WorkerFinally fields are also visited and changed from protected/private to public. 115*fc3927beSAndroid Build Coastguard Worker 116*fc3927beSAndroid Build Coastguard WorkerThe next step of the transformation is changing the name of the class in case we requested the class 117*fc3927beSAndroid Build Coastguard Workerto be renamed. This uses the RenameClassAdapter to also rename all inner classes and references in 118*fc3927beSAndroid Build Coastguard Workermethods and types. Note that other classes are not transformed and keep referencing the original 119*fc3927beSAndroid Build Coastguard Workername. 120*fc3927beSAndroid Build Coastguard Worker 121*fc3927beSAndroid Build Coastguard WorkerThe class is then fed to RefactorClassAdapter which is like RenameClassAdapter but updates the 122*fc3927beSAndroid Build Coastguard Workerreferences in all classes. This is used to update the references of classes in the java package that 123*fc3927beSAndroid Build Coastguard Workerwere added in the Dalvik VM but are not a part of the Desktop VM. The existing classes are 124*fc3927beSAndroid Build Coastguard Workermodified to update all references to these non-desktop classes. An alternate implementation of 125*fc3927beSAndroid Build Coastguard Workerthese (com.android.tools.layoutlib.java.*) is injected. 126*fc3927beSAndroid Build Coastguard Worker 127*fc3927beSAndroid Build Coastguard WorkerReplaceMethodCallsAdapter replaces calls to certain methods. This is different from the 128*fc3927beSAndroid Build Coastguard WorkerDelegateMethodAdapter since it doesn't preserve the original copy of the method and more importantly 129*fc3927beSAndroid Build Coastguard Workerchanges the calls to a method in each class instead of changing the implementation of the method. 130*fc3927beSAndroid Build Coastguard WorkerThis is useful for methods in the Java namespace where we cannot add delegates. The configuration 131*fc3927beSAndroid Build Coastguard Workerfor this is not done through the CreateInfo class, but done in the ReplaceMethodAdapter. 132*fc3927beSAndroid Build Coastguard Worker 133*fc3927beSAndroid Build Coastguard WorkerThe ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7 134*fc3927beSAndroid Build Coastguard WorkerTransformation chains in the asm user guide, link in the References.) The order of execution of 135*fc3927beSAndroid Build Coastguard Workerthese is: 136*fc3927beSAndroid Build Coastguard WorkerClassReader -> [DelegateClassAdapter] -> TransformClassAdapter -> [RenameClassAdapter] -> 137*fc3927beSAndroid Build Coastguard WorkerRefactorClassAdapter -> [ReplaceMethodCallsAdapter] -> ClassWriter 138*fc3927beSAndroid Build Coastguard Worker 139*fc3927beSAndroid Build Coastguard Worker- Method stubs 140*fc3927beSAndroid Build Coastguard Worker-------------- 141*fc3927beSAndroid Build Coastguard Worker 142*fc3927beSAndroid Build Coastguard WorkerAs indicated above, all native and overridden methods are replaced by a stub. We don't have the 143*fc3927beSAndroid Build Coastguard Workercode to replace with in layoutlib_create. Instead the StubCallMethodAdapter replaces the code of the 144*fc3927beSAndroid Build Coastguard Workermethod by a call to OverrideMethod.invokeX(). When using the final JAR, the bridge can register 145*fc3927beSAndroid Build Coastguard Workerlisteners from these overridden method calls based on the method signatures. 146*fc3927beSAndroid Build Coastguard Worker 147*fc3927beSAndroid Build Coastguard WorkerThe listeners are currently pretty basic: we only pass the signature of the method being called, its 148*fc3927beSAndroid Build Coastguard Workercaller object and a flag indicating whether the method was native. We do not currently provide the 149*fc3927beSAndroid Build Coastguard Workerparameters. The listener can however specify the return value of the overridden method. 150*fc3927beSAndroid Build Coastguard Worker 151*fc3927beSAndroid Build Coastguard WorkerThis strategy is now obsolete and replaced by the method delegates. 152*fc3927beSAndroid Build Coastguard Worker 153*fc3927beSAndroid Build Coastguard Worker 154*fc3927beSAndroid Build Coastguard Worker- Strategies 155*fc3927beSAndroid Build Coastguard Worker------------ 156*fc3927beSAndroid Build Coastguard Worker 157*fc3927beSAndroid Build Coastguard WorkerWe currently have 6 strategies to deal with overriding the rendering code and make it run in 158*fc3927beSAndroid Build Coastguard WorkerAndroid Studio. Most of these strategies are implemented hand-in-hand by the bridge (which runs in Android Studio) 159*fc3927beSAndroid Build Coastguard Workerand the generator. 160*fc3927beSAndroid Build Coastguard Worker 161*fc3927beSAndroid Build Coastguard Worker 162*fc3927beSAndroid Build Coastguard Worker1- Class Injection 163*fc3927beSAndroid Build Coastguard Worker 164*fc3927beSAndroid Build Coastguard WorkerThis is the easiest: we currently inject the following classes: 165*fc3927beSAndroid Build Coastguard Worker- OverrideMethod and its associated MethodListener and MethodAdapter are used to intercept calls to 166*fc3927beSAndroid Build Coastguard Worker some specific methods that are stubbed out and change their return value. 167*fc3927beSAndroid Build Coastguard Worker- CreateInfo class, which configured the generator. Not used yet, but could in theory help us track 168*fc3927beSAndroid Build Coastguard Worker what the generator changed. 169*fc3927beSAndroid Build Coastguard Worker- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new classes are 170*fc3927beSAndroid Build Coastguard Worker injected. The implementation for these classes has been taken from Android's libcore 171*fc3927beSAndroid Build Coastguard Worker (platform/libcore/luni/src/main/java/java/...). 172*fc3927beSAndroid Build Coastguard Worker- Charsets, IntegralToString and UnsafeByteSequence are not part of the Desktop VM. They are 173*fc3927beSAndroid Build Coastguard Worker added to the Dalvik VM for performance reasons. An implementation that is very close to the 174*fc3927beSAndroid Build Coastguard Worker original (which is at platform/libcore/luni/src/main/java/...) is injected. Since these classes 175*fc3927beSAndroid Build Coastguard Worker were in part of the java package, where we can't inject classes, all references to these have been 176*fc3927beSAndroid Build Coastguard Worker updated (See strategy 4- Refactoring Classes). 177*fc3927beSAndroid Build Coastguard Worker 178*fc3927beSAndroid Build Coastguard Worker 179*fc3927beSAndroid Build Coastguard Worker2- Overriding methods 180*fc3927beSAndroid Build Coastguard Worker 181*fc3927beSAndroid Build Coastguard WorkerAs explained earlier, the creator doesn't have any replacement code for methods to override. Instead 182*fc3927beSAndroid Build Coastguard Workerit removes the original code and replaces it by a call to a specific OverrideMethod.invokeX(). The 183*fc3927beSAndroid Build Coastguard Workerbridge then registers a listener on the method signature and can provide an implementation. 184*fc3927beSAndroid Build Coastguard Worker 185*fc3927beSAndroid Build Coastguard WorkerThis strategy is now obsolete and replaced by the method delegates (See strategy 6- Method 186*fc3927beSAndroid Build Coastguard WorkerDelegates). 187*fc3927beSAndroid Build Coastguard Worker 188*fc3927beSAndroid Build Coastguard Worker 189*fc3927beSAndroid Build Coastguard Worker3- Renaming classes 190*fc3927beSAndroid Build Coastguard Worker 191*fc3927beSAndroid Build Coastguard WorkerThis simply changes the name of a class in its definition, as well as all its references in internal 192*fc3927beSAndroid Build Coastguard Workerinner classes and methods. Calls from other classes are not modified -- they keep referencing the 193*fc3927beSAndroid Build Coastguard Workeroriginal class name. This allows the bridge to literally replace an implementation. 194*fc3927beSAndroid Build Coastguard Worker 195*fc3927beSAndroid Build Coastguard WorkerAn example will make this easier: android.graphics.Paint is the main drawing class that we need to 196*fc3927beSAndroid Build Coastguard Workerreplace. To do so, the generator renames Paint to _original_Paint. Later the bridge provides its own 197*fc3927beSAndroid Build Coastguard Workerreplacement version of Paint which will be used by the rest of the Android stack. The replacement 198*fc3927beSAndroid Build Coastguard Workerversion of Paint can still use (either by inheritance or delegation) all the original non-native 199*fc3927beSAndroid Build Coastguard Workercode of _original_Paint if it so desires. 200*fc3927beSAndroid Build Coastguard Worker 201*fc3927beSAndroid Build Coastguard WorkerSome of the Android classes are basically wrappers over native objects and since we don't have the 202*fc3927beSAndroid Build Coastguard Workernative code in Android Studio, we need to provide a full alternate implementation. Sub-classing doesn't 203*fc3927beSAndroid Build Coastguard Workerwork as some native methods are static and we don't control object creation. 204*fc3927beSAndroid Build Coastguard Worker 205*fc3927beSAndroid Build Coastguard WorkerThis won't rename/replace the inner static methods of a given class. 206*fc3927beSAndroid Build Coastguard Worker 207*fc3927beSAndroid Build Coastguard Worker 208*fc3927beSAndroid Build Coastguard Worker4- Refactoring classes 209*fc3927beSAndroid Build Coastguard Worker 210*fc3927beSAndroid Build Coastguard WorkerThis is very similar to the Renaming classes except that it also updates the reference in all 211*fc3927beSAndroid Build Coastguard Workerclasses. This is done for classes which are added to the Dalvik VM for performance reasons but are 212*fc3927beSAndroid Build Coastguard Workernot present in the Desktop VM. An implementation for these classes is also injected. 213*fc3927beSAndroid Build Coastguard Worker 214*fc3927beSAndroid Build Coastguard Worker 215*fc3927beSAndroid Build Coastguard Worker5- Method erasure based on return type 216*fc3927beSAndroid Build Coastguard Worker 217*fc3927beSAndroid Build Coastguard WorkerThis is mostly an implementation detail of the bridge: in the Paint class mentioned above, some 218*fc3927beSAndroid Build Coastguard Workerinner static classes are used to pass around attributes (e.g. FontMetrics, or the Style enum) and 219*fc3927beSAndroid Build Coastguard Workerall the original implementation is native. 220*fc3927beSAndroid Build Coastguard Worker 221*fc3927beSAndroid Build Coastguard WorkerIn this case we have a strategy that tells the generator that anything returning, for example, the 222*fc3927beSAndroid Build Coastguard Workerinner class Paint$Style in the Paint class should be discarded and the bridge will provide its own 223*fc3927beSAndroid Build Coastguard Workerimplementation. 224*fc3927beSAndroid Build Coastguard Worker 225*fc3927beSAndroid Build Coastguard Worker 226*fc3927beSAndroid Build Coastguard Worker6- Method Delegates 227*fc3927beSAndroid Build Coastguard Worker 228*fc3927beSAndroid Build Coastguard WorkerThis strategy is used to override method implementations. Given a method SomeClass.MethodName(), 1 229*fc3927beSAndroid Build Coastguard Workeror 2 methods are generated: 230*fc3927beSAndroid Build Coastguard Workera- A copy of the original method named SomeClass.MethodName_Original(). The content is the original 231*fc3927beSAndroid Build Coastguard Workermethod as-is from the reader. This step is omitted if the method is native, since it has no Java 232*fc3927beSAndroid Build Coastguard Workerimplementation. 233*fc3927beSAndroid Build Coastguard Workerb- A brand new implementation of SomeClass.MethodName() which calls to a non-existing static method 234*fc3927beSAndroid Build Coastguard Workernamed SomeClass_Delegate.MethodName(). The implementation of this 'delegate' method is done in 235*fc3927beSAndroid Build Coastguard Workerlayoutlib_bridge. 236*fc3927beSAndroid Build Coastguard Worker 237*fc3927beSAndroid Build Coastguard WorkerThe delegate method is a static method. If the original method is non-static, the delegate method 238*fc3927beSAndroid Build Coastguard Workerreceives the original 'this' as its first argument. If the original method is an inner non-static 239*fc3927beSAndroid Build Coastguard Workermethod, it also receives the inner 'this' as the second argument. 240*fc3927beSAndroid Build Coastguard Worker 241*fc3927beSAndroid Build Coastguard Worker 242*fc3927beSAndroid Build Coastguard Worker 243*fc3927beSAndroid Build Coastguard Worker- References - 244*fc3927beSAndroid Build Coastguard Worker-------------- 245*fc3927beSAndroid Build Coastguard Worker 246*fc3927beSAndroid Build Coastguard Worker 247*fc3927beSAndroid Build Coastguard WorkerThe JVM Specification 2nd edition: 248*fc3927beSAndroid Build Coastguard Worker http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html 249*fc3927beSAndroid Build Coastguard Worker 250*fc3927beSAndroid Build Coastguard WorkerUnderstanding bytecode: 251*fc3927beSAndroid Build Coastguard Worker http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/ 252*fc3927beSAndroid Build Coastguard Worker 253*fc3927beSAndroid Build Coastguard WorkerBytecode opcode list: 254*fc3927beSAndroid Build Coastguard Worker http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings 255*fc3927beSAndroid Build Coastguard Worker 256*fc3927beSAndroid Build Coastguard WorkerASM user guide: 257*fc3927beSAndroid Build Coastguard Worker http://download.forge.objectweb.org/asm/asm4-guide.pdf 258*fc3927beSAndroid Build Coastguard Worker 259*fc3927beSAndroid Build Coastguard Worker 260*fc3927beSAndroid Build Coastguard Worker-- 261*fc3927beSAndroid Build Coastguard Workerend 262