diff options
author | Xavier Ducrohet <xav@android.com> | 2012-05-29 20:46:22 -0700 |
---|---|---|
committer | android code review <noreply-gerritcodereview@google.com> | 2012-05-29 20:46:23 -0700 |
commit | 8a7ac644b4d1197849fb1ae5d81730c807ba89eb (patch) | |
tree | 6779fa2321315faf888e027fe0f721c1e2414cc5 | |
parent | 6f2290e44b112695c9796de4ba7be887e7d64791 (diff) | |
parent | dc3f6e66f549d0313192d6df2bd3b2b3fa9b70a9 (diff) | |
download | sdk-8a7ac644b4d1197849fb1ae5d81730c807ba89eb.zip sdk-8a7ac644b4d1197849fb1ae5d81730c807ba89eb.tar.gz sdk-8a7ac644b4d1197849fb1ae5d81730c807ba89eb.tar.bz2 |
Merge "Update ApiGenerator to only deal with android.jar."
10 files changed, 290 insertions, 1947 deletions
diff --git a/apigenerator/src/com/android/apigenerator/AndroidJarReader.java b/apigenerator/src/com/android/apigenerator/AndroidJarReader.java new file mode 100644 index 0000000..89924a5 --- /dev/null +++ b/apigenerator/src/com/android/apigenerator/AndroidJarReader.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2012 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.apigenerator; + +import com.android.util.Pair; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.FieldNode; +import org.objectweb.asm.tree.MethodNode; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * Reads all the android.jar files found in an SDK and generate a map of {@link ApiClass}. + * + */ +public class AndroidJarReader { + + private static final byte[] BUFFER = new byte[65535]; + + private final String mSdkFolder; + + public AndroidJarReader(String sdkFolder) { + mSdkFolder = sdkFolder; + } + + public Map<String, ApiClass> getClasses() { + HashMap<String, ApiClass> map = new HashMap<String, ApiClass>(); + + // Get all the android.jar. They are in platforms-# + int apiLevel = 0; + while (true) { + apiLevel++; + try { + File jar = new File(mSdkFolder, "platforms/android-" + apiLevel + "/android.jar"); + if (jar.exists() == false) { + System.out.println("Last API level found: " + (apiLevel-1)); + break; + } + + FileInputStream fis = new FileInputStream(jar); + ZipInputStream zis = new ZipInputStream(fis); + ZipEntry entry = zis.getNextEntry(); + while (entry != null) { + String name = entry.getName(); + + if (name.endsWith(".class")) { + + int index = 0; + do { + int size = zis.read(BUFFER, index, BUFFER.length - index); + if (size >= 0) { + index += size; + } else { + break; + } + } while (true); + + byte[] b = new byte[index]; + System.arraycopy(BUFFER, 0, b, 0, index); + + ClassReader reader = new ClassReader(b); + ClassNode classNode = new ClassNode(); + reader.accept(classNode, 0 /*flags*/); + + if (classNode != null) { + ApiClass theClass = addClass(map, classNode.name, apiLevel); + + // super class + if (classNode.superName != null) { + theClass.addSuperClass(classNode.superName, apiLevel); + } + + // interfaces + for (Object interfaceName : classNode.interfaces) { + theClass.addInterface((String) interfaceName, apiLevel); + } + + // fields + for (Object field : classNode.fields) { + FieldNode fieldNode = (FieldNode) field; + if ((fieldNode.access & Opcodes.ACC_PRIVATE) != 0) { + continue; + } + if (fieldNode.name.startsWith("this$") == false && + fieldNode.name.equals("$VALUES") == false) { + theClass.addField(fieldNode.name, apiLevel); + } + } + + // methods + for (Object method : classNode.methods) { + MethodNode methodNode = (MethodNode) method; + if ((methodNode.access & Opcodes.ACC_PRIVATE) != 0) { + continue; + } + if (methodNode.name.equals("<clinit>") == false) { + theClass.addMethod(methodNode.name + methodNode.desc, apiLevel); + } + } + } + } + entry = zis.getNextEntry(); + } + + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + + } + } + + postProcessClasses(map); + + return map; + } + + private void postProcessClasses(Map<String, ApiClass> classes) { + for (ApiClass theClass : classes.values()) { + Map<String, Integer> methods = theClass.getMethods(); + Map<String, Integer> fixedMethods = new HashMap<String, Integer>(); + + List<Pair<String, Integer>> superClasses = theClass.getSuperClasses(); + List<Pair<String, Integer>> interfaces = theClass.getInterfaces(); + + methodLoop: for (Entry<String, Integer> method : methods.entrySet()) { + String methodName = method.getKey(); + int apiLevel = method.getValue(); + + if (methodName.startsWith("<init>(") == false) { + + for (Pair<String, Integer> parent : superClasses) { + // only check the parent if it was a parent class at the introduction + // of the method. + if (parent.getSecond() <= apiLevel) { + ApiClass parentClass = classes.get(parent.getFirst()); + assert parentClass != null; + if (parentClass != null && + checkClassContains(theClass.getName(), + methodName, apiLevel, + classes, parentClass)) { + continue methodLoop; + } + } + } + + for (Pair<String, Integer> parent : interfaces) { + // only check the parent if it was a parent class at the introduction + // of the method. + if (parent.getSecond() <= apiLevel) { + ApiClass parentClass = classes.get(parent.getFirst()); + assert parentClass != null; + if (parentClass != null && + checkClassContains(theClass.getName(), + methodName, apiLevel, + classes, parentClass)) { + continue methodLoop; + } + } + } + } + + // if we reach here. the method isn't an override + fixedMethods.put(methodName, method.getValue()); + } + + theClass.replaceMethods(fixedMethods); + } + } + + private boolean checkClassContains(String className, String methodName, int apiLevel, + Map<String, ApiClass> classMap, ApiClass parentClass) { + + Integer parentMethodApiLevel = parentClass.getMethods().get(methodName); + if (parentMethodApiLevel != null && parentMethodApiLevel <= apiLevel) { + // the parent class has the method and it was introduced in the parent at the + // same api level as the method, or before. + return true; + } + + // check on this class parents. + List<Pair<String, Integer>> superClasses = parentClass.getSuperClasses(); + List<Pair<String, Integer>> interfaces = parentClass.getInterfaces(); + + for (Pair<String, Integer> parent : superClasses) { + // only check the parent if it was a parent class at the introduction + // of the method. + if (parent.getSecond() <= apiLevel) { + ApiClass superParentClass = classMap.get(parent.getFirst()); + assert superParentClass != null; + if (superParentClass != null && checkClassContains(className, methodName, apiLevel, + classMap, superParentClass)) { + return true; + } + } + } + + for (Pair<String, Integer> parent : interfaces) { + // only check the parent if it was a parent class at the introduction + // of the method. + if (parent.getSecond() <= apiLevel) { + ApiClass superParentClass = classMap.get(parent.getFirst()); + assert superParentClass != null; + if (superParentClass != null && checkClassContains(className, methodName, apiLevel, + classMap, superParentClass)) { + return true; + } + } + } + + return false; + } + + private ApiClass addClass(HashMap<String, ApiClass> classes, String name, int apiLevel) { + ApiClass theClass = classes.get(name); + if (theClass == null) { + theClass = new ApiClass(name, apiLevel); + classes.put(name, theClass); + } + + return theClass; + } +} diff --git a/apigenerator/src/com/android/apigenerator/ApiClass.java b/apigenerator/src/com/android/apigenerator/ApiClass.java index 13b2d42..ccdc075 100644 --- a/apigenerator/src/com/android/apigenerator/ApiClass.java +++ b/apigenerator/src/com/android/apigenerator/ApiClass.java @@ -20,6 +20,8 @@ import com.android.util.Pair; import java.io.PrintStream; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -49,6 +51,10 @@ public class ApiClass { mSince = since; } + public String getName() { + return mName; + } + int getSince() { return mSince; } @@ -67,18 +73,35 @@ public class ApiClass { } } + public Map<String, Integer> getMethods() { + return mMethods; + } + + public void replaceMethods(Map<String, Integer> fixedMethods) { + mMethods.clear(); + mMethods.putAll(fixedMethods); + } + public void addSuperClass(String superClass, int since) { addToArray(mSuperClasses, superClass, since); } + public List<Pair<String, Integer>> getSuperClasses() { + return mSuperClasses; + } + public void addInterface(String interfaceClass, int since) { addToArray(mInterfaces, interfaceClass, since); } + public List<Pair<String, Integer>> getInterfaces() { + return mInterfaces; + } + void addToArray(List<Pair<String, Integer>> list, String name, int value) { // check if we already have that name (at a lower level) for (Pair<String, Integer> pair : list) { - if (name.equals(pair.getFirst())) { + if (name.equals(pair.getFirst()) && pair.getSecond() < value) { return; } } @@ -102,6 +125,13 @@ public class ApiClass { } private void print(List<Pair<String, Integer> > list, String name, PrintStream stream) { + Collections.sort(list, new Comparator<Pair<String, Integer> >() { + + @Override + public int compare(Pair<String, Integer> o1, Pair<String, Integer> o2) { + return o1.getFirst().compareTo(o2.getFirst()); + } + }); for (Pair<String, Integer> pair : list) { if (mSince == pair.getSecond()) { diff --git a/apigenerator/src/com/android/apigenerator/ApiParseException.java b/apigenerator/src/com/android/apigenerator/ApiParseException.java deleted file mode 100644 index 7fc8bde..0000000 --- a/apigenerator/src/com/android/apigenerator/ApiParseException.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 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.apigenerator; - - -/** - * Basic exception used by {@link NewApiParser}. - * - * This is adapted from doclava. - * - */ -public final class ApiParseException extends Exception { - private static final long serialVersionUID = 1L; - - public String file; - public int line; - - public ApiParseException() { - } - - public ApiParseException(String message) { - super(message); - } - - public ApiParseException(String message, Exception cause) { - super(message, cause); - if (cause instanceof ApiParseException) { - this.line = ((ApiParseException) cause).line; - } - } - - public ApiParseException(String message, int line) { - super(message); - this.line = line; - } - - @Override - public String getMessage() { - if (line > 0) { - return super.getMessage() + " line " + line; - } else { - return super.getMessage(); - } - } -} diff --git a/apigenerator/src/com/android/apigenerator/EnumParser.java b/apigenerator/src/com/android/apigenerator/EnumParser.java deleted file mode 100644 index 18c0a94..0000000 --- a/apigenerator/src/com/android/apigenerator/EnumParser.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (C) 2012 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.apigenerator; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - -/** - * Parser for the simplified XML API format version 1. - */ -public class EnumParser extends DefaultHandler { - - private final static String NODE_API = "api"; - private final static String NODE_CLASS = "class"; - private final static String NODE_FIELD = "field"; - private final static String NODE_METHOD = "method"; - private final static String NODE_EXTENDS = "extends"; - private final static String NODE_IMPLEMENTS = "implements"; - - private final static String ATTR_NAME = "name"; - private final static String ATTR_SINCE = "since"; - - private final Map<String, ApiClass> mClasses = new HashMap<String, ApiClass>(); - - private ApiClass mCurrentClass; - - public EnumParser() { - } - - public Map<String, ApiClass> getClasses() { - return mClasses; - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - - if (localName == null || localName.length() == 0) { - localName = qName; - } - - try { - if (NODE_API.equals(localName)) { - // do nothing. - - } else if (NODE_CLASS.equals(localName)) { - String name = attributes.getValue(ATTR_NAME); - int since = Integer.parseInt(attributes.getValue(ATTR_SINCE)); - - mCurrentClass = addClass(name, since); - - } else if (NODE_EXTENDS.equals(localName)) { - String name = attributes.getValue(ATTR_NAME); - int since = getSince(attributes); - - mCurrentClass.addSuperClass(name, since); - - } else if (NODE_IMPLEMENTS.equals(localName)) { - String name = attributes.getValue(ATTR_NAME); - int since = getSince(attributes); - - mCurrentClass.addInterface(name, since); - - } else if (NODE_METHOD.equals(localName)) { - String name = attributes.getValue(ATTR_NAME); - int since = getSince(attributes); - - mCurrentClass.addMethod(name, since); - - } else if (NODE_FIELD.equals(localName)) { - String name = attributes.getValue(ATTR_NAME); - int since = getSince(attributes); - - mCurrentClass.addField(name, since); - - } - - } finally { - super.startElement(uri, localName, qName, attributes); - } - } - - private ApiClass addClass(String name, int apiLevel) { - ApiClass theClass = mClasses.get(name); - if (theClass == null) { - theClass = new ApiClass(name, apiLevel); - mClasses.put(name, theClass); - } - - return theClass; - } - - private int getSince(Attributes attributes) { - int since = mCurrentClass.getSince(); - String sinceAttr = attributes.getValue(ATTR_SINCE); - - if (sinceAttr != null) { - since = Integer.parseInt(sinceAttr); - } - - return since; - } - - public static Map<String, ApiClass> parseApi(InputStream stream) { - try { - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - SAXParser parser = parserFactory.newSAXParser(); - EnumParser apiParser = new EnumParser(); - parser.parse(stream, apiParser); - - return apiParser.getClasses(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - -} diff --git a/apigenerator/src/com/android/apigenerator/Main.java b/apigenerator/src/com/android/apigenerator/Main.java index 5c26e14..4ce7ac9 100644 --- a/apigenerator/src/com/android/apigenerator/Main.java +++ b/apigenerator/src/com/android/apigenerator/Main.java @@ -17,24 +17,13 @@ package com.android.apigenerator; -import com.android.apigenerator.enumfix.AndroidJarReader; - -import org.xml.sax.SAXException; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; import java.io.PrintStream; -import java.util.HashMap; import java.util.Map; import java.util.TreeMap; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - /** * Main class for command line command to convert the existing API XML/TXT files into diff-based * simple text files. @@ -46,98 +35,22 @@ public class Main { * @param args */ public static void main(String[] args) { - if (args.length < 2 || args.length > 3) { + if (args.length != 2) { printUsage(); } - if (args.length == 3) { - if (args[0].equals("enum")) { - AndroidJarReader reader = new AndroidJarReader(args[1]); - Map<String, ApiClass> classes = reader.getEnumClasses(); - createApiFile(new File(args[2]), classes); - } else { - printUsage(); - } - } else { - Map<String, ApiClass> classes = parsePlatformApiFiles(new File(args[0])); - createApiFile(new File(args[1]), classes); - } - + AndroidJarReader reader = new AndroidJarReader(args[0]); + Map<String, ApiClass> classes = reader.getClasses(); + createApiFile(new File(args[1]), classes); } private static void printUsage() { - System.err.println("Convert API files into a more manageable file\n"); + System.err.println("Generates a single API file from the content of an SDK.\n"); System.err.println("Usage\n"); - System.err.println("\tApiCheck [enum] FOLDER OUTFILE\n"); + System.err.println("\tApiCheck SDKFOLDER OUTFILE\n"); System.exit(1); } - - /** - * Parses platform API files. - * @param apiFolder the folder containing the files. - * @return a top level {@link ApiInfo} object for the highest available API level. - */ - private static Map<String, ApiClass> parsePlatformApiFiles(File apiFolder) { - int apiLevel = 1; - - Map<String, ApiClass> map = new HashMap<String, ApiClass>(); - - InputStream stream = Main.class.getResourceAsStream( - "enums.xml"); - if (stream != null) { - map = EnumParser.parseApi(stream); - } - - if (map == null) { - map = new HashMap<String, ApiClass>(); - } - - while (true) { - File file = new File(apiFolder, Integer.toString(apiLevel) + ".xml"); - if (file.exists()) { - parseXmlApiFile(file, apiLevel, map); - apiLevel++; - } else { - file = new File(apiFolder, Integer.toString(apiLevel) + ".txt"); - if (file.exists()) { - parseTxtApiFile(file, apiLevel, map); - apiLevel++; - - } else { - break; - } - } - } - - return map; - } - - private static void parseTxtApiFile(File apiFile, int api, Map<String, ApiClass> map) { - try { - NewApiParser.parseApi(apiFile.getName(), new FileInputStream(apiFile), map, api); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (ApiParseException e) { - e.printStackTrace(); - } - } - - private static void parseXmlApiFile(File apiFile, int apiLevel, - Map<String, ApiClass> map) { - try { - SAXParserFactory parserFactory = SAXParserFactory.newInstance(); - SAXParser parser = parserFactory.newSAXParser(); - parser.parse(new FileInputStream(apiFile), new XmlApiParser(map, apiLevel)); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - } - /** * Creates the simplified diff-based API level. * @param outFolder the out folder. diff --git a/apigenerator/src/com/android/apigenerator/NewApiParser.java b/apigenerator/src/com/android/apigenerator/NewApiParser.java deleted file mode 100644 index 91cb1e2..0000000 --- a/apigenerator/src/com/android/apigenerator/NewApiParser.java +++ /dev/null @@ -1,619 +0,0 @@ -/* - * Copyright (C) 2012 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.apigenerator; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - -/** - * Parser for the new format of platform API files. This is adapted from the Doclava code. - * - */ -class NewApiParser { - - public static void parseApi(String filename, InputStream stream, - Map<String, ApiClass> classes, int api) throws ApiParseException { - final int CHUNK = 1024 * 1024; - int hint = 0; - try { - hint = stream.available() + CHUNK; - } catch (IOException ex) { - } - - if (hint < CHUNK) { - hint = CHUNK; - } - - byte[] buf = new byte[hint]; - int size = 0; - - try { - while (true) { - if (size == buf.length) { - byte[] tmp = new byte[buf.length + CHUNK]; - System.arraycopy(buf, 0, tmp, 0, buf.length); - buf = tmp; - } - int amt = stream.read(buf, size, (buf.length - size)); - if (amt < 0) { - break; - } else { - size += amt; - } - } - } catch (IOException ex) { - throw new ApiParseException("Error reading API file", ex); - } - - final Tokenizer tokenizer = new Tokenizer(filename, - (new String(buf, 0, size)).toCharArray()); - - final ParserState state = new ParserState(classes, api); - - while (true) { - String token = tokenizer.getToken(); - if (token == null) { - break; - } - if ("package".equals(token)) { - parsePackage(state, tokenizer); - } else { - throw new ApiParseException("expected package got " + token, tokenizer.getLine()); - } - } - } - - private static void parsePackage(ParserState state, Tokenizer tokenizer) - throws ApiParseException { - String token; - String name; - - token = tokenizer.requireToken(); - assertIdent(tokenizer, token); - name = token; - - state.addPackage(name); - - token = tokenizer.requireToken(); - if (!"{".equals(token)) { - throw new ApiParseException("expected '{' got " + token, tokenizer.getLine()); - } - while (true) { - token = tokenizer.requireToken(); - if ("}".equals(token)) { - break; - } else { - parseClass(state, tokenizer, token); - } - } - - state.finishPackage(); - } - - private static void parseClass(ParserState state, Tokenizer tokenizer, String token) - throws ApiParseException { - boolean pub = false; - boolean prot = false; - boolean pkgpriv = false; - boolean stat = false; - boolean fin = false; - boolean abs = false; - boolean dep = false; - boolean iface; - String name; - String qname; - - // even though we don't care about all those parameters, we keep this parsing logic - // to make sure we go through all the tokens. - - if ("public".equals(token)) { - pub = true; - token = tokenizer.requireToken(); - } else if ("protected".equals(token)) { - prot = true; - token = tokenizer.requireToken(); - } else { - pkgpriv = true; - } - if ("static".equals(token)) { - stat = true; - token = tokenizer.requireToken(); - } - if ("final".equals(token)) { - fin = true; - token = tokenizer.requireToken(); - } - if ("abstract".equals(token)) { - abs = true; - token = tokenizer.requireToken(); - } - if ("deprecated".equals(token)) { - dep = true; - token = tokenizer.requireToken(); - } - if ("class".equals(token)) { - iface = false; - token = tokenizer.requireToken(); - } else if ("interface".equals(token)) { - iface = true; - token = tokenizer.requireToken(); - } else { - throw new ApiParseException("missing class or interface. got: " + token, - tokenizer.getLine()); - } - assertIdent(tokenizer, token); - name = token; - token = tokenizer.requireToken(); - - state.addClass(name); - - // even though we don't care about all those parameters, we keep this parsing logic - // to make sure we go through all the tokens. - - - if ("extends".equals(token)) { - token = tokenizer.requireToken(); - assertIdent(tokenizer, token); - state.addSuperClass(token); - token = tokenizer.requireToken(); - } - - // Resolve superclass after done parsing - if ("implements".equals(token)) { - while (true) { - token = tokenizer.requireToken(); - if ("{".equals(token)) { - break; - } else { - if (!",".equals(token)) { - state.addInterface(token); - } - } - } - } - - if (!"{".equals(token)) { - throw new ApiParseException("expected {", tokenizer.getLine()); - } - - token = tokenizer.requireToken(); - while (true) { - if ("}".equals(token)) { - break; - } else if ("ctor".equals(token)) { - token = tokenizer.requireToken(); - parseConstructor(tokenizer, state, token); - } else if ("method".equals(token)) { - token = tokenizer.requireToken(); - parseMethod(tokenizer, state, token); - } else if ("field".equals(token)) { - token = tokenizer.requireToken(); - parseField(tokenizer, state, token, false); - } else if ("enum_constant".equals(token)) { - token = tokenizer.requireToken(); - parseField(tokenizer, state, token, true); - } else { - throw new ApiParseException("expected ctor, enum_constant, field or method", - tokenizer.getLine()); - } - token = tokenizer.requireToken(); - } - - state.finishClass(); - } - - private static void parseConstructor(Tokenizer tokenizer, ParserState state, String token) - throws ApiParseException { - boolean pub = false; - boolean prot = false; - boolean pkgpriv = false; - boolean dep = false; - String name; - - if ("public".equals(token)) { - pub = true; - token = tokenizer.requireToken(); - } else if ("protected".equals(token)) { - prot = true; - token = tokenizer.requireToken(); - } else { - pkgpriv = true; - } - if ("deprecated".equals(token)) { - dep = true; - token = tokenizer.requireToken(); - } - assertIdent(tokenizer, token); - name = token; - token = tokenizer.requireToken(); - if (!"(".equals(token)) { - throw new ApiParseException("expected (", tokenizer.getLine()); - } - - state.startNewConstructor(); - - token = tokenizer.requireToken(); - parseParameterList(tokenizer, state, token); - token = tokenizer.requireToken(); - if ("throws".equals(token)) { - token = parseThrows(tokenizer, state); - } - if (!";".equals(token)) { - throw new ApiParseException("expected ; found " + token, tokenizer.getLine()); - } - - state.finishMethod(); - } - - private static void parseMethod(Tokenizer tokenizer, ParserState state, String token) - throws ApiParseException { - boolean pub = false; - boolean prot = false; - boolean pkgpriv = false; - boolean stat = false; - boolean fin = false; - boolean abs = false; - boolean dep = false; - boolean syn = false; - String type; - String name; - String ext = null; - - if ("public".equals(token)) { - pub = true; - token = tokenizer.requireToken(); - } else if ("protected".equals(token)) { - prot = true; - token = tokenizer.requireToken(); - } else { - pkgpriv = true; - } - if ("static".equals(token)) { - stat = true; - token = tokenizer.requireToken(); - } - if ("final".equals(token)) { - fin = true; - token = tokenizer.requireToken(); - } - if ("abstract".equals(token)) { - abs = true; - token = tokenizer.requireToken(); - } - if ("deprecated".equals(token)) { - dep = true; - token = tokenizer.requireToken(); - } - if ("synchronized".equals(token)) { - syn = true; - token = tokenizer.requireToken(); - } - assertIdent(tokenizer, token); - type = token; - token = tokenizer.requireToken(); - assertIdent(tokenizer, token); - name = token; - - state.startNewMethod(name, type); - - token = tokenizer.requireToken(); - if (!"(".equals(token)) { - throw new ApiParseException("expected (", tokenizer.getLine()); - } - token = tokenizer.requireToken(); - parseParameterList(tokenizer, state, token); - token = tokenizer.requireToken(); - if ("throws".equals(token)) { - token = parseThrows(tokenizer, state); - } - if (!";".equals(token)) { - throw new ApiParseException("expected ; found " + token, tokenizer.getLine()); - } - - state.finishMethod(); - } - - private static void parseField(Tokenizer tokenizer, ParserState state, String token, boolean isEnum) - throws ApiParseException { - boolean pub = false; - boolean prot = false; - boolean pkgpriv = false; - boolean stat = false; - boolean fin = false; - boolean dep = false; - boolean trans = false; - boolean vol = false; - String type; - String name; - String val = null; - Object v; - - if ("public".equals(token)) { - pub = true; - token = tokenizer.requireToken(); - } else if ("protected".equals(token)) { - prot = true; - token = tokenizer.requireToken(); - } else { - pkgpriv = true; - } - if ("static".equals(token)) { - stat = true; - token = tokenizer.requireToken(); - } - if ("final".equals(token)) { - fin = true; - token = tokenizer.requireToken(); - } - if ("deprecated".equals(token)) { - dep = true; - token = tokenizer.requireToken(); - } - if ("transient".equals(token)) { - trans = true; - token = tokenizer.requireToken(); - } - if ("volatile".equals(token)) { - vol = true; - token = tokenizer.requireToken(); - } - assertIdent(tokenizer, token); - type = token; - token = tokenizer.requireToken(); - assertIdent(tokenizer, token); - name = token; - token = tokenizer.requireToken(); - if ("=".equals(token)) { - token = tokenizer.requireToken(false); - val = token; - token = tokenizer.requireToken(); - } - if (!";".equals(token)) { - throw new ApiParseException("expected ; found " + token, tokenizer.getLine()); - } - - if (isEnum) { - state.addField(name); - } else { - state.addField(name); - } - } - - private static void parseParameterList(Tokenizer tokenizer, ParserState state, - String token) throws ApiParseException { - while (true) { - if (")".equals(token)) { - return; - } - - String type = token; - String name = null; - token = tokenizer.requireToken(); - if (isIdent(token)) { - name = token; - token = tokenizer.requireToken(); - } - if (",".equals(token)) { - token = tokenizer.requireToken(); - } else if (")".equals(token)) { - } else { - throw new ApiParseException("expected , found " + token, tokenizer.getLine()); - } - state.addMethodParameter(type); -// method.addParameter(new ParameterInfo(name, type, Converter.obtainTypeFromString(type), -// type.endsWith("..."), tokenizer.pos())); - } - } - - private static String parseThrows(Tokenizer tokenizer, ParserState state) - throws ApiParseException { - String token = tokenizer.requireToken(); - boolean comma = true; - while (true) { - if (";".equals(token)) { - return token; - } else if (",".equals(token)) { - if (comma) { - throw new ApiParseException("Expected exception, got ','", tokenizer.getLine()); - } - comma = true; - } else { - if (!comma) { - throw new ApiParseException("Expected ',' or ';' got " + token, - tokenizer.getLine()); - } - comma = false; - } - token = tokenizer.requireToken(); - } - } - -// private static String qualifiedName(String pkg, String className, ClassInfo parent) { -// String parentQName = (parent != null) ? (parent.qualifiedName() + ".") : ""; -// return pkg + "." + parentQName + className; -// } - - private static boolean isIdent(String token) { - return isident(token.charAt(0)); - } - - private static void assertIdent(Tokenizer tokenizer, String token) throws ApiParseException { - if (!isident(token.charAt(0))) { - throw new ApiParseException("Expected identifier: " + token, tokenizer.getLine()); - } - } - - static class Tokenizer { - char[] mBuf; - - String mFilename; - - int mPos; - - int mLine = 1; - - Tokenizer(String filename, char[] buf) { - mFilename = filename; - mBuf = buf; - } - - public int getLine() { - return mLine; - } - - boolean eatWhitespace() { - boolean ate = false; - while (mPos < mBuf.length && isspace(mBuf[mPos])) { - if (mBuf[mPos] == '\n') { - mLine++; - } - mPos++; - ate = true; - } - return ate; - } - - boolean eatComment() { - if (mPos + 1 < mBuf.length) { - if (mBuf[mPos] == '/' && mBuf[mPos + 1] == '/') { - mPos += 2; - while (mPos < mBuf.length && !isnewline(mBuf[mPos])) { - mPos++; - } - return true; - } - } - return false; - } - - void eatWhitespaceAndComments() { - while (eatWhitespace() || eatComment()) { - } - } - - public String requireToken() throws ApiParseException { - return requireToken(true); - } - - public String requireToken(boolean parenIsSep) throws ApiParseException { - final String token = getToken(parenIsSep); - if (token != null) { - return token; - } else { - throw new ApiParseException("Unexpected end of file", mLine); - } - } - - public String getToken() throws ApiParseException { - return getToken(true); - } - - public String getToken(boolean parenIsSep) throws ApiParseException { - eatWhitespaceAndComments(); - if (mPos >= mBuf.length) { - return null; - } - final int line = mLine; - final char c = mBuf[mPos]; - final int start = mPos; - mPos++; - if (c == '"') { - final int STATE_BEGIN = 0; - final int STATE_ESCAPE = 1; - int state = STATE_BEGIN; - while (true) { - if (mPos >= mBuf.length) { - throw new ApiParseException("Unexpected end of file for \" starting at " - + line, mLine); - } - final char k = mBuf[mPos]; - if (k == '\n' || k == '\r') { - throw new ApiParseException( - "Unexpected newline for \" starting at " + line, mLine); - } - mPos++; - switch (state) { - case STATE_BEGIN: - switch (k) { - case '\\': - state = STATE_ESCAPE; - mPos++; - break; - case '"': - return new String(mBuf, start, mPos - start); - } - case STATE_ESCAPE: - state = STATE_BEGIN; - break; - } - } - } else if (issep(c, parenIsSep)) { - return "" + c; - } else { - int genericDepth = 0; - do { - while (mPos < mBuf.length && !isspace(mBuf[mPos]) - && !issep(mBuf[mPos], parenIsSep)) { - mPos++; - } - if (mPos < mBuf.length) { - if (mBuf[mPos] == '<') { - genericDepth++; - mPos++; - } else if (mBuf[mPos] == '>') { - genericDepth--; - mPos++; - } else if (genericDepth != 0) { - mPos++; - } - } - } while (mPos < mBuf.length - && ((!isspace(mBuf[mPos]) && !issep(mBuf[mPos], parenIsSep)) || genericDepth != 0)); - if (mPos >= mBuf.length) { - throw new ApiParseException( - "Unexpected end of file for \" starting at " + line, mLine); - } - return new String(mBuf, start, mPos - start); - } - } - } - - static boolean isspace(char c) { - return c == ' ' || c == '\t' || c == '\n' || c == '\r'; - } - - static boolean isnewline(char c) { - return c == '\n' || c == '\r'; - } - - static boolean issep(char c, boolean parenIsSep) { - if (parenIsSep) { - if (c == '(' || c == ')') { - return true; - } - } - return c == '{' || c == '}' || c == ',' || c == ';' || c == '<' || c == '>'; - } - - static boolean isident(char c) { - if (c == '"' || issep(c, true)) { - return false; - } - return true; - } -} diff --git a/apigenerator/src/com/android/apigenerator/ParserState.java b/apigenerator/src/com/android/apigenerator/ParserState.java deleted file mode 100644 index 7ffb57a..0000000 --- a/apigenerator/src/com/android/apigenerator/ParserState.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2012 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.apigenerator; - -import java.util.Map; - -/** - * Parser state used during parsing of the platform API files. - * - */ -class ParserState { - - private final int mApiLevel; - - private final Map<String, ApiClass> mClasses; - - private String mCurrentPackage; - private ApiClass mCurrentClass; - - private String mMethodName; - private StringBuilder mMethodParams = new StringBuilder(); - private String mMethodReturnType; - - ParserState(Map<String, ApiClass> classes, int apiLevel) { - mClasses = classes; - mApiLevel = apiLevel; - } - - Map<String, ApiClass> getClasses() { - return mClasses; - } - - void addPackage(String packageName) { - mCurrentPackage = packageName; - } - - void addClass(String className) { - String fqcn = makeJavaClass(mCurrentPackage + "." + className); - mCurrentClass = addClass(fqcn, mApiLevel); - } - - void addSuperClass(String superClass) { - mCurrentClass.addSuperClass(makeJavaClass(superClass), mApiLevel); - } - - void addInterface(String interfaceClass) { - mCurrentClass.addInterface(makeJavaClass(interfaceClass), mApiLevel); - } - - void startNewConstructor() { - mMethodParams.setLength(0); - mMethodName = "<init>"; - mMethodReturnType = "V"; - } - - void startNewMethod(String name, String returnType) { - mMethodParams.setLength(0); - mMethodName = name; - mMethodReturnType = parseType(returnType); - } - - void addMethodParameter(String parameter) { - mMethodParams.append(parseType(parameter)); - } - - void finishMethod() { - addMethod(mMethodName + "(" + mMethodParams.toString() + ")" + - (mMethodReturnType != null ? mMethodReturnType : "")); - } - - void addMethod(String methodSignature) { - mCurrentClass.addMethod(methodSignature, mApiLevel); - } - - void addField(String fieldName) { - mCurrentClass.addField(fieldName, mApiLevel); - } - - void finishClass() { - mCurrentClass = null; - } - - void finishPackage() { - finishClass(); - mCurrentPackage = null; - } - - void done() { - finishPackage(); - } - - private ApiClass addClass(String name, int apiLevel) { - ApiClass theClass = mClasses.get(name); - if (theClass == null) { - theClass = new ApiClass(name, apiLevel); - mClasses.put(name, theClass); - } - - return theClass; - } - - - private String makeJavaClass(String fqcn) { - final int length = fqcn.length(); - - StringBuilder sb = new StringBuilder(length); - - boolean isClass = Character.isUpperCase(fqcn.charAt(0)); - for (int i = 0 ; i < length ; i++) { - if (fqcn.charAt(i) == '.') { - if (isClass) { - sb.append('$'); - } else { - sb.append('/'); - } - - if (i < length -1 ) { - isClass = Character.isUpperCase(fqcn.charAt(i+1)); - } - } else { - if (fqcn.charAt(i) == '<') { - break; - } - - sb.append(fqcn.charAt(i)); - } - } - - return sb.toString(); - } - - private String parseType(String type) { - StringBuilder result = new StringBuilder(); - - if (type.endsWith("...")) { - result.append('['); - type = type.substring(0, type.length() - 3); - } - - while (type.endsWith("[]")) { - result.append('['); - type = type.substring(0, type.length() - 2); - } - - if ("byte".equals(type)) result.append('B'); - else if ("char".equals(type)) result.append('C'); - else if ("double".equals(type)) result.append('D'); - else if ("float".equals(type)) result.append('F'); - else if ("int".equals(type)) result.append('I'); - else if ("long".equals(type)) result.append('J'); - else if ("short".equals(type)) result.append('S'); - else if ("void".equals(type)) result.append('V'); - else if ("boolean".equals(type)) result.append('Z'); - else { - result.append('L').append(makeJavaClass(type)).append(';'); - } - - return result.toString(); - } -} diff --git a/apigenerator/src/com/android/apigenerator/XmlApiParser.java b/apigenerator/src/com/android/apigenerator/XmlApiParser.java deleted file mode 100644 index 840272c..0000000 --- a/apigenerator/src/com/android/apigenerator/XmlApiParser.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2012 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.apigenerator; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -import java.util.Map; - -/** - * Parser for the old, XML-based format of platform API files. - */ -class XmlApiParser extends DefaultHandler { - - private final static String NODE_API = "api"; - private final static String NODE_PACKAGE = "package"; - private final static String NODE_CLASS = "class"; - private final static String NODE_INTERFACE = "interface"; - private final static String NODE_IMPLEMENTS = "implements"; - private final static String NODE_FIELD = "field"; - private final static String NODE_CONSTRUCTOR = "constructor"; - private final static String NODE_METHOD = "method"; - private final static String NODE_PARAMETER = "parameter"; - - private final static String ATTR_NAME = "name"; - private final static String ATTR_TYPE = "type"; - private final static String ATTR_RETURN = "return"; - private final static String ATTR_EXTENDS = "extends"; - - private final ParserState mParserState; - - XmlApiParser(Map<String, ApiClass> map, int apiLevel) { - mParserState = new ParserState(map, apiLevel); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) - throws SAXException { - - if (localName == null || localName.length() == 0) { - localName = qName; - } - - try { - - if (NODE_API.equals(localName)) { - } else if (NODE_PACKAGE.equals(localName)) { - mParserState.addPackage(attributes.getValue(ATTR_NAME)); - - } else if (NODE_CLASS.equals(localName) || NODE_INTERFACE.equals(localName)) { - mParserState.addClass(attributes.getValue(ATTR_NAME)); - - String extendsAttr = attributes.getValue(ATTR_EXTENDS); - if (extendsAttr != null) { - mParserState.addSuperClass(extendsAttr); - } - - } else if (NODE_IMPLEMENTS.equals(localName)) { - mParserState.addInterface(attributes.getValue(ATTR_NAME)); - - } else if (NODE_FIELD.equals(localName)) { - mParserState.addField(attributes.getValue(ATTR_NAME)); - - } else if (NODE_CONSTRUCTOR.equals(localName)) { - parseConstructor(attributes); - - } else if (NODE_METHOD.equals(localName)) { - parseMethod(attributes); - - } else if (NODE_PARAMETER.equals(localName)) { - parseParameter(attributes); - } - - } finally { - super.startElement(uri, localName, qName, attributes); - } - } - - private void parseConstructor(Attributes attributes) { - mParserState.startNewConstructor(); - } - - private void parseMethod(Attributes attributes) { - mParserState.startNewMethod(attributes.getValue(ATTR_NAME), - attributes.getValue(ATTR_RETURN)); - } - - private void parseParameter(Attributes attributes) { - mParserState.addMethodParameter(attributes.getValue(ATTR_TYPE)); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - if (localName == null || localName.length() == 0) { - localName = qName; - } - - try { - - if (NODE_METHOD.equals(localName) || NODE_CONSTRUCTOR.equals(localName)) { - mParserState.finishMethod(); - - } else if (NODE_API.equals(localName)) { - mParserState.done(); - } - - } finally { - super.endElement(uri, localName, qName); - } - } -}
\ No newline at end of file diff --git a/apigenerator/src/com/android/apigenerator/enumfix/AndroidJarReader.java b/apigenerator/src/com/android/apigenerator/enumfix/AndroidJarReader.java deleted file mode 100644 index 7669786..0000000 --- a/apigenerator/src/com/android/apigenerator/enumfix/AndroidJarReader.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2012 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.apigenerator.enumfix; - -import com.android.apigenerator.ApiClass; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.FieldNode; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * This codes looks at all the android.jar in an SDK and use ASM to figure out when enums - * where introduced. This is a one time thing that creates the file - * /com/android/apichecker/generator/enums.xml which is then used to create the final API file. - * - */ -public class AndroidJarReader { - - // this the last API until we switched to a new API format that included enum values. - private final static int MAX_API = 13; - private static final byte[] BUFFER = new byte[65535]; - - private final String mSdkFolder; - - public AndroidJarReader(String sdkFolder) { - mSdkFolder = sdkFolder; - } - - public Map<String, ApiClass> getEnumClasses() { - HashMap<String, ApiClass> map = new HashMap<String, ApiClass>(); - - // Get all the android.jar. They are in platforms-# - for (int apiLevel = 1 ; apiLevel <= MAX_API ; apiLevel++) { - try { - File jar = new File(mSdkFolder, "platforms/android-" + apiLevel + "/android.jar"); - if (jar.exists() == false) { - System.err.println("Missing android.jar for API level " + apiLevel); - continue; - } - - FileInputStream fis = new FileInputStream(jar); - ZipInputStream zis = new ZipInputStream(fis); - ZipEntry entry = zis.getNextEntry(); - while (entry != null) { - String name = entry.getName(); - - if (name.endsWith(".class")) { - - int index = 0; - do { - int size = zis.read(BUFFER, index, BUFFER.length - index); - if (size >= 0) { - index += size; - } else { - break; - } - } while (true); - - byte[] b = new byte[index]; - System.arraycopy(BUFFER, 0, b, 0, index); - - ClassReader reader = new ClassReader(b); - ClassNode classNode = new ClassNode(); - reader.accept(classNode, 0 /*flags*/); - - if (classNode != null && classNode.superName != null && - classNode.superName.equals("java/lang/Enum")) { - - ApiClass theClass = addClass(map, classNode.name, apiLevel); - theClass.addSuperClass("java/lang/Enum", apiLevel); - - List fields = classNode.fields; - for (Object f : fields) { - FieldNode fnode = (FieldNode) f; - if (fnode.desc.substring(1, fnode.desc.length() - 1).equals(classNode.name)) { - theClass.addField(fnode.name, apiLevel); - } - } - } - } - entry = zis.getNextEntry(); - } - } catch (MalformedURLException e) { - e.printStackTrace(); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - - } - } - - return map; - } - - private ApiClass addClass(HashMap<String, ApiClass> classes, String name, int apiLevel) { - ApiClass theClass = classes.get(name); - if (theClass == null) { - theClass = new ApiClass(name, apiLevel); - classes.put(name, theClass); - } - - return theClass; - } - -} diff --git a/apigenerator/src/com/android/apigenerator/enums.xml b/apigenerator/src/com/android/apigenerator/enums.xml deleted file mode 100644 index 54a2a21..0000000 --- a/apigenerator/src/com/android/apigenerator/enums.xml +++ /dev/null @@ -1,596 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<api version="1"> - <class name="android/database/CursorJoiner$Result" since="1"> - <extends name="java/lang/Enum" /> - <field name="BOTH" /> - <field name="LEFT" /> - <field name="RIGHT" /> - </class> - <class name="android/graphics/AvoidXfermode$Mode" since="1"> - <extends name="java/lang/Enum" /> - <field name="AVOID" /> - <field name="TARGET" /> - </class> - <class name="android/graphics/Bitmap$CompressFormat" since="1"> - <extends name="java/lang/Enum" /> - <field name="JPEG" /> - <field name="PNG" /> - </class> - <class name="android/graphics/Bitmap$Config" since="1"> - <extends name="java/lang/Enum" /> - <field name="ALPHA_8" /> - <field name="ARGB_4444" /> - <field name="ARGB_8888" /> - <field name="RGB_565" /> - </class> - <class name="android/graphics/BlurMaskFilter$Blur" since="1"> - <extends name="java/lang/Enum" /> - <field name="INNER" /> - <field name="NORMAL" /> - <field name="OUTER" /> - <field name="SOLID" /> - </class> - <class name="android/graphics/Canvas$EdgeType" since="1"> - <extends name="java/lang/Enum" /> - <field name="AA" /> - <field name="BW" /> - </class> - <class name="android/graphics/Canvas$VertexMode" since="1"> - <extends name="java/lang/Enum" /> - <field name="TRIANGLES" /> - <field name="TRIANGLE_FAN" /> - <field name="TRIANGLE_STRIP" /> - </class> - <class name="android/graphics/Interpolator$Result" since="1"> - <extends name="java/lang/Enum" /> - <field name="FREEZE_END" /> - <field name="FREEZE_START" /> - <field name="NORMAL" /> - </class> - <class name="android/graphics/Matrix$ScaleToFit" since="1"> - <extends name="java/lang/Enum" /> - <field name="CENTER" /> - <field name="END" /> - <field name="FILL" /> - <field name="START" /> - </class> - <class name="android/graphics/Paint$Align" since="1"> - <extends name="java/lang/Enum" /> - <field name="CENTER" /> - <field name="LEFT" /> - <field name="RIGHT" /> - </class> - <class name="android/graphics/Paint$Cap" since="1"> - <extends name="java/lang/Enum" /> - <field name="BUTT" /> - <field name="ROUND" /> - <field name="SQUARE" /> - </class> - <class name="android/graphics/Paint$Join" since="1"> - <extends name="java/lang/Enum" /> - <field name="BEVEL" /> - <field name="MITER" /> - <field name="ROUND" /> - </class> - <class name="android/graphics/Paint$Style" since="1"> - <extends name="java/lang/Enum" /> - <field name="FILL" /> - <field name="FILL_AND_STROKE" /> - <field name="STROKE" /> - </class> - <class name="android/graphics/Path$Direction" since="1"> - <extends name="java/lang/Enum" /> - <field name="CCW" /> - <field name="CW" /> - </class> - <class name="android/graphics/Path$FillType" since="1"> - <extends name="java/lang/Enum" /> - <field name="EVEN_ODD" /> - <field name="INVERSE_EVEN_ODD" /> - <field name="INVERSE_WINDING" /> - <field name="WINDING" /> - </class> - <class name="android/graphics/PathDashPathEffect$Style" since="1"> - <extends name="java/lang/Enum" /> - <field name="MORPH" /> - <field name="ROTATE" /> - <field name="TRANSLATE" /> - </class> - <class name="android/graphics/PorterDuff$Mode" since="1"> - <extends name="java/lang/Enum" /> - <field name="ADD" since="11" /> - <field name="CLEAR" /> - <field name="DARKEN" /> - <field name="DST" /> - <field name="DST_ATOP" /> - <field name="DST_IN" /> - <field name="DST_OUT" /> - <field name="DST_OVER" /> - <field name="LIGHTEN" /> - <field name="MULTIPLY" /> - <field name="OVERLAY" since="11" /> - <field name="SCREEN" /> - <field name="SRC" /> - <field name="SRC_ATOP" /> - <field name="SRC_IN" /> - <field name="SRC_OUT" /> - <field name="SRC_OVER" /> - <field name="XOR" /> - </class> - <class name="android/graphics/Region$Op" since="1"> - <extends name="java/lang/Enum" /> - <field name="DIFFERENCE" /> - <field name="INTERSECT" /> - <field name="REPLACE" /> - <field name="REVERSE_DIFFERENCE" /> - <field name="UNION" /> - <field name="XOR" /> - </class> - <class name="android/graphics/Shader$TileMode" since="1"> - <extends name="java/lang/Enum" /> - <field name="CLAMP" /> - <field name="MIRROR" /> - <field name="REPEAT" /> - </class> - <class name="android/graphics/drawable/GradientDrawable$Orientation" since="1"> - <extends name="java/lang/Enum" /> - <field name="BL_TR" /> - <field name="BOTTOM_TOP" /> - <field name="BR_TL" /> - <field name="LEFT_RIGHT" /> - <field name="RIGHT_LEFT" /> - <field name="TL_BR" /> - <field name="TOP_BOTTOM" /> - <field name="TR_BL" /> - </class> - <class name="android/net/LocalSocketAddress$Namespace" since="1"> - <extends name="java/lang/Enum" /> - <field name="ABSTRACT" /> - <field name="FILESYSTEM" /> - <field name="RESERVED" /> - </class> - <class name="android/net/NetworkInfo$DetailedState" since="1"> - <extends name="java/lang/Enum" /> - <field name="AUTHENTICATING" /> - <field name="CONNECTED" /> - <field name="CONNECTING" /> - <field name="DISCONNECTED" /> - <field name="DISCONNECTING" /> - <field name="FAILED" /> - <field name="IDLE" /> - <field name="OBTAINING_IPADDR" /> - <field name="SCANNING" /> - <field name="SUSPENDED" /> - </class> - <class name="android/net/NetworkInfo$State" since="1"> - <extends name="java/lang/Enum" /> - <field name="CONNECTED" /> - <field name="CONNECTING" /> - <field name="DISCONNECTED" /> - <field name="DISCONNECTING" /> - <field name="SUSPENDED" /> - <field name="UNKNOWN" /> - </class> - <class name="android/net/wifi/SupplicantState" since="1"> - <extends name="java/lang/Enum" /> - <field name="ASSOCIATED" /> - <field name="ASSOCIATING" /> - <field name="COMPLETED" /> - <field name="DISCONNECTED" /> - <field name="DORMANT" /> - <field name="FOUR_WAY_HANDSHAKE" /> - <field name="GROUP_HANDSHAKE" /> - <field name="INACTIVE" /> - <field name="INVALID" /> - <field name="SCANNING" /> - <field name="UNINITIALIZED" /> - </class> - <class name="android/os/AsyncTask$Status" since="3"> - <extends name="java/lang/Enum" /> - <field name="FINISHED" /> - <field name="PENDING" /> - <field name="RUNNING" /> - </class> - <class name="android/renderscript/Allocation$MipmapControl" since="11"> - <extends name="java/lang/Enum" /> - <field name="MIPMAP_FULL" /> - <field name="MIPMAP_NONE" /> - <field name="MIPMAP_ON_SYNC_TO_TEXTURE" /> - </class> - <class name="android/renderscript/Element$DataKind" since="11"> - <extends name="java/lang/Enum" /> - <field name="PIXEL_A" /> - <field name="PIXEL_L" /> - <field name="PIXEL_LA" /> - <field name="PIXEL_RGB" /> - <field name="PIXEL_RGBA" /> - <field name="USER" /> - </class> - <class name="android/renderscript/Element$DataType" since="11"> - <extends name="java/lang/Enum" /> - <field name="BOOLEAN" /> - <field name="FLOAT_32" /> - <field name="FLOAT_64" /> - <field name="MATRIX_2X2" /> - <field name="MATRIX_3X3" /> - <field name="MATRIX_4X4" /> - <field name="RS_ALLOCATION" /> - <field name="RS_ELEMENT" /> - <field name="RS_MESH" /> - <field name="RS_PROGRAM_FRAGMENT" /> - <field name="RS_PROGRAM_RASTER" /> - <field name="RS_PROGRAM_STORE" /> - <field name="RS_PROGRAM_VERTEX" /> - <field name="RS_SAMPLER" /> - <field name="RS_SCRIPT" /> - <field name="RS_TYPE" /> - <field name="SIGNED_16" /> - <field name="SIGNED_32" /> - <field name="SIGNED_64" /> - <field name="SIGNED_8" /> - <field name="UNSIGNED_16" /> - <field name="UNSIGNED_32" /> - <field name="UNSIGNED_4_4_4_4" /> - <field name="UNSIGNED_5_5_5_1" /> - <field name="UNSIGNED_5_6_5" /> - <field name="UNSIGNED_64" /> - <field name="UNSIGNED_8" /> - </class> - <class name="android/renderscript/FileA3D$EntryType" since="11"> - <extends name="java/lang/Enum" /> - <field name="MESH" /> - <field name="UNKNOWN" /> - </class> - <class name="android/renderscript/Font$Style" since="11"> - <extends name="java/lang/Enum" /> - <field name="BOLD" /> - <field name="BOLD_ITALIC" /> - <field name="ITALIC" /> - <field name="NORMAL" /> - </class> - <class name="android/renderscript/Mesh$Primitive" since="11"> - <extends name="java/lang/Enum" /> - <field name="LINE" /> - <field name="LINE_STRIP" /> - <field name="POINT" /> - <field name="TRIANGLE" /> - <field name="TRIANGLE_FAN" /> - <field name="TRIANGLE_STRIP" /> - </class> - <class name="android/renderscript/Program$TextureType" since="11"> - <extends name="java/lang/Enum" /> - <field name="TEXTURE_2D" /> - <field name="TEXTURE_CUBE" /> - </class> - <class name="android/renderscript/ProgramFragmentFixedFunction$Builder$EnvMode" since="11"> - <extends name="java/lang/Enum" /> - <field name="DECAL" /> - <field name="MODULATE" /> - <field name="REPLACE" /> - </class> - <class name="android/renderscript/ProgramFragmentFixedFunction$Builder$Format" since="11"> - <extends name="java/lang/Enum" /> - <field name="ALPHA" /> - <field name="LUMINANCE_ALPHA" /> - <field name="RGB" /> - <field name="RGBA" /> - </class> - <class name="android/renderscript/ProgramRaster$CullMode" since="11"> - <extends name="java/lang/Enum" /> - <field name="BACK" /> - <field name="FRONT" /> - <field name="NONE" /> - </class> - <class name="android/renderscript/ProgramStore$BlendDstFunc" since="11"> - <extends name="java/lang/Enum" /> - <field name="DST_ALPHA" /> - <field name="ONE" /> - <field name="ONE_MINUS_DST_ALPHA" /> - <field name="ONE_MINUS_SRC_ALPHA" /> - <field name="ONE_MINUS_SRC_COLOR" /> - <field name="SRC_ALPHA" /> - <field name="SRC_COLOR" /> - <field name="ZERO" /> - </class> - <class name="android/renderscript/ProgramStore$BlendSrcFunc" since="11"> - <extends name="java/lang/Enum" /> - <field name="DST_ALPHA" /> - <field name="DST_COLOR" /> - <field name="ONE" /> - <field name="ONE_MINUS_DST_ALPHA" /> - <field name="ONE_MINUS_DST_COLOR" /> - <field name="ONE_MINUS_SRC_ALPHA" /> - <field name="SRC_ALPHA" /> - <field name="SRC_ALPHA_SATURATE" /> - <field name="ZERO" /> - </class> - <class name="android/renderscript/ProgramStore$DepthFunc" since="11"> - <extends name="java/lang/Enum" /> - <field name="ALWAYS" /> - <field name="EQUAL" /> - <field name="GREATER" /> - <field name="GREATER_OR_EQUAL" /> - <field name="LESS" /> - <field name="LESS_OR_EQUAL" /> - <field name="NOT_EQUAL" /> - </class> - <class name="android/renderscript/RenderScript$Priority" since="11"> - <extends name="java/lang/Enum" /> - <field name="LOW" /> - <field name="NORMAL" /> - </class> - <class name="android/renderscript/Sampler$Value" since="11"> - <extends name="java/lang/Enum" /> - <field name="CLAMP" /> - <field name="LINEAR" /> - <field name="LINEAR_MIP_LINEAR" /> - <field name="LINEAR_MIP_NEAREST" /> - <field name="NEAREST" /> - <field name="WRAP" /> - </class> - <class name="android/renderscript/Type$CubemapFace" since="11"> - <extends name="java/lang/Enum" /> - <field name="NEGATIVE_X" /> - <field name="NEGATIVE_Y" /> - <field name="NEGATIVE_Z" /> - <field name="POSITVE_X" /> - <field name="POSITVE_Y" /> - <field name="POSITVE_Z" /> - </class> - <class name="android/telephony/SmsMessage$MessageClass" since="4"> - <extends name="java/lang/Enum" /> - <field name="CLASS_0" /> - <field name="CLASS_1" /> - <field name="CLASS_2" /> - <field name="CLASS_3" /> - <field name="UNKNOWN" /> - </class> - <class name="android/telephony/gsm/SmsMessage$MessageClass" since="1"> - <extends name="java/lang/Enum" /> - <field name="CLASS_0" /> - <field name="CLASS_1" /> - <field name="CLASS_2" /> - <field name="CLASS_3" /> - <field name="UNKNOWN" /> - </class> - <class name="android/text/Layout$Alignment" since="1"> - <extends name="java/lang/Enum" /> - <field name="ALIGN_CENTER" /> - <field name="ALIGN_NORMAL" /> - <field name="ALIGN_OPPOSITE" /> - </class> - <class name="android/text/TextUtils$TruncateAt" since="1"> - <extends name="java/lang/Enum" /> - <field name="END" /> - <field name="MARQUEE" since="2" /> - <field name="MIDDLE" /> - <field name="START" /> - </class> - <class name="android/text/method/TextKeyListener$Capitalize" since="1"> - <extends name="java/lang/Enum" /> - <field name="CHARACTERS" /> - <field name="NONE" /> - <field name="SENTENCES" /> - <field name="WORDS" /> - </class> - <class name="android/util/JsonToken" since="11"> - <extends name="java/lang/Enum" /> - <field name="BEGIN_ARRAY" /> - <field name="BEGIN_OBJECT" /> - <field name="BOOLEAN" /> - <field name="END_ARRAY" /> - <field name="END_DOCUMENT" /> - <field name="END_OBJECT" /> - <field name="NAME" /> - <field name="NULL" /> - <field name="NUMBER" /> - <field name="STRING" /> - </class> - <class name="android/util/Xml$Encoding" since="1"> - <extends name="java/lang/Enum" /> - <field name="ISO_8859_1" /> - <field name="US_ASCII" /> - <field name="UTF_16" /> - <field name="UTF_8" /> - </class> - <class name="android/view/ViewDebug$HierarchyTraceType" since="1"> - <extends name="java/lang/Enum" /> - <field name="BUILD_CACHE" /> - <field name="DRAW" /> - <field name="INVALIDATE" /> - <field name="INVALIDATE_CHILD" /> - <field name="INVALIDATE_CHILD_IN_PARENT" /> - <field name="ON_LAYOUT" /> - <field name="ON_MEASURE" /> - <field name="REQUEST_LAYOUT" /> - </class> - <class name="android/view/ViewDebug$RecyclerTraceType" since="1"> - <extends name="java/lang/Enum" /> - <field name="BIND_VIEW" /> - <field name="MOVE_FROM_ACTIVE_TO_SCRAP_HEAP" /> - <field name="MOVE_TO_ACTIVE_HEAP" /> - <field name="MOVE_TO_SCRAP_HEAP" /> - <field name="NEW_VIEW" /> - <field name="RECYCLE_FROM_ACTIVE_HEAP" /> - <field name="RECYCLE_FROM_SCRAP_HEAP" /> - </class> - <class name="android/webkit/ConsoleMessage$MessageLevel" since="8"> - <extends name="java/lang/Enum" /> - <field name="DEBUG" /> - <field name="ERROR" /> - <field name="LOG" /> - <field name="TIP" /> - <field name="WARNING" /> - </class> - <class name="android/webkit/WebSettings$LayoutAlgorithm" since="1"> - <extends name="java/lang/Enum" /> - <field name="NARROW_COLUMNS" /> - <field name="NORMAL" /> - <field name="SINGLE_COLUMN" /> - </class> - <class name="android/webkit/WebSettings$PluginState" since="8"> - <extends name="java/lang/Enum" /> - <field name="OFF" /> - <field name="ON" /> - <field name="ON_DEMAND" /> - </class> - <class name="android/webkit/WebSettings$RenderPriority" since="1"> - <extends name="java/lang/Enum" /> - <field name="HIGH" /> - <field name="LOW" /> - <field name="NORMAL" /> - </class> - <class name="android/webkit/WebSettings$TextSize" since="1"> - <extends name="java/lang/Enum" /> - <field name="LARGER" /> - <field name="LARGEST" /> - <field name="NORMAL" /> - <field name="SMALLER" /> - <field name="SMALLEST" /> - </class> - <class name="android/webkit/WebSettings$ZoomDensity" since="7"> - <extends name="java/lang/Enum" /> - <field name="CLOSE" /> - <field name="FAR" /> - <field name="MEDIUM" /> - </class> - <class name="android/widget/ImageView$ScaleType" since="1"> - <extends name="java/lang/Enum" /> - <field name="CENTER" /> - <field name="CENTER_CROP" /> - <field name="CENTER_INSIDE" /> - <field name="FIT_CENTER" /> - <field name="FIT_END" /> - <field name="FIT_START" /> - <field name="FIT_XY" /> - <field name="MATRIX" /> - </class> - <class name="android/widget/TextView$BufferType" since="1"> - <extends name="java/lang/Enum" /> - <field name="EDITABLE" /> - <field name="NORMAL" /> - <field name="SPANNABLE" /> - </class> - <class name="com/google/android/maps/MapView$ReticleDrawMode" since="1"> - <extends name="java/lang/Enum" /> - <field name="DRAW_RETICLE_NEVER" /> - <field name="DRAW_RETICLE_OVER" /> - <field name="DRAW_RETICLE_UNDER" /> - </class> - <class name="java/lang/Thread$State" since="1"> - <extends name="java/lang/Enum" /> - <field name="BLOCKED" /> - <field name="NEW" /> - <field name="RUNNABLE" /> - <field name="TERMINATED" /> - <field name="TIMED_WAITING" /> - <field name="WAITING" /> - </class> - <class name="java/lang/annotation/ElementType" since="1"> - <extends name="java/lang/Enum" /> - <field name="ANNOTATION_TYPE" /> - <field name="CONSTRUCTOR" /> - <field name="FIELD" /> - <field name="LOCAL_VARIABLE" /> - <field name="METHOD" /> - <field name="PACKAGE" /> - <field name="PARAMETER" /> - <field name="TYPE" /> - </class> - <class name="java/lang/annotation/RetentionPolicy" since="1"> - <extends name="java/lang/Enum" /> - <field name="CLASS" /> - <field name="RUNTIME" /> - <field name="SOURCE" /> - </class> - <class name="java/math/RoundingMode" since="1"> - <extends name="java/lang/Enum" /> - <field name="CEILING" /> - <field name="DOWN" /> - <field name="FLOOR" /> - <field name="HALF_DOWN" /> - <field name="HALF_EVEN" /> - <field name="HALF_UP" /> - <field name="UNNECESSARY" /> - <field name="UP" /> - </class> - <class name="java/net/Authenticator$RequestorType" since="1"> - <extends name="java/lang/Enum" /> - <field name="PROXY" /> - <field name="SERVER" /> - </class> - <class name="java/net/Proxy$Type" since="1"> - <extends name="java/lang/Enum" /> - <field name="DIRECT" /> - <field name="HTTP" /> - <field name="SOCKS" /> - </class> - <class name="java/security/KeyRep$Type" since="1"> - <extends name="java/lang/Enum" /> - <field name="PRIVATE" /> - <field name="PUBLIC" /> - <field name="SECRET" /> - </class> - <class name="java/sql/ClientInfoStatus" since="9"> - <extends name="java/lang/Enum" /> - <field name="REASON_UNKNOWN" /> - <field name="REASON_UNKNOWN_PROPERTY" /> - <field name="REASON_VALUE_INVALID" /> - <field name="REASON_VALUE_TRUNCATED" /> - </class> - <class name="java/sql/RowIdLifetime" since="9"> - <extends name="java/lang/Enum" /> - <field name="ROWID_UNSUPPORTED" /> - <field name="ROWID_VALID_FOREVER" /> - <field name="ROWID_VALID_OTHER" /> - <field name="ROWID_VALID_SESSION" /> - <field name="ROWID_VALID_TRANSACTION" /> - </class> - <class name="java/text/Normalizer$Form" since="9"> - <extends name="java/lang/Enum" /> - <field name="NFC" /> - <field name="NFD" /> - <field name="NFKC" /> - <field name="NFKD" /> - </class> - <class name="java/util/Formatter$BigDecimalLayoutForm" since="1"> - <extends name="java/lang/Enum" /> - <field name="DECIMAL_FLOAT" /> - <field name="SCIENTIFIC" /> - </class> - <class name="java/util/concurrent/TimeUnit" since="1"> - <extends name="java/lang/Enum" /> - <field name="DAYS" since="9" /> - <field name="HOURS" since="9" /> - <field name="MICROSECONDS" /> - <field name="MILLISECONDS" /> - <field name="MINUTES" since="9" /> - <field name="NANOSECONDS" /> - <field name="SECONDS" /> - </class> - <class name="javax/net/ssl/SSLEngineResult$HandshakeStatus" since="1"> - <extends name="java/lang/Enum" /> - <field name="FINISHED" /> - <field name="NEED_TASK" /> - <field name="NEED_UNWRAP" /> - <field name="NEED_WRAP" /> - <field name="NOT_HANDSHAKING" /> - </class> - <class name="javax/net/ssl/SSLEngineResult$Status" since="1"> - <extends name="java/lang/Enum" /> - <field name="BUFFER_OVERFLOW" /> - <field name="BUFFER_UNDERFLOW" /> - <field name="CLOSED" /> - <field name="OK" /> - </class> - <class name="org/apache/http/conn/routing/RouteInfo$LayerType" since="1"> - <extends name="java/lang/Enum" /> - <field name="LAYERED" /> - <field name="PLAIN" /> - </class> - <class name="org/apache/http/conn/routing/RouteInfo$TunnelType" since="1"> - <extends name="java/lang/Enum" /> - <field name="PLAIN" /> - <field name="TUNNELLED" /> - </class> -</api> |