• Home
  • History
  • Annotate
  • only in /frameworks/base/tools/layoutlib/create/
NameDateSize

..11-Jul-20144 KiB

.classpath11-Jul-2014535

.project11-Jul-2014375

.settings/11-Jul-20144 KiB

Android.mk11-Jul-2014857

manifest.txt11-Jul-201452

README.txt11-Jul-201411.3 KiB

src/11-Jul-20144 KiB

tests/11-Jul-20144 KiB

README.txt

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