ApkCheck.rar

  • PUDN用户
    了解作者
  • Unix_Linux
    开发工具
  • 5KB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • 1 积分
    下载积分
  • 1
    下载次数
  • 2014-08-21 14:40
    上传日期
Checks an APK s dependencies against the published API specification.
ApkCheck.rar
  • define.h
    7.9KB
  • ApkCheck.c
    14.9KB
内容介绍
package com.android.apkcheck; import org.xml.sax.*; import org.xml.sax.helpers.*; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; /** * Checks an APK's dependencies against the published API specification. * * We need to read two XML files (spec and APK) and perform some operations * on the elements. The file formats are similar but not identical, so * we distill it down to common elements. * * We may also want to read some additional API lists representing * libraries that would be included with a "uses-library" directive. * * For performance we want to allow processing of multiple APKs so * we don't have to re-parse the spec file each time. */ public class ApkCheck { /* keep track of current APK file name, for error messages */ private static ApiList sCurrentApk; /* show warnings? */ private static boolean sShowWarnings = false; /* show errors? */ private static boolean sShowErrors = true; /* names of packages we're allowed to ignore */ private static HashSet<String> sIgnorablePackages = new HashSet<String>(); /** * Program entry point. */ public static void main(String[] args) { ApiList apiDescr = new ApiList("public-api"); if (args.length < 2) { usage(); return; } /* process args */ int idx; for (idx = 0; idx < args.length; idx++) { if (args[idx].equals("--help")) { usage(); return; } else if (args[idx].startsWith("--uses-library=")) { String libName = args[idx].substring(args[idx].indexOf('=')+1); if ("BUILTIN".equals(libName)) { Reader reader = Builtin.getReader(); if (!parseXml(apiDescr, reader, "BUILTIN")) return; } else { if (!parseApiDescr(apiDescr, libName)) return; } } else if (args[idx].startsWith("--ignore-package=")) { String pkgName = args[idx].substring(args[idx].indexOf('=')+1); sIgnorablePackages.add(pkgName); } else if (args[idx].equals("--warn")) { sShowWarnings = true; } else if (args[idx].equals("--no-warn")) { sShowWarnings = false; } else if (args[idx].equals("--error")) { sShowErrors = true; } else if (args[idx].equals("--no-error")) { sShowErrors = false; } else if (args[idx].startsWith("--")) { if (args[idx].equals("--")) { // remainder are filenames, even if they start with "--" idx++; break; } else { // unknown option specified System.err.println("ERROR: unknown option " + args[idx] + " (use \"--help\" for usage info)"); return; } } else { break; } } if (idx > args.length - 2) { usage(); return; } /* parse base API description */ if (!parseApiDescr(apiDescr, args[idx++])) return; /* "flatten" superclasses and interfaces */ sCurrentApk = apiDescr; flattenInherited(apiDescr); /* walk through list of libs we want to scan */ for ( ; idx < args.length; idx++) { ApiList apkDescr = new ApiList(args[idx]); sCurrentApk = apkDescr; boolean success = parseApiDescr(apkDescr, args[idx]); if (!success) { if (idx < args.length-1) System.err.println("Skipping..."); continue; } check(apiDescr, apkDescr); System.out.println(args[idx] + ": summary: " + apkDescr.getErrorCount() + " errors, " + apkDescr.getWarningCount() + " warnings\n"); } } /** * Prints usage statement. */ static void usage() { System.err.println("Android APK checker v1.0"); System.err.println("Copyright (C) 2010 The Android Open Source Project\n"); System.err.println("Usage: apkcheck [options] public-api.xml apk1.xml ...\n"); System.err.println("Options:"); System.err.println(" --help show this message"); System.err.println(" --uses-library=lib.xml load additional public API list"); System.err.println(" --ignore-package=pkg don't show errors for references to this package"); System.err.println(" --[no-]warn enable or disable display of warnings"); System.err.println(" --[no-]error enable or disable display of errors"); } /** * Opens the file and passes it to parseXml. * * TODO: allow '-' as an alias for stdin? */ static boolean parseApiDescr(ApiList apiList, String fileName) { boolean result = false; try { FileReader fileReader = new FileReader(fileName); result = parseXml(apiList, fileReader, fileName); fileReader.close(); } catch (IOException ioe) { System.err.println("Error opening " + fileName); } return result; } /** * Parses an XML file holding an API description. * * @param fileReader Data source. * @param apiList Container to add stuff to. * @param fileName Input file name, only used for debug messages. */ static boolean parseXml(ApiList apiList, Reader reader, String fileName) { //System.out.println("--- parsing " + fileName); try { XMLReader xmlReader = XMLReaderFactory.createXMLReader(); ApiDescrHandler handler = new ApiDescrHandler(apiList); xmlReader.setContentHandler(handler); xmlReader.setErrorHandler(handler); xmlReader.parse(new InputSource(reader)); //System.out.println("--- parsing complete"); //dumpApi(apiList); return true; } catch (SAXParseException ex) { System.err.println("Error parsing " + fileName + " line " + ex.getLineNumber() + ": " + ex.getMessage()); } catch (Exception ex) { System.err.println("Error while reading " + fileName + ": " + ex.getMessage()); ex.printStackTrace(); } // failed return false; } /** * Expands lists of fields and methods to recursively include superclass * and interface entries. * * The API description files have entries for every method a class * declares, even if it's present in the superclass (e.g. toString()). * Removal of one of these methods doesn't constitute an API change, * though, so if we don't find a method in a class we need to hunt * through its superclasses. * * We can walk up the hierarchy while analyzing the target APK, * or we can "flatten" the methods declared by the superclasses and * interfaces before we begin the analysis. Expanding up front can be * beneficial if we're analyzing lots of APKs in one go, but detrimental * to startup time if we just want to look at one small APK. * * It also means filling the field/method hash tables with lots of * entries that never get used, possibly worsening the hash table * hit rate. * * We only need to do this for the public API list. The dexdeps output * doesn't have this sort of information anyway. */ static void flattenInherited(ApiList pubList) { Iterator<PackageInfo> pkgIter = pubList.getPackageIterator(); while (pkgIter.has
评论
    相关推荐