1 Android APK Checker 2 3 This compares the set of classes, fields, and methods used by an Android 4 application against the published API. It identifies and reports the 5 use of any unpublished members or methods. 6 7 The public API description files live in the source tree, in 8 frameworks/base/api/. The tip-of-tree version is in "current.xml", 9 and each officially released API has a numbered file (e.g. "6.xml"). 10 They're generated from the sources, and can take into acount javadoc 11 annotations like "@hide" in comments. 12 13 The dependency set for an APK can be generated with "dexdeps". It finds 14 all classes, fields, and methods that are referenced by classes.dex but not 15 defined locally. The tool can't easily tell anything about a dependency 16 beyond the name (e.g. whether a class is a static or non-static inner 17 class), so while the output from dexdeps is similar in structure to the 18 API XML file, it has much less detail. 19 20 21 ==== Usage ==== 22 23 % apkcheck [options] public-api.xml apk1.xml ... 24 25 Provide the public API data file of choice, and one or more XML files 26 generated by dexdeps. The time required to parse and manipulate the 27 public API XML file is generally much larger than the time required to 28 analyze the APK, so if you have a large set of APKs it's best to run them 29 through in large batches. 30 31 Options: 32 33 --help 34 Show options summary. 35 36 --uses-library=<lib.xml> 37 Load additional public API list. This is intended for APKs that 38 use "uses-library" directives to pull in external libraries. Since 39 the external libraries are not part of the public API, their use 40 would otherwise be flagged as illegal by apkcheck. 41 42 --ignore-package=<package-name> 43 Ignore errors generated by references to the named package (e.g. 44 "com.google.android.maps"). Warnings will be generated instead. 45 Useful for ignoring references to shared library content when 46 XML API data is not available. 47 48 --[no-]warn 49 Enable or disable warning messages. These are disabled by default. 50 51 --[no-]error 52 Enable or disable error messages. These are enabled by default. If 53 you disable both warnings and errors you will only see a summary. 54 55 In some cases involving generic signatures it may not be possible 56 to accurately reconstruct the public API. Some popular cases have 57 been hard-coded into the program. They can be included by specifying 58 "--uses-library=BUILTIN". 59 60 Example use: 61 62 % dexdeps out/target/product/sapphire/system/app/Gmail.apk > Gmail.apk.xml 63 % apkcheck --uses-library=BUILTIN frameworks/base/api/current.xml Gmail.apk.xml 64 Gmail.apk.xml: summary: 0 errors, 15 warnings 65 66 67 ==== Limitations ==== 68 69 The API XML files have some ambiguous entries and are missing important 70 pieces. A summary of the issues follows. 71 72 (1) Class names are not in binary form 73 74 Example: 75 76 type="android.os.Parcelable.Creator" 77 78 This could be a Creator class in the package android.os.Parcelable, 79 or Parcelable.Creator in the package android.os. We can guess based on 80 capitalization, but that's unreliable. 81 82 The API XML does specify each package in a <package> tag, so we should have 83 the full set of packages available. From this we can remove one element 84 at a time from the right until we match a known package. This will work 85 unless "android.os" and "android.os.Parcelable" are both valid packages. 86 87 88 (2) Public enums are not enumerated 89 90 Enumeration classes are included, and always have two methods ("valueOf" 91 and "values"). What isn't included are entries for the fields representing 92 the enumeration values. This makes it look like an APK is referring 93 to non-public fields in the class. 94 95 If apkcheck sees a reference to an unknown field, and the field's defining 96 class appears to be an Enum (the superclass is java.lang.Enum), we emit 97 a warning instead of an error. 98 99 100 (3) Public annotation methods are not listed 101 102 Annotation classes have trivial entries that show only the class name 103 and "implements java.lang.annotation.Annotation". It is not possible 104 to verify that a method call on an annotation is valid. 105 106 If apkcheck sees a method call to an unknown method, and the class appears 107 to be an annotation (extends Object, implements Annotation, defines no 108 fields or methods), we emit a warning instead of an error. 109 110 111 (4) Covariant return types 112 113 Suppose a class defines a method "public Foo gimmeFoo()". Any subclass 114 that overrides that method must also return Foo, so it would seem that 115 there's no need to emit a method entry for gimmeFoo() in the subclasses. 116 117 However, it's possible to override gimmeFoo with "public MegaFoo 118 gimmeFoo()" so long as MegaFoo is an instance of Foo. In that case it 119 is necessary to emit a new method entry, but the public API XML generator 120 does not. 121 122 If apkcheck can't find an exact match for a method reference, but can 123 find a method that matches on everything but the return type, it will 124 emit a warning instead of an error. (We could be more thorough and try 125 to verify that the return types are related, but that's more trouble than 126 it's worth.) 127 128 129 (5) Generic signatures 130 131 When generic signatures are used, the public API file will contain 132 entries like these: 133 134 <parameter name="key" type="K"> 135 <parameter name="others" type="E..."> 136 <parameter name="map" type="java.util.Map<? extends K, ? extends V>"> 137 138 The generic types are generally indistinguishable from classes in the 139 default package (i.e. that have no package name). In most cases they're 140 a single letter, so apkcheck includes a kluge that converts single-letter 141 class names to java.lang.Object. 142 143 This often works, but falls apart in a few cases. For example: 144 145 public <T extends Parcelable> T getParcelableExtra(String name) { 146 return mExtras == null ? null : mExtras.<T>getParcelable(name); 147 } 148 149 This is emitted as: 150 151 <method name="getParcelableExtra" return="T"> 152 153 which gets converted to java.lang.Object. Unfortunately the APK wants 154 a method with a more specific return type (android.os.Parcelable), so 155 the lookup fails. 156 157 There is no way to recover the actual type, because the generic signature 158 details are not present in the XML. This particular case will be handled 159 as a covariant return type. When the generic type is in the parameter 160 list, though, this isn't handled so easily. 161 162 These cases are relatively few, so they were handled by baking the 163 signatures into the code (--uses-library=BUILTIN). (At some point it 164 may be worthwhile to try a little harder here.) 165 166 167 (6) Use of opaque non-public types 168 169 Some classes are not meant for public consumption, but are still referred 170 to by application code. For example, an opaque type might be passed to 171 the app as a cookie. 172 173 Another example is the Dalvik annotation classes, like 174 dalvik.annotation.InnerClass. These are emitted by "dx", and referenced 175 from the DEX file, but not intended to be used by application code. 176 177 If an APK refers to a non-public class, but doesn't access any fields 178 or methods, a warning is emitted instead of an error. 179 180