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