Re-import 6.0.1+r72 to include platform/development

parent 3fcbecce
*~
*.bak
*.pyc
*.pyc-2.4
Thumbs.db
# Copyright (C) 2007 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.
#
# If you don't need to do a full clean build but would like to touch
# a file or delete some intermediate files, add a clean step to the end
# of the list. These steps will only be run once, if they haven't been
# run before.
#
# E.g.:
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
#
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
# files that are missing or have been moved.
#
# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
# Use $(OUT_DIR) to refer to the "out" directory.
#
# If you need to re-do something that's already mentioned, just copy
# the command and add it to the bottom of the list. E.g., if a change
# that you made last week required touching a file and a change you
# made today requires touching the same file, just copy the old
# touch step and add it to the end of the list.
#
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
# For example:
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/CorpApp_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
# Copyright (C) 2010 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.
LOCAL_PATH := $(call my-dir)
# We use copy-file-to-new-target so that the installed
# script file's timestamp is at least as new as the
# .jar file it wraps.
# the execution script
# ============================================================
include $(CLEAR_VARS)
LOCAL_IS_HOST_MODULE := true
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE := apkcheck
include $(BUILD_SYSTEM)/base_rules.mk
$(LOCAL_BUILT_MODULE): $(HOST_OUT_JAVA_LIBRARIES)/apkcheck$(COMMON_JAVA_PACKAGE_SUFFIX)
$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/etc/apkcheck | $(ACP)
@echo "Copy: $(PRIVATE_MODULE) ($@)"
$(copy-file-to-new-target)
$(hide) chmod 755 $@
# the other stuff
# ============================================================
subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
src \
))
include $(subdirs)
Android APK Checker
This compares the set of classes, fields, and methods used by an Android
application against the published API. It identifies and reports the
use of any unpublished members or methods.
The public API description files live in the source tree, in
frameworks/base/api/. The tip-of-tree version is in "current.xml",
and each officially released API has a numbered file (e.g. "6.xml").
They're generated from the sources, and can take into acount javadoc
annotations like "@hide" in comments.
The dependency set for an APK can be generated with "dexdeps". It finds
all classes, fields, and methods that are referenced by classes.dex but not
defined locally. The tool can't easily tell anything about a dependency
beyond the name (e.g. whether a class is a static or non-static inner
class), so while the output from dexdeps is similar in structure to the
API XML file, it has much less detail.
==== Usage ====
% apkcheck [options] public-api.xml apk1.xml ...
Provide the public API data file of choice, and one or more XML files
generated by dexdeps. The time required to parse and manipulate the
public API XML file is generally much larger than the time required to
analyze the APK, so if you have a large set of APKs it's best to run them
through in large batches.
Options:
--help
Show options summary.
--uses-library=<lib.xml>
Load additional public API list. This is intended for APKs that
use "uses-library" directives to pull in external libraries. Since
the external libraries are not part of the public API, their use
would otherwise be flagged as illegal by apkcheck.
--ignore-package=<package-name>
Ignore errors generated by references to the named package (e.g.
"com.google.android.maps"). Warnings will be generated instead.
Useful for ignoring references to shared library content when
XML API data is not available.
--[no-]warn
Enable or disable warning messages. These are disabled by default.
--[no-]error
Enable or disable error messages. These are enabled by default. If
you disable both warnings and errors you will only see a summary.
In some cases involving generic signatures it may not be possible
to accurately reconstruct the public API. Some popular cases have
been hard-coded into the program. They can be included by specifying
"--uses-library=BUILTIN".
Example use:
% dexdeps out/target/product/sapphire/system/app/Gmail.apk > Gmail.apk.xml
% apkcheck --uses-library=BUILTIN frameworks/base/api/current.xml Gmail.apk.xml
Gmail.apk.xml: summary: 0 errors, 15 warnings
==== Limitations ====
The API XML files have some ambiguous entries and are missing important
pieces. A summary of the issues follows.
(1) Class names are not in binary form
Example:
type="android.os.Parcelable.Creator"
This could be a Creator class in the package android.os.Parcelable,
or Parcelable.Creator in the package android.os. We can guess based on
capitalization, but that's unreliable.
The API XML does specify each package in a <package> tag, so we should have
the full set of packages available. From this we can remove one element
at a time from the right until we match a known package. This will work
unless "android.os" and "android.os.Parcelable" are both valid packages.
(2) Public enums are not enumerated
Enumeration classes are included, and always have two methods ("valueOf"
and "values"). What isn't included are entries for the fields representing
the enumeration values. This makes it look like an APK is referring
to non-public fields in the class.
If apkcheck sees a reference to an unknown field, and the field's defining
class appears to be an Enum (the superclass is java.lang.Enum), we emit
a warning instead of an error.
(3) Public annotation methods are not listed
Annotation classes have trivial entries that show only the class name
and "implements java.lang.annotation.Annotation". It is not possible
to verify that a method call on an annotation is valid.
If apkcheck sees a method call to an unknown method, and the class appears
to be an annotation (extends Object, implements Annotation, defines no
fields or methods), we emit a warning instead of an error.
(4) Covariant return types
Suppose a class defines a method "public Foo gimmeFoo()". Any subclass
that overrides that method must also return Foo, so it would seem that
there's no need to emit a method entry for gimmeFoo() in the subclasses.
However, it's possible to override gimmeFoo with "public MegaFoo
gimmeFoo()" so long as MegaFoo is an instance of Foo. In that case it
is necessary to emit a new method entry, but the public API XML generator
does not.
If apkcheck can't find an exact match for a method reference, but can
find a method that matches on everything but the return type, it will
emit a warning instead of an error. (We could be more thorough and try
to verify that the return types are related, but that's more trouble than
it's worth.)
(5) Generic signatures
When generic signatures are used, the public API file will contain
entries like these:
<parameter name="key" type="K">
<parameter name="others" type="E...">
<parameter name="map" type="java.util.Map&lt;? extends K, ? extends V&gt;">
The generic types are generally indistinguishable from classes in the
default package (i.e. that have no package name). In most cases they're
a single letter, so apkcheck includes a kluge that converts single-letter
class names to java.lang.Object.
This often works, but falls apart in a few cases. For example:
public <T extends Parcelable> T getParcelableExtra(String name) {
return mExtras == null ? null : mExtras.<T>getParcelable(name);
}
This is emitted as:
<method name="getParcelableExtra" return="T">
which gets converted to java.lang.Object. Unfortunately the APK wants
a method with a more specific return type (android.os.Parcelable), so
the lookup fails.
There is no way to recover the actual type, because the generic signature
details are not present in the XML. This particular case will be handled
as a covariant return type. When the generic type is in the parameter
list, though, this isn't handled so easily.
These cases are relatively few, so they were handled by baking the
signatures into the code (--uses-library=BUILTIN). (At some point it
may be worthwhile to try a little harder here.)
(6) Use of opaque non-public types
Some classes are not meant for public consumption, but are still referred
to by application code. For example, an opaque type might be passed to
the app as a cookie.
Another example is the Dalvik annotation classes, like
dalvik.annotation.InnerClass. These are emitted by "dx", and referenced
from the DEX file, but not intended to be used by application code.
If an APK refers to a non-public class, but doesn't access any fields
or methods, a warning is emitted instead of an error.
#!/bin/bash
#
# Copyright (C) 2010 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.
# Set up prog to be the path of this script, including following symlinks,
# and set up progdir to be the fully-qualified pathname of its directory.
prog="$0"
while [ -h "${prog}" ]; do
newProg=`/bin/ls -ld "${prog}"`
newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
if expr "x${newProg}" : 'x/' >/dev/null; then
prog="${newProg}"
else
progdir=`dirname "${prog}"`
prog="${progdir}/${newProg}"
fi
done
oldwd=`pwd`
progdir=`dirname "${prog}"`
cd "${progdir}"
progdir=`pwd`
prog="${progdir}"/`basename "${prog}"`
cd "${oldwd}"
libdir=`dirname $progdir`/framework
javaOpts=""
while expr "x$1" : 'x-J' >/dev/null; do
opt=`expr "$1" : '-J\(.*\)'`
javaOpts="${javaOpts} -${opt}"
shift
done
exec java $javaOpts -jar $libdir/apkcheck.jar "$@"
Manifest-Version: 1.0
Main-Class: com.android.apkcheck.ApkCheck
# Copyright (C) 2010 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.
LOCAL_PATH := $(call my-dir)
# apkcheck java library
# ============================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAR_MANIFEST := ../etc/manifest.txt
LOCAL_MODULE:= apkcheck
include $(BUILD_HOST_JAVA_LIBRARY)
/*
* Copyright (C) 2010 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.apkcheck;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.io.*;
/**
* Provides implementation for SAX parser.
*/
class ApiDescrHandler extends DefaultHandler {
/*
* Uber-container.
*/
private ApiList mApiList;
/*
* Temporary objects, used as containers while we accumulate the
* innards.
*/
private PackageInfo mCurrentPackage = null;
private ClassInfo mCurrentClass = null;
private MethodInfo mCurrentMethod = null;
/**
* Constructs an ApiDescrHandler.
*
* @param fileName Source file name, used for debugging.
*/
public ApiDescrHandler(ApiList apiList) {
mApiList = apiList;
}
/**
* Returns the ApiList in its current state. Generally only
* makes sense to call here after parsing is completed.
*/
public ApiList getApiList() {
return mApiList;
}
/**
* Processes start tags. If the file is malformed we will likely
* NPE, but this is captured by the caller.
*
* We currently assume that packages and classes only appear once,
* so all classes associated with a package are wrapped in a singular
* instance of &lt;package&gt;. We may want to remove this assumption
* by attempting to find an existing package/class with the same name.
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) {
if (qName.equals("package")) {
/* top-most element */
mCurrentPackage = mApiList.getOrCreatePackage(
attributes.getValue("name"));
} else if (qName.equals("class") || qName.equals("interface")) {
/* get class, gather fields/methods and interfaces */
mCurrentClass = mCurrentPackage.getOrCreateClass(
attributes.getValue("name"),
attributes.getValue("extends"),
attributes.getValue("static"));
} else if (qName.equals("implements")) {
/* add name of interface to current class */
mCurrentClass.addInterface(attributes.getValue("name"));
} else if (qName.equals("method")) {
/* hold object while we gather parameters */
mCurrentMethod = new MethodInfo(attributes.getValue("name"),
attributes.getValue("return"));
} else if (qName.equals("constructor")) {
/* like "method", but has no name or return type */
mCurrentMethod = new MethodInfo("<init>", "void");
/*
* If this is a non-static inner class, we want to add the
* "hidden" outer class parameter as the first parameter.
* We can tell if it's an inner class because the class name
* will include a '$' (it has been normalized already).
*/
String staticClass = mCurrentClass.getStatic();
if (staticClass == null) {
/*
* We're parsing an APK file, which means we can't know
* if the class we're referencing is static or not. We
* also already have the "secret" first parameter
* represented in the method parameter list, so we don't
* need to insert it here.
*/
} else if ("false".equals(staticClass)) {
String className = mCurrentClass.getName();
int dollarIndex = className.indexOf('$');
if (dollarIndex >= 0) {
String outerClass = className.substring(0, dollarIndex);
//System.out.println("--- inserting " +
// mCurrentPackage.getName() + "." + outerClass +
// " into constructor for " + className);
mCurrentMethod.addParameter(mCurrentPackage.getName() +
"." + outerClass);
}
}
} else if (qName.equals("field")) {
/* add to current class */
FieldInfo fInfo = new FieldInfo(attributes.getValue("name"),
attributes.getValue("type"));
mCurrentClass.addField(fInfo);
} else if (qName.equals("parameter")) {
/* add to current method */
mCurrentMethod.addParameter(attributes.getValue("type"));
}
}
/**
* Processes end tags. Generally these add the under-construction
* item to the appropriate container.
*/
@Override
public void endElement(String uri, String localName, String qName) {
if (qName.equals("method") || qName.equals("constructor")) {
/* add method to class */
mCurrentClass.addMethod(mCurrentMethod);
mCurrentMethod = null;
} else if (qName.equals("class") || qName.equals("interface")) {
mCurrentClass = null;
} else if (qName.equals("package")) {
mCurrentPackage = null;
}
}
}
/*
* Copyright (C) 2010 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.apkcheck;
import java.util.HashMap;
import java.util.Iterator;
/**
* Holds a list of API members, including classes, fields, and methods.
*/
public class ApiList {
private HashMap<String,PackageInfo> mPackageList;
private String mDebugString;
private int mWarnings, mErrors;
/**
* Constructs an ApiList.
*
* @param debugString Identification string useful for debugging.
*/
public ApiList(String debugString) {
mPackageList = new HashMap<String,PackageInfo>();
mDebugString = debugString;
}
/**
* Returns the source filename. Useful for debug messages only.
*/