[android-platform-tools-base] 01/01: Imported Debian patch 1.5.0-1

Markus Koschany apo-guest at moszumanska.debian.org
Thu Feb 18 00:27:10 GMT 2016


This is an automated email from the git hooks/post-receive script.

apo-guest pushed a commit to branch master
in repository android-platform-tools-base.

commit 6b8dbcbbfed96cde735a59d1383b642bcfa42074
Author: Markus Koschany <apo at debian.org>
Date:   Thu Feb 18 00:47:02 2016 +0100

    Imported Debian patch 1.5.0-1
---
 debian/android-platform-tools-base.install         |   27 +
 debian/changelog                                   |    5 +
 debian/compat                                      |    1 +
 debian/control                                     |   73 +
 debian/copyright                                   |  341 +
 debian/libandroid-tools-annotations-java.jlibs     |    2 +
 ...ndroid-tools-annotations-java.lintian-overrides |    3 +
 debian/libandroid-tools-annotations-java.poms      |    1 +
 debian/libandroid-tools-common-java.jlibs          |    2 +
 .../libandroid-tools-common-java.lintian-overrides |    3 +
 debian/libandroid-tools-common-java.poms           |    1 +
 debian/maven.rules                                 |   12 +
 debian/patches/SdkTestCase.patch                   |   26 +
 debian/patches/build.gradle.patch                  | 1102 +++
 debian/patches/disable-lint.patch                  | 9620 ++++++++++++++++++++
 debian/patches/gradle-experimental.patch           |   62 +
 debian/patches/project-test-lib.patch              |   35 +
 debian/patches/series                              |    7 +
 debian/patches/settings.gradle.patch               |   87 +
 debian/patches/trove3.patch                        |  154 +
 debian/poms/android-tools-annotations-pom.xml      |   26 +
 debian/poms/android-tools-common-pom.xml           |   40 +
 debian/rules                                       |   11 +
 debian/source/format                               |    1 +
 debian/watch                                       |    2 +
 25 files changed, 11644 insertions(+)

diff --git a/debian/android-platform-tools-base.install b/debian/android-platform-tools-base.install
new file mode 100644
index 0000000..72a90fd
--- /dev/null
+++ b/debian/android-platform-tools-base.install
@@ -0,0 +1,27 @@
+out/build/base/asset-studio/build/libs/asset-studio-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/testutils/build/libs/testutils-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/google-services/build/libs/google-services-1.5.0.jar usr/share/android-platform-tools-base
+out/build/base/layoutlib-api/build/libs/layoutlib-api-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/sdklib-test/build/libs/sdklib-test-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/archquery/build/libs/archquery-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/draw9patch/build/libs/draw9patch-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/builder-test-api/build/libs/builder-test-api-1.5.0.jar usr/share/android-platform-tools-base
+out/build/base/perflib/build/libs/perflib-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/screenshot2/build/libs/screenshot2-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/profile/build/libs/profile.jar usr/share/android-platform-tools-base
+out/build/base/ant-tasks/build/libs/ant-tasks-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/sdklib/build/libs/sdklib-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/builder-model/build/libs/builder-model-1.5.0.jar usr/share/android-platform-tools-base
+out/build/base/builder/build/libs/builder-1.5.0.jar usr/share/android-platform-tools-base
+out/build/base/gradle-core/build/libs/gradle-core-1.5.0.jar usr/share/android-platform-tools-base
+out/build/base/jack/jack-api/build/libs/jack-api-0.9.0.jar usr/share/android-platform-tools-base
+out/build/base/jack/jill-api/build/libs/jill-api-0.9.0.jar usr/share/android-platform-tools-base
+out/build/base/gradle/build/libs/gradle-1.5.0.jar usr/share/android-platform-tools-base
+out/build/base/dvlib/build/libs/dvlib-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/manifest-merger/build/libs/manifest-merger-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/ninepatch/build/libs/ninepatch-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/chartlib/build/libs/chartlib-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/sdk-common/build/libs/sdk-common-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/rule-api/build/libs/rule-api-24.5.0.jar usr/share/android-platform-tools-base
+out/build/base/api-generator/build/libs/api-generator.jar usr/share/android-platform-tools-base
+out/build/base/ddmlib/build/libs/ddmlib-24.5.0.jar usr/share/android-platform-tools-base
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..79a70e5
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+android-platform-tools-base (1.5.0-1) unstable; urgency=medium
+
+  * Initial release. (Closes: #814797)
+
+ -- Markus Koschany <apo at debian.org>  Thu, 18 Feb 2016 00:47:02 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..892d7df
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,73 @@
+Source: android-platform-tools-base
+Section: java
+Priority: optional
+Maintainer: Android Tools Maintainer <android-tools-devel at lists.alioth.debian.org>
+Uploaders:
+ Markus Koschany <apo at debian.org>
+Build-Depends:
+ debhelper (>= 9),
+ default-jdk,
+ gradle-debian-helper,
+ javahelper,
+ junit4,
+ libandroid-tools-annotations-java,
+ libandroid-tools-common-java,
+ libasm4-java,
+ libbcpkix-java,
+ libbcprov-java,
+ libcommons-compress-java,
+ libhttpmime-java,
+ libintellij-annotations-java,
+ libjavawriter-java,
+ libjsr305-java,
+ libkxml2-java,
+ libtrove3-java,
+ maven-debian-helper,
+ maven-repo-helper,
+ proguard
+Standards-Version: 3.9.7
+Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/android-platform-tools-base.git
+Vcs-Git: https://anonscm.debian.org/git/pkg-java/android-platform-tools-base.git
+Homepage: https://android.googlesource.com/platform/tools/base/
+
+Package: android-platform-tools-base
+Architecture: all
+Depends:
+ ${misc:Depends}
+Description: base tools for developing applications for the Android system
+ This package includes various tools for developing and building Android
+ applications, e.g.
+ .
+  * Draw 9-patch
+    Allows you to easily create a NinePatch graphic using a WYSIWYG
+    editor. It also previews stretched versions of the image, and
+    highlights the area in which content is allowed.
+ .
+  * JOBB
+    Allows you to build encrypted and unencrypted APK expansion files
+    in Opaque Binary Blob (OBB) format.
+ .
+  * Android plugin for Gradle
+    The Android build system consists of an Android plugin for Gradle.
+    You can build your Android apps from within Android Studio and from
+    the command line on your machine or on machines where Android Studio
+    is not installed (such as continuous integration servers).
+ .
+  * Manifest Merger, ddmlib, layoutlib, chartlib, Jack & Jill (Java Android
+    Compiler Kit)
+
+Package: libandroid-tools-annotations-java
+Architecture: all
+Depends:
+ ${misc:Depends}
+Description: annotations used throughout the Android tools libraries
+ This package provides support for annotations which can be found in all
+ Android tools libraries.
+
+Package: libandroid-tools-common-java
+Architecture: all
+Depends:
+ ${misc:Depends}
+Description: common library used by other Android tools libraries
+ This package provides common tasks and classes which are used by other Android
+ tools libraries.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..6afe3f0
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,341 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: Android Platform Tools Base
+Source: https://android.googlesource.com/platform/tools/base/
+Files-Excluded:
+ *.so
+
+Files: *
+Copyright: 2009-2015, The Android Open Source Project
+License: Apache-2.0
+
+Files: base/rule-api/src/main/java/com/android/ide/common/api/RuleAction.java
+ base/rule-api/src/main/java/com/android/ide/common/api/*
+ base/asset-studio/src/test/java/com/android/assetstudiolib/*
+ base/sdklib/src/test/java/com/android/sdklib/internal/repository/AddonsListFetcherTest.java
+ base/sdklib/src/test/java/com/android/sdklib/internal/repository/*.java
+ base/sdklib/src/test/java/com/android/sdklib/internal/build/SymbolLoaderTest.java
+ base/sdklib/src/test/java/com/android/sdklib/repository/*.java
+ base/device_validator/app/src/com/android/validator/*
+ base/testutils/src/main/java/com/android/testutils/SdkTestCase.java
+ base/build-system/manifest-merger/src/test/java/com/android/manifmerger/ManifestMergerTest.java
+ base/build-system/builder/src/test/java/com/android/builder/internal/SymbolWriterTest.java
+ base/sdk-common/src/main/java/com/android/ide/common/resources/ScanningContext.java
+ base/common/src/test/java/com/android/io/NonClosingInputStreamTest.java
+Copyright: 2009-2015, The Android Open Source Project
+License: EPL-1.0
+
+Files: base/build-system/integration-test/test-projects/ndkSanAngeles2/*
+Copyright: 2009,      The Android Open Source Project
+           2004-2005, Jetro Lauha
+License: LGPL-2.1+ or BSD-3-clause
+
+Files: base/jobb/src/main/java/Twofish/Twofish*
+Copyright: The Cryptix Foundation Limited
+License: Cryptix-General-License
+
+Files: base/jobb/src/main/java/com/android/jobb/Base64.java
+Copyright: 2000, The Legion Of The Bouncy Castle
+License: BSD-3-clause
+
+Files: debian/*
+Copyright: 2016, Markus Koschany <apo at debian.org>
+License: Apache-2.0
+
+License: LGPL-2.1+
+ On Debian systems the full license text of the GNU Lesser General Public
+ License 2.1 can be found in /usr/share/common-licenses/LGPL-2.1.
+
+License: Apache-2.0
+ 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.
+ .
+ On Debian systems, the complete text of the Apache version 2.0 license
+ can be found in "/usr/share/common-licenses/Apache-2.0".
+
+License: Cryptix-General-License
+ Cryptix General License
+ .
+ Copyright (c) 1995-2005 The Cryptix Foundation Limited.
+ .
+ All rights reserved.
+ .
+ Redistribution and use in source and binary forms, with or without
+ .
+ modification, are permitted provided that the following conditions are
+ .
+ met:
+ .
+ 1. Redistributions of source code must retain the copyright notice,
+    this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+ .
+ THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND
+ .
+ CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ .
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ .
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ .
+ IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE
+ .
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ .
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ .
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ .
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ .
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ .
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ .
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+License: BSD-3-clause
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the Software
+ is furnished to do so, subject to the following conditions:
+ .
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+ .
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN~
+ THE SOFTWARE.
+
+License: EPL-1.0
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE
+ PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+ .
+ 1. DEFINITIONS
+ .
+ "Contribution" means:
+ .
+ a) in the case of the initial Contributor, the initial code and documentation
+ distributed under this Agreement, and
+ b) in the case of each subsequent Contributor:
+ .
+ i) changes to the Program, and
+ .
+ ii) additions to the Program;
+ .
+ where such changes and/or additions to the Program originate from and are
+ distributed by that particular Contributor. A Contribution 'originates'
+ from a Contributor if it was added to the Program by such Contributor itself
+ or anyone acting on such Contributor's behalf. Contributions do not include
+ additions to the Program which: (i) are separate modules of software
+ distributed in conjunction with the Program under their own license
+ agreement, and (ii) are not derivative works of the Program.
+ .
+ "Contributor" means any person or entity that distributes the Program.
+ .
+ "Licensed Patents " mean patent claims licensable by a Contributor which are
+ necessarily infringed by the use or sale of its Contribution alone or when
+ combined with the Program.
+ .
+ "Program" means the Contributions distributed in accordance with this
+ Agreement.
+ .
+ "Recipient" means anyone who receives the Program under this Agreement,
+ including all Contributors.
+ .
+ 2. GRANT OF RIGHTS
+ .
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce, prepare derivative works of, publicly display, publicly perform,
+ distribute and sublicense the Contribution of such Contributor, if any,
+ and such derivative works, in source code and object code form.
+ .
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free patent license under
+ Licensed Patents to make, use, sell, offer to sell, import and otherwise
+ transfer the Contribution of such Contributor, if any, in source code and
+ object code form. This patent license shall apply to the combination of
+ the Contribution and the Program if, at the time the Contribution is added
+ by the Contributor, such addition of the Contribution causes such
+ combination to be covered by the Licensed Patents. The patent license shall
+ not apply to any other combinations which include the Contribution. No
+ hardware per se is licensed hereunder.
+ .
+ c) Recipient understands that although each Contributor grants the licenses
+ to its Contributions set forth herein, no assurances are provided by any
+ Contributor that the Program does not infringe the patent or other
+ intellectual property rights of any other entity. Each Contributor disclaims
+ any liability to Recipient for claims brought by any other entity based on
+ infringement of intellectual property rights or otherwise. As a condition to
+ exercising the rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual property rights
+ needed, if any. For example, if a third party patent license is required to
+ allow Recipient to distribute the Program, it is Recipient's responsibility
+ to acquire that license before distributing the Program.
+ .
+ d) Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright license
+ set forth in this Agreement.
+ .
+ 3. REQUIREMENTS
+ .
+ A Contributor may choose to distribute the Program in object code form under
+ its own license agreement, provided that:
+ .
+ a) it complies with the terms and conditions of this Agreement; and
+ .
+ b) its license agreement:
+ .
+ i) effectively disclaims on behalf of all Contributors all warranties and
+ conditions, express and implied, including warranties or conditions of title
+ and non-infringement, and implied warranties or conditions of merchantability
+ and fitness for a particular purpose;
+ .
+ ii) effectively excludes on behalf of all Contributors all liability for
+ damages, including direct, indirect, special, incidental and consequential
+ damages, such as lost profits;
+ .
+ iii) states that any provisions which differ from this Agreement are offered
+ by that Contributor alone and not by any other party; and
+ .
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable manner on
+ or through a medium customarily used for software exchange.
+ .
+ When the Program is made available in source code form:
+ .
+ a) it must be made available under this Agreement; and
+ .
+ b) a copy of this Agreement must be included with each copy of the Program.
+ .
+ Contributors may not remove or alter any copyright notices contained within
+ the Program.
+ .
+ Each Contributor must identify itself as the originator of its Contribution,
+ if any, in a manner that reasonably allows subsequent Recipients to identify
+ the originator of the Contribution.
+ .
+ 4. COMMERCIAL DISTRIBUTION
+ .
+ Commercial distributors of software may accept certain responsibilities with
+ respect to end users, business partners and the like. While this license is
+ intended to facilitate the commercial use of the Program, the Contributor who
+ includes the Program in a commercial product offering should do so in a manner
+ which does not create potential liability for other Contributors. Therefore,
+ if a Contributor includes the Program in a commercial product offering, such
+ Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+ every other Contributor ("Indemnified Contributor") against any losses,
+ damages and costs (collectively "Losses") arising from claims, lawsuits and
+ other legal actions brought by a third party against the Indemnified
+ Contributor to the extent caused by the acts or omissions of such Commercial
+ Contributor in connection with its distribution of the Program in a commercial
+ product offering. The obligations in this section do not apply to any claims
+ or Losses relating to any actual or alleged intellectual property
+ infringement. In order to qualify, an Indemnified Contributor must:
+ a) promptly notify the Commercial Contributor in writing of such claim, and
+ b) allow the Commercial Contributor to control, and cooperate with the
+ Commercial Contributor in, the defense and any related settlement
+ negotiations. The Indemnified Contributor may participate in any such claim
+ at its own expense.
+ .
+ For example, a Contributor might include the Program in a commercial product
+ offering, Product X. That Contributor is then a Commercial Contributor. If
+ that Commercial Contributor then makes performance claims, or offers
+ warranties related to Product X, those performance claims and warranties are
+ such Commercial Contributor's responsibility alone. Under this section, the
+ Commercial Contributor would have to defend claims against the other
+ Contributors related to those performance claims and warranties, and if a
+ court requires any other Contributor to pay any damages as a result, the
+ Commercial Contributor must pay those damages.
+ .
+ 5. NO WARRANTY
+ .
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
+ AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
+ EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
+ CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
+ PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
+ appropriateness of using and distributing the Program and assumes all
+ risks associated with its exercise of rights under this Agreement ,
+ including but not limited to the risks and costs of program errors,
+ compliance with applicable laws, damage to or loss of data, programs or
+ equipment, and unavailability or interruption of operations.
+ .
+ 6. DISCLAIMER OF LIABILITY
+ .
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+ CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
+ LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
+ EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGES.
+ .
+ 7. GENERAL
+ .
+ If any provision of this Agreement is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of the
+ remainder of the terms of this Agreement, and without further action by
+ the parties hereto, such provision shall be reformed to the minimum extent
+ necessary to make such provision valid and enforceable.
+ .
+ If Recipient institutes patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+ (excluding combinations of the Program with other software or hardware)
+ infringes such Recipient's patent(s), then such Recipient's rights granted
+ under Section 2(b) shall terminate as of the date such litigation is filed.
+ .
+ All Recipient's rights under this Agreement shall terminate if it fails to
+ comply with any of the material terms or conditions of this Agreement and
+ does not cure such failure in a reasonable period of time after becoming
+ aware of such noncompliance. If all Recipient's rights under this Agreement
+ terminate, Recipient agrees to cease use and distribution of the Program as
+ soon as reasonably practicable. However, Recipient's obligations under this
+ Agreement and any licenses granted by Recipient relating to the Program
+ shall continue and survive.
+ .
+ Everyone is permitted to copy and distribute copies of this Agreement, but
+ in order to avoid inconsistency the Agreement is copyrighted and may only
+ be modified in the following manner. The Agreement Steward reserves the
+ right to publish new versions (including revisions) of this Agreement from
+ time to time. No one other than the Agreement Steward has the right to
+ modify this Agreement. The Eclipse Foundation is the initial Agreement
+ Steward. The Eclipse Foundation may assign the responsibility to serve as
+ the Agreement Steward to a suitable separate entity. Each new version of
+ the Agreement will be given a distinguishing version number. The Program
+ (including Contributions) may always be distributed subject to the version
+ of the Agreement under which it was received. In addition, after a new
+ version of the Agreement is published, Contributor may elect to distribute
+ the Program (including its Contributions) under the new version. Except as
+ expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
+ rights or licenses to the intellectual property of any Contributor under
+ this Agreement, whether expressly, by implication, estoppel or otherwise.
+ All rights in the Program not expressly granted under this Agreement are
+ reserved.
+ .
+ This Agreement is governed by the laws of the State of New York and the
+ intellectual property laws of the United States of America. No party to
+ this Agreement will bring a legal action under this Agreement more than
+ one year after the cause of action arose. Each party waives its rights to
+ a jury trial in any resulting litigation.
diff --git a/debian/libandroid-tools-annotations-java.jlibs b/debian/libandroid-tools-annotations-java.jlibs
new file mode 100644
index 0000000..3fad08f
--- /dev/null
+++ b/debian/libandroid-tools-annotations-java.jlibs
@@ -0,0 +1,2 @@
+com.android.tools.annotations.jar
+
diff --git a/debian/libandroid-tools-annotations-java.lintian-overrides b/debian/libandroid-tools-annotations-java.lintian-overrides
new file mode 100644
index 0000000..4d50e31
--- /dev/null
+++ b/debian/libandroid-tools-annotations-java.lintian-overrides
@@ -0,0 +1,3 @@
+# Java 8 is the new default now, hence all jars will work.
+incompatible-java-bytecode-format
+
diff --git a/debian/libandroid-tools-annotations-java.poms b/debian/libandroid-tools-annotations-java.poms
new file mode 100644
index 0000000..a4084b0
--- /dev/null
+++ b/debian/libandroid-tools-annotations-java.poms
@@ -0,0 +1 @@
+debian/poms/android-tools-annotations-pom.xml --no-parent --usj-name=com.android.tools.annotations --artifact=com.android.tools.annotations.jar
diff --git a/debian/libandroid-tools-common-java.jlibs b/debian/libandroid-tools-common-java.jlibs
new file mode 100644
index 0000000..eb3dc31
--- /dev/null
+++ b/debian/libandroid-tools-common-java.jlibs
@@ -0,0 +1,2 @@
+com.android.tools.common.jar
+
diff --git a/debian/libandroid-tools-common-java.lintian-overrides b/debian/libandroid-tools-common-java.lintian-overrides
new file mode 100644
index 0000000..4d50e31
--- /dev/null
+++ b/debian/libandroid-tools-common-java.lintian-overrides
@@ -0,0 +1,3 @@
+# Java 8 is the new default now, hence all jars will work.
+incompatible-java-bytecode-format
+
diff --git a/debian/libandroid-tools-common-java.poms b/debian/libandroid-tools-common-java.poms
new file mode 100644
index 0000000..a77a0d2
--- /dev/null
+++ b/debian/libandroid-tools-common-java.poms
@@ -0,0 +1 @@
+debian/poms/android-tools-common-pom.xml --no-parent --usj-name=com.android.tools.common --artifact=com.android.tools.common.jar
diff --git a/debian/maven.rules b/debian/maven.rules
new file mode 100644
index 0000000..31bf657
--- /dev/null
+++ b/debian/maven.rules
@@ -0,0 +1,12 @@
+s/net.sf.kxml/kxml2/ * * s/.*/debian/ * *
+org.ow2.asm asm * s/.*/4.x/ * *
+org.ow2.asm asm-tree * s/.*/4.x/ * *
+org.ow2.asm asm-analysis * s/.*/4.x/ * *
+com.google.code.findbugs jsr305 * s/.*/0.x/ * *
+org.bouncycastle s/bcpkix-jdk15on/bcpkix/ * s/.*/1.51/ * *
+org.bouncycastle s/bcprov-jdk15on/bcprov/ * s/.*/1.51/ * *
+junit junit * s/.*/4.x/ * *
+org.gradle s/messaging/gradle-messaging/ * s/.*/debian/ * *
+org.gradle s/core/gradle-core/ * s/.*/debian/ * *
+org.gradle s/wrapper/gradle-wrapper/ * s/.*/debian/ * *
+org.gradle s/baseServices/gradle-base-services/ * s/.*/debian/ * *
diff --git a/debian/patches/SdkTestCase.patch b/debian/patches/SdkTestCase.patch
new file mode 100644
index 0000000..5666a3d
--- /dev/null
+++ b/debian/patches/SdkTestCase.patch
@@ -0,0 +1,26 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 6 Feb 2016 22:13:21 +0100
+Subject: SdkTestCase
+
+---
+ .../testutils/src/main/java/com/android/testutils/SdkTestCase.java | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/base/testutils/src/main/java/com/android/testutils/SdkTestCase.java b/base/testutils/src/main/java/com/android/testutils/SdkTestCase.java
+index 75877a5..2a3eded 100644
+--- a/base/testutils/src/main/java/com/android/testutils/SdkTestCase.java
++++ b/base/testutils/src/main/java/com/android/testutils/SdkTestCase.java
+@@ -353,13 +353,6 @@ public abstract class SdkTestCase extends TestCase {
+             tempFile.delete();
+         }
+ 
+-        Files.copy(new InputSupplier<InputStream>() {
+-            @Override
+-            public InputStream getInput() throws IOException {
+-                return contents;
+-            }
+-        }, tempFile);
+-
+         return tempFile;
+     }
+ 
diff --git a/debian/patches/build.gradle.patch b/debian/patches/build.gradle.patch
new file mode 100644
index 0000000..e72125c
--- /dev/null
+++ b/debian/patches/build.gradle.patch
@@ -0,0 +1,1102 @@
+From: Markus Koschany <apo at debian.org>
+Date: Thu, 21 Jan 2016 20:52:18 +0100
+Subject: build.gradle
+
+Patch upstream's build system for Debian.
+
+Forwarded: not-needed
+---
+ base/annotations/build.gradle                      |  7 ++---
+ base/asset-studio/build.gradle                     |  5 ++--
+ base/build-system/builder-model/build.gradle       | 13 +++-------
+ base/build-system/builder-test-api/build.gradle    |  8 +-----
+ base/build-system/builder/build.gradle             | 19 +++-----------
+ base/build-system/google-services/build.gradle     |  7 +----
+ base/build-system/gradle-core/build.gradle         |  6 +----
+ base/build-system/gradle-experimental/build.gradle |  7 +----
+ base/build-system/gradle/build.gradle              |  9 +------
+ base/build-system/integration-test/build.gradle    |  5 ++--
+ .../3rdPartyTests/buildSrc/build.gradle            |  3 +--
+ base/build-system/manifest-merger/build.gradle     |  7 ++---
+ base/build-system/project-test-lib/build.gradle    |  2 --
+ base/build-system/project-test/build.gradle        |  2 --
+ base/build.gradle                                  |  1 -
+ base/chartlib/build.gradle                         |  3 +--
+ base/common/build.gradle                           |  7 ++---
+ base/ddmlib/build.gradle                           |  7 ++---
+ base/device_validator/dvlib/build.gradle           |  8 ++----
+ base/draw9patch/build.gradle                       | 17 ++----------
+ base/jack/jack-api/build.gradle                    |  3 ---
+ base/jack/jill-api/build.gradle                    |  3 ---
+ base/jobb/build.gradle                             | 16 ++----------
+ base/layoutlib-api/build.gradle                    |  7 ++---
+ base/legacy/ant-tasks/build.gradle                 |  4 +--
+ base/legacy/archquery/build.gradle                 |  5 ++--
+ base/lint/cli/build.gradle                         | 20 +++------------
+ base/lint/libs/lint-api/build.gradle               |  7 ++---
+ base/lint/libs/lint-checks/build.gradle            |  7 ++---
+ base/lint/libs/lint-tests/build.gradle             |  5 +---
+ base/misc/screenshot2/build.gradle                 | 15 ++---------
+ base/ninepatch/build.gradle                        |  4 +--
+ base/perflib/build.gradle                          |  3 +--
+ base/rpclib/build.gradle                           |  3 +--
+ base/rule-api/build.gradle                         |  4 +--
+ base/sdk-common/build.gradle                       |  7 ++---
+ base/sdk-common/generate-locale-data/build.gradle  |  5 ++--
+ base/sdklib/build.gradle                           |  7 ++---
+ base/sdklib/test.gradle                            |  2 +-
+ base/templates/build.gradle                        | 10 --------
+ base/testutils/build.gradle                        |  5 +---
+ build.gradle                                       | 30 ++--------------------
+ 42 files changed, 65 insertions(+), 250 deletions(-)
+
+diff --git a/base/annotations/build.gradle b/base/annotations/build.gradle
+index dbfcea6..d448bbf 100644
+--- a/base/annotations/build.gradle
++++ b/base/annotations/build.gradle
+@@ -1,13 +1,10 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'annotations'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ project.ext.pomName = 'Android Tools Annotations library'
+ project.ext.pomDesc = 'annotations used throughout the Android tools libraries.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/asset-studio/build.gradle b/base/asset-studio/build.gradle
+index 1e186ad..35c11b6 100644
+--- a/base/asset-studio/build.gradle
++++ b/base/asset-studio/build.gradle
+@@ -1,10 +1,9 @@
+ apply plugin: 'java'
+-apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'asset-studio'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:layoutlib-api')
+diff --git a/base/build-system/builder-model/build.gradle b/base/build-system/builder-model/build.gradle
+index 0f2fc5f..123de89 100644
+--- a/base/build-system/builder-model/build.gradle
++++ b/base/build-system/builder-model/build.gradle
+@@ -1,6 +1,5 @@
+ apply plugin: 'java'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ dependencies {
+     compile project(':base:annotations')
+@@ -8,20 +7,16 @@ dependencies {
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'builder-model'
+-version = rootProject.ext.buildVersion
++version = '1.5.0'
+ 
+ project.ext.pomName = 'Android Builder Model library'
+ project.ext.pomDesc = 'Model for the Builder library.'
+ 
+-project.ext.apiVersion = rootProject.ext.apiVersion ?: 0
++project.ext.apiVersion = '3'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+ ["Model-Version": version, "Model-Api-Version": apiVersion].each { key, value ->
+     jar.manifest.attributes((key): value)
+-    sdkJar.manifest.attributes((key): value)
+ }
+ 
+ def generated = new File("${project.buildDir}/generated/java")
+@@ -53,4 +48,4 @@ public final class Version {
+ """
+ }
+ 
+-tasks.compileJava.dependsOn generateVersionConstantsJava
+\ No newline at end of file
++tasks.compileJava.dependsOn generateVersionConstantsJava
+diff --git a/base/build-system/builder-test-api/build.gradle b/base/build-system/builder-test-api/build.gradle
+index d24b00f..07524a0 100644
+--- a/base/build-system/builder-test-api/build.gradle
++++ b/base/build-system/builder-test-api/build.gradle
+@@ -1,6 +1,4 @@
+ apply plugin: 'java'
+-apply plugin: 'jacoco'
+-apply plugin: 'clone-artifacts'
+ 
+ dependencies {
+     compile project(':base:ddmlib')
+@@ -10,12 +8,8 @@ dependencies {
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'builder-test-api'
+-version = rootProject.ext.buildVersion
++version = '1.5.0'
+ 
+ project.ext.pomName = 'Android Builder Test API library'
+ project.ext.pomDesc = 'API for the Test extension point in the Builder library.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+-
+diff --git a/base/build-system/builder/build.gradle b/base/build-system/builder/build.gradle
+index 050a4a1..c1379b6 100644
+--- a/base/build-system/builder/build.gradle
++++ b/base/build-system/builder/build.gradle
+@@ -1,6 +1,4 @@
+ apply plugin: 'java'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'jacoco'
+ 
+ evaluationDependsOn(':base:builder-model')
+ evaluationDependsOn(':base:builder-test-api')
+@@ -27,7 +25,7 @@ dependencies {
+     testCompile 'junit:junit:4.12'
+     testCompile 'org.mockito:mockito-all:1.9.5'
+     testCompile project(':base:testutils')
+-    testCompile project(':base:sdklib').sourceSets.test.output
++    testCompile project(':base:sdklib')
+ }
+ 
+ test {
+@@ -36,14 +34,11 @@ test {
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'builder'
+-version = rootProject.ext.buildVersion
++version = '1.5.0'
+ 
+ project.ext.pomName = 'Android Builder library'
+ project.ext.pomDesc = 'Library to build Android applications.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+ jar.manifest.attributes("Builder-Version": version)
+ 
+@@ -58,8 +53,6 @@ sourceSets {
+ }
+ 
+ task generateVersionConstantsJava {
+-    inputs.property("apiVersion", apiVersion)
+-    inputs.property("version", version)
+     ext.versionFile = new File(generated, "com/android/builder/Version.java")
+     outputs.file(versionFile)
+ }
+@@ -70,8 +63,8 @@ package com.android.builder;
+ 
+ public final class Version {
+     private Version() {}
+-    public static final String ANDROID_GRADLE_PLUGIN_VERSION = "$version";
+-    public static final int BUILDER_MODEL_API_VERSION = $apiVersion;
++    public static final String ANDROID_GRADLE_PLUGIN_VERSION = "1.5";
++    public static final int BUILDER_MODEL_API_VERSION = 3;
+ }
+ """
+ }
+@@ -95,11 +88,7 @@ dependencies {
+ sourceSets.main.compileClasspath += [configurations.provided]
+ sourceSets.test.runtimeClasspath += [configurations.provided]
+ tasks.compileJava.dependsOn(configurations.provided)
+-tasks.sourcesJar.dependsOn(configurations.sourcesProvided)
+ 
+ tasks.jar {
+     from({zipTree(configurations.provided.singleFile)})
+ }
+-tasks.sourcesJar {
+-    from({zipTree(configurations.sourcesProvided.singleFile)})
+-}
+\ No newline at end of file
+diff --git a/base/build-system/google-services/build.gradle b/base/build-system/google-services/build.gradle
+index e5afe75..663364e 100644
+--- a/base/build-system/google-services/build.gradle
++++ b/base/build-system/google-services/build.gradle
+@@ -1,7 +1,4 @@
+ apply plugin: 'groovy'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'idea'
+-apply plugin: 'jacoco'
+ 
+ dependencies {
+     compile gradleApi()
+@@ -16,13 +13,11 @@ ext {
+ 
+ group = 'com.google.gms'
+ archivesBaseName = 'google-services'
+-version = rootProject.ext.buildVersion
++version = '1.5.0'
+ 
+ project.ext.pomName = 'Gradle Plug-in for Google Services'
+ project.ext.pomDesc = 'Gradle plug-in for Google Services'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+ 
+ groovydoc {
+     exclude     "**/internal/**"
+diff --git a/base/build-system/gradle-core/build.gradle b/base/build-system/gradle-core/build.gradle
+index 2505e6d..7e3a673 100644
+--- a/base/build-system/gradle-core/build.gradle
++++ b/base/build-system/gradle-core/build.gradle
+@@ -1,6 +1,4 @@
+ apply plugin: 'groovy'
+-apply plugin: 'jacoco'
+-apply plugin: 'clone-artifacts'
+ 
+ configurations {
+     provided
+@@ -36,13 +34,11 @@ tasks.compileJava.dependsOn ":setupGradleInIde"
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'gradle-core'
+-version = rootProject.ext.buildVersion
++version = '1.5.0'
+ 
+ project.ext.pomName = 'Core Library for Android Gradle Plug-in'
+ project.ext.pomDesc = 'Core library to build Android Gradle plugin.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+ 
+ test {
+     environment("CUSTOM_REPO", rootProject.file("../out/repo"))
+diff --git a/base/build-system/gradle-experimental/build.gradle b/base/build-system/gradle-experimental/build.gradle
+index 9e9154a..ce579e0 100644
+--- a/base/build-system/gradle-experimental/build.gradle
++++ b/base/build-system/gradle-experimental/build.gradle
+@@ -1,7 +1,4 @@
+ apply plugin: 'groovy'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'idea'
+-apply plugin: 'jacoco'
+ 
+ // Extract gradle libraries to ensure gradle-core is compatible with older version.
+ String gradleVersion = "2.5"
+@@ -29,13 +26,11 @@ dependencies {
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'gradle-experimental'
+-version = rootProject.ext.experimentalVersion
++version = '0.4.0'
+ 
+ project.ext.pomName = 'Gradle Plug-in for Android Using Component Model'
+ project.ext.pomDesc = 'Gradle plug-in to build Android applications.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+ 
+ jar.manifest.attributes("Plugin-Version": version)
+ jar.manifest.attributes("Inception-Date":"${Calendar.getInstance().get(Calendar.YEAR)}:" +
+diff --git a/base/build-system/gradle/build.gradle b/base/build-system/gradle/build.gradle
+index 5bcf41f..b36e23e 100644
+--- a/base/build-system/gradle/build.gradle
++++ b/base/build-system/gradle/build.gradle
+@@ -1,8 +1,4 @@
+ apply plugin: 'groovy'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'idea'
+-apply plugin: 'jacoco'
+-apply plugin: 'license-report'
+ 
+ dependencies {
+     compile project(':base:gradle-core')
+@@ -14,14 +10,11 @@ dependencies {
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'gradle'
+-version = rootProject.ext.buildVersion
++version = '1.5.0'
+ 
+ project.ext.pomName = 'Gradle Plug-in for Android'
+ project.ext.pomDesc = 'Gradle plug-in to build Android applications.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-
+ jar.manifest.attributes("Plugin-Version": version)
+ jar.manifest.attributes("Inception-Date":"${Calendar.getInstance().get(Calendar.YEAR)}:" +
+         "${Calendar.getInstance().get(Calendar.MONTH)}:${Calendar.getInstance().get(Calendar.DATE)}")
+diff --git a/base/build-system/integration-test/build.gradle b/base/build-system/integration-test/build.gradle
+index 36a3527..ae0d7e5 100644
+--- a/base/build-system/integration-test/build.gradle
++++ b/base/build-system/integration-test/build.gradle
+@@ -1,5 +1,4 @@
+ apply plugin: 'groovy'
+-apply plugin: 'jacoco'
+ 
+ repositories {
+     maven { url = uri(rootProject.cloneArtifacts.repository) }
+@@ -30,8 +29,8 @@ dependencies {
+ def testEnvironment = [
+     PROJECT_BUILD_DIR: project.buildDir,
+     CUSTOM_REPO: rootProject.file("../out/repo"),
+-    CUSTOM_GRADLE: System.env.CUSTOM_GRADLE ?: rootProject.ext.buildVersion,
+-    CUSTOM_EXPERIMENTAL_GRADLE: System.env.CUSTOM_EXPERIMENTAL_GRADLE ?:rootProject.ext.experimentalVersion,
++    CUSTOM_GRADLE: System.env.CUSTOM_GRADLE ?: '1.5.0',
++    CUSTOM_EXPERIMENTAL_GRADLE: System.env.CUSTOM_EXPERIMENTAL_GRADLE ?:'0.4.0',
+     ANDROID_HOME: System.env.ANDROID_HOME,
+     ANDROID_NDK_HOME: System.env.ANDROID_NDK_HOME,
+     CUSTOM_BUILDTOOLS: System.env.CUSTOM_BUILDTOOLS,
+diff --git a/base/build-system/integration-test/test-projects/3rdPartyTests/buildSrc/build.gradle b/base/build-system/integration-test/test-projects/3rdPartyTests/buildSrc/build.gradle
+index 82e0baa..2dfbb57 100644
+--- a/base/build-system/integration-test/test-projects/3rdPartyTests/buildSrc/build.gradle
++++ b/base/build-system/integration-test/test-projects/3rdPartyTests/buildSrc/build.gradle
+@@ -1,5 +1,4 @@
+ apply plugin: 'java'
+-apply plugin: 'idea'
+ 
+ def env = new Object() {
+     String gradleVersion
+@@ -11,4 +10,4 @@ apply from: "../../commonLocalRepo.gradle"
+ 
+ dependencies {
+     compile "com.android.tools.build:builder-test-api:$env.gradleVersion"
+-}
+\ No newline at end of file
++}
+diff --git a/base/build-system/manifest-merger/build.gradle b/base/build-system/manifest-merger/build.gradle
+index 3ca48a0..4d3d7db 100644
+--- a/base/build-system/manifest-merger/build.gradle
++++ b/base/build-system/manifest-merger/build.gradle
+@@ -1,12 +1,12 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ evaluationDependsOn(':base:sdklib')
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'manifest-merger'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:common')
+@@ -32,7 +32,4 @@ test {
+ project.ext.pomName = 'Android Tools Manifest Merger library'
+ project.ext.pomDesc = 'A Library to merge Android manifests.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/build-system/project-test-lib/build.gradle b/base/build-system/project-test-lib/build.gradle
+index 82ddb41..d7fc943 100644
+--- a/base/build-system/project-test-lib/build.gradle
++++ b/base/build-system/project-test-lib/build.gradle
+@@ -1,6 +1,4 @@
+ apply plugin: 'java'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'idea'
+ 
+ def toolingApiVersion = gradle.gradleVersion
+ dependencies {
+diff --git a/base/build-system/project-test/build.gradle b/base/build-system/project-test/build.gradle
+index b28ca5d..c4b0060 100644
+--- a/base/build-system/project-test/build.gradle
++++ b/base/build-system/project-test/build.gradle
+@@ -1,6 +1,4 @@
+ apply plugin: 'java'
+-apply plugin: 'clone-artifacts'
+-apply plugin: 'idea'
+ apply plugin: 'application'
+ 
+ dependencies {
+diff --git a/base/build.gradle b/base/build.gradle
+index b07f6c9..7a52da9 100644
+--- a/base/build.gradle
++++ b/base/build.gradle
+@@ -2,6 +2,5 @@ subprojects { Project project ->
+     // only configure leaf projects.
+     if (!project.getSubprojects().isEmpty()) return
+ 
+-    apply from: "$rootDir/buildSrc/base/baseJava.gradle"
+ }
+ 
+diff --git a/base/chartlib/build.gradle b/base/chartlib/build.gradle
+index 24c58d6..dff471b 100644
+--- a/base/chartlib/build.gradle
++++ b/base/chartlib/build.gradle
+@@ -3,7 +3,7 @@ apply plugin: 'jacoco'
+ 
+ group = 'com.android.tools.chartlib'
+ archivesBaseName = 'chartlib'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+   compile project(':base:common')
+@@ -14,4 +14,3 @@ dependencies {
+ project.ext.pomName = 'Android Tools chartlib'
+ project.ext.pomDesc = 'Library with Swing chart widgets'
+ 
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/common/build.gradle b/base/common/build.gradle
+index 904c8f9..21ef059 100644
+--- a/base/common/build.gradle
++++ b/base/common/build.gradle
+@@ -1,6 +1,6 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ dependencies {
+     compile project(':base:annotations')
+@@ -11,11 +11,8 @@ dependencies {
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'common'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ project.ext.pomName = 'Android Tools common library'
+ project.ext.pomDesc = 'common library used by other Android tools libraries.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/ddmlib/build.gradle b/base/ddmlib/build.gradle
+index fd300c1..5695891 100644
+--- a/base/ddmlib/build.gradle
++++ b/base/ddmlib/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools.ddms'
+ archivesBaseName = 'ddmlib'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:common')
+@@ -23,6 +23,3 @@ sourceSets {
+ project.ext.pomName = 'Android Tools ddmlib'
+ project.ext.pomDesc = 'Library providing APIs to talk to Android devices'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/device_validator/dvlib/build.gradle b/base/device_validator/dvlib/build.gradle
+index 4111d48..4feee01 100644
+--- a/base/device_validator/dvlib/build.gradle
++++ b/base/device_validator/dvlib/build.gradle
+@@ -1,6 +1,6 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ dependencies {
+     compile project(':base:common')
+@@ -9,14 +9,10 @@ dependencies {
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'dvlib'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ // configure the manifest of the sdkJar task
+-sdkJar.manifest.attributes("Main-Class": "com.android.validator.DeviceValidator")
+ 
+ project.ext.pomName = 'Android Tools dvlib'
+ project.ext.pomDesc = 'A Library to manage the Android device database XML files.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/draw9patch/build.gradle b/base/draw9patch/build.gradle
+index b54a7f0..0a2fd6b 100644
+--- a/base/draw9patch/build.gradle
++++ b/base/draw9patch/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'draw9patch'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     testCompile 'junit:junit:4.12'
+@@ -15,16 +15,3 @@ sourceSets {
+     test.resources.srcDir 'src/test/java'
+ }
+ 
+-sdk {
+-    linux {
+-        item('etc/draw9patch') { executable true}
+-    }
+-    mac {
+-        item('etc/draw9patch') { executable true}
+-    }
+-    windows {
+-        item 'etc/draw9patch.bat'
+-    }
+-}
+-
+-sdkJar.manifest.attributes("Main-Class": "com.android.draw9patch.Application")
+diff --git a/base/jack/jack-api/build.gradle b/base/jack/jack-api/build.gradle
+index d5bf9de..f7f2260 100644
+--- a/base/jack/jack-api/build.gradle
++++ b/base/jack/jack-api/build.gradle
+@@ -17,9 +17,6 @@ compileJava.classpath += configurations.provided
+ project.ext.pomName = 'Android Jack API'
+ project.ext.pomDesc = 'API to dynamically load Jack'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+ javadoc {
+     classpath += configurations.provided
+diff --git a/base/jack/jill-api/build.gradle b/base/jack/jill-api/build.gradle
+index 5c0edf4..5668fdc 100644
+--- a/base/jack/jill-api/build.gradle
++++ b/base/jack/jill-api/build.gradle
+@@ -17,9 +17,6 @@ compileJava.classpath += configurations.provided
+ project.ext.pomName = 'Android Jill API'
+ project.ext.pomDesc = 'API to dynamically load Jill'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+ javadoc {
+     classpath += configurations.provided
+diff --git a/base/jobb/build.gradle b/base/jobb/build.gradle
+index bf112f1..ba3eaba 100644
+--- a/base/jobb/build.gradle
++++ b/base/jobb/build.gradle
+@@ -1,5 +1,5 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ dependencies {
+     compile project(':external:fat32lib')
+@@ -7,19 +7,7 @@ dependencies {
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'jobb'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ // configure the manifest of the sdkJar task
+-sdkJar.manifest.attributes("Main-Class": "com.android.jobb.Main")
+ 
+-sdk {
+-    linux {
+-        item('etc/jobb') { executable true }
+-    }
+-    mac {
+-        item('etc/jobb') { executable true }
+-    }
+-    windows {
+-        item 'etc/jobb.bat'
+-    }
+-}
+diff --git a/base/layoutlib-api/build.gradle b/base/layoutlib-api/build.gradle
+index 2ac4682..8fdaabc 100644
+--- a/base/layoutlib-api/build.gradle
++++ b/base/layoutlib-api/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools.layoutlib'
+ archivesBaseName = 'layoutlib-api'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:common')
+@@ -18,7 +18,4 @@ dependencies {
+ project.ext.pomName = 'Android Tools layoutlib-api'
+ project.ext.pomDesc = 'Library to use the rendering library for Android layouts: layoutlib'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/legacy/ant-tasks/build.gradle b/base/legacy/ant-tasks/build.gradle
+index 65288b6..38e6674 100644
+--- a/base/legacy/ant-tasks/build.gradle
++++ b/base/legacy/ant-tasks/build.gradle
+@@ -1,9 +1,9 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools.build'
+ archivesBaseName = 'ant-tasks'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:manifest-merger')
+diff --git a/base/legacy/archquery/build.gradle b/base/legacy/archquery/build.gradle
+index f38f236..1f17700 100644
+--- a/base/legacy/archquery/build.gradle
++++ b/base/legacy/archquery/build.gradle
+@@ -1,9 +1,8 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'archquery'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ // configure the manifest of the sdkJar task.
+-sdkJar.manifest.attributes("Main-Class": "com.android.archquery.Main")
+diff --git a/base/lint/cli/build.gradle b/base/lint/cli/build.gradle
+index 7d7fe85..5ffa9e5 100644
+--- a/base/lint/cli/build.gradle
++++ b/base/lint/cli/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools.lint'
+ archivesBaseName = 'lint'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:lint-checks')
+@@ -20,24 +20,10 @@ test {
+     maxParallelForks = Runtime.runtime.availableProcessors() / 2
+ }
+ 
+-sdk {
+-    linux {
+-        item('etc/lint') { executable true }
+-    }
+-    mac {
+-        item('etc/lint') { executable true }
+-    }
+-    windows {
+-        item 'etc/lint.bat'
+-    }
+-}
++
+ 
+ // configure the manifest of the sdkJar task.
+-sdkJar.manifest.attributes("Main-Class": "com.android.tools.lint.Main")
+ 
+ project.ext.pomName = 'Android Lint Tool'
+ project.ext.pomDesc = 'Lint tools. Both a Command line tool and a library to add lint features to other tools'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/lint/libs/lint-api/build.gradle b/base/lint/libs/lint-api/build.gradle
+index df9d553..2ab953e 100644
+--- a/base/lint/libs/lint-api/build.gradle
++++ b/base/lint/libs/lint-api/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools.lint'
+ archivesBaseName = 'lint-api'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:sdk-common')
+@@ -23,7 +23,4 @@ sourceSets {
+ project.ext.pomName = 'Android Tools Lint API'
+ project.ext.pomDesc = 'API to build lint checks'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/lint/libs/lint-checks/build.gradle b/base/lint/libs/lint-checks/build.gradle
+index b71cb35..b5f24dc 100644
+--- a/base/lint/libs/lint-checks/build.gradle
++++ b/base/lint/libs/lint-checks/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools.lint'
+ archivesBaseName = 'lint-checks'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:lint-api')
+@@ -19,7 +19,4 @@ sourceSets {
+ project.ext.pomName = 'Android Lint Checks'
+ project.ext.pomDesc = 'Checks for Android Lint'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/lint/libs/lint-tests/build.gradle b/base/lint/libs/lint-tests/build.gradle
+index 7781b8a..c55c01f 100644
+--- a/base/lint/libs/lint-tests/build.gradle
++++ b/base/lint/libs/lint-tests/build.gradle
+@@ -3,7 +3,7 @@ apply plugin: 'jacoco'
+ 
+ group = 'com.android.tools.lint'
+ archivesBaseName = 'lint-tests'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:lint')
+@@ -24,7 +24,4 @@ sourceSets {
+ project.ext.pomName = 'Android Tools Lint Test API'
+ project.ext.pomDesc = 'API to build lint check tests'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/misc/screenshot2/build.gradle b/base/misc/screenshot2/build.gradle
+index 51a060f..8704ad4 100644
+--- a/base/misc/screenshot2/build.gradle
++++ b/base/misc/screenshot2/build.gradle
+@@ -1,22 +1,11 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'screenshot2'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:ddmlib')
+ }
+ 
+-sdk {
+-    linux {
+-        item('etc/screenshot2') { executable true }
+-    }
+-    mac {
+-        item('etc/screenshot2') { executable true }
+-    }
+-}
+-
+-// configure the manifest of the sdkJar task.
+-sdkJar.manifest.attributes("Main-Class": "com.android.screenshot.Screenshot")
+diff --git a/base/ninepatch/build.gradle b/base/ninepatch/build.gradle
+index 7699e1b..17a49b6 100644
+--- a/base/ninepatch/build.gradle
++++ b/base/ninepatch/build.gradle
+@@ -1,10 +1,10 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'ninepatch'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     testCompile 'junit:junit:4.12'
+diff --git a/base/perflib/build.gradle b/base/perflib/build.gradle
+index a923c0d..dae11eb 100644
+--- a/base/perflib/build.gradle
++++ b/base/perflib/build.gradle
+@@ -3,7 +3,7 @@ apply plugin: 'jacoco'
+ 
+ group = 'com.android.tools.perflib'
+ archivesBaseName = 'perflib'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:ddmlib')
+@@ -17,4 +17,3 @@ dependencies {
+ project.ext.pomName = 'Android Tools perflib'
+ project.ext.pomDesc = 'Library to handle android performance data'
+ 
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/rpclib/build.gradle b/base/rpclib/build.gradle
+index bccfc24..69be33b 100644
+--- a/base/rpclib/build.gradle
++++ b/base/rpclib/build.gradle
+@@ -2,7 +2,7 @@ apply plugin: 'java'
+ 
+ group = 'com.android.tools.rpclib'
+ archivesBaseName = 'rpclib'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+   compile project(':base:common')
+@@ -13,4 +13,3 @@ dependencies {
+ project.ext.pomName = 'Android Tools rpclib'
+ project.ext.pomDesc = 'Library to handle Gaze RPC'
+ 
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/base/rule-api/build.gradle b/base/rule-api/build.gradle
+index ed2f763..b7937cc 100644
+--- a/base/rule-api/build.gradle
++++ b/base/rule-api/build.gradle
+@@ -1,9 +1,9 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'rule-api'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:common')
+diff --git a/base/sdk-common/build.gradle b/base/sdk-common/build.gradle
+index cc946c4..f432f69 100644
+--- a/base/sdk-common/build.gradle
++++ b/base/sdk-common/build.gradle
+@@ -1,11 +1,11 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ apply plugin: 'application'
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'sdk-common'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ mainClassName = 'com.android.ide.common.vectordrawable.VdPreview'
+ 
+ dependencies {
+@@ -23,7 +23,4 @@ dependencies {
+ project.ext.pomName = 'Android Tools sdk-common library'
+ project.ext.pomDesc = 'sdk-common library used by other Android tools libraries.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/sdk-common/generate-locale-data/build.gradle b/base/sdk-common/generate-locale-data/build.gradle
+index 2531629..7535bcb 100644
+--- a/base/sdk-common/generate-locale-data/build.gradle
++++ b/base/sdk-common/generate-locale-data/build.gradle
+@@ -1,5 +1,5 @@
+ apply plugin: 'java'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ dependencies {
+     compile project(':base:sdk-common')
+@@ -9,5 +9,4 @@ dependencies {
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'generate-locale-data'
+-version = rootProject.ext.baseVersion
+-sdkJar.manifest.attributes("Main-Class": "com.android.ide.common.generate.locale.LocaleTableGenerator")
++version = '24.5.0'
+diff --git a/base/sdklib/build.gradle b/base/sdklib/build.gradle
+index bc76ff4..fd3c225 100644
+--- a/base/sdklib/build.gradle
++++ b/base/sdklib/build.gradle
+@@ -1,12 +1,12 @@
+ apply plugin: 'java'
+ apply plugin: 'jacoco'
+-apply plugin: 'sdk-java-lib'
++
+ 
+ evaluationDependsOn(':base:dvlib')
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'sdklib'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:layoutlib-api')
+@@ -62,7 +62,4 @@ copyXsd.doLast {
+ project.ext.pomName = 'Android Tools sdklib'
+ project.ext.pomDesc = 'A library to parse and download the Android SDK.'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+ 
+diff --git a/base/sdklib/test.gradle b/base/sdklib/test.gradle
+index 4324376..1c402d0 100755
+--- a/base/sdklib/test.gradle
++++ b/base/sdklib/test.gradle
+@@ -5,7 +5,7 @@ evaluationDependsOn(':base:dvlib')
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'sdklib-test'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:sdklib')
+diff --git a/base/templates/build.gradle b/base/templates/build.gradle
+index 238c922..e69de29 100644
+--- a/base/templates/build.gradle
++++ b/base/templates/build.gradle
+@@ -1,10 +0,0 @@
+-apply plugin: 'sdk-files'
+-
+-sdk {
+-    common {
+-        item('eclipse/projects')   { into 'templates/projects' }
+-        item('eclipse/activities') { into 'templates/activities' }
+-        item('eclipse/gradle')     { into 'templates/gradle' }
+-        item('eclipse/other')      { into 'templates/other' }
+-    }
+-}
+\ No newline at end of file
+diff --git a/base/testutils/build.gradle b/base/testutils/build.gradle
+index b69a4fb..8b8deb3 100644
+--- a/base/testutils/build.gradle
++++ b/base/testutils/build.gradle
+@@ -3,7 +3,7 @@ apply plugin: 'jacoco'
+ 
+ group = 'com.android.tools'
+ archivesBaseName = 'testutils'
+-version = rootProject.ext.baseVersion
++version = '24.5.0'
+ 
+ dependencies {
+     compile project(':base:common')
+@@ -19,6 +19,3 @@ sourceSets {
+ project.ext.pomName = 'Android Tools Test Utilities'
+ project.ext.pomDesc = 'API used by lint testing infrastructure'
+ 
+-apply from: "$rootDir/buildSrc/base/publish.gradle"
+-apply from: "$rootDir/buildSrc/base/bintray.gradle"
+-apply from: "$rootDir/buildSrc/base/javadoc.gradle"
+diff --git a/build.gradle b/build.gradle
+index a6c30b5..bf35058 100644
+--- a/build.gradle
++++ b/build.gradle
+@@ -1,15 +1,6 @@
+-apply plugin: 'clone-artifacts'
+ 
+ // Currently, the minimum requirement to run Android SDK tools is Java 1.6
+ // So make sure that we are compiling with 1.6
+-task('checkJavaVersion') << {
+-    def jvmVersion = System.getProperty('java.version')
+-    def requiredVersion = System.getenv('JAVA_FOR_TESTS') ?: '1.6'
+-    if (!jvmVersion.startsWith(requiredVersion)) {
+-        throw new RuntimeException("Tools need to be compiled with Java $requiredVersion, you are using Java $jvmVersion.")
+-    }
+-}
+-final def checkJavaVersionTask = tasks['checkJavaVersion']
+ 
+ allprojects { subproject ->
+     tasks.withType(JavaForkOptions) {
+@@ -23,15 +14,10 @@ allprojects { subproject ->
+         final def buildTasks = ['build', 'compileJava', 'compileGroovy', 'classes', 'assemble', 'javadoc', 'groovydoc', 'check']
+         // Task.doFirst does not run if the task has no work to do. Need to be more aggressive than that.
+         // Some projects won't have all of these tasks, so need to use findByName.
+-        buildTasks.each { subproject.tasks.findByName(it)?.dependsOn(checkJavaVersionTask) }
++        buildTasks.each { subproject.tasks.findByName(it) }
+     }
+ }
+ 
+-// artifact cloning destinations
+-cloneArtifacts {
+-    repository = "$rootDir/../prebuilts/tools/common/m2/repository"
+-}
+-
+ if (System.env.USE_EXTERNAL_REPO != null) {
+   allprojects {
+     repositories {
+@@ -55,7 +41,7 @@ if (System.env.DIST_DIR != null && System.env.OUT_DIR != null) {
+     ext.androidHostDist = file(System.env.DIST_DIR)
+ } else {
+     // ext.androidHostOut is shared by all tools/{base,build,swt} gradle projects/
+-    ext.androidHostOut = file("$rootDir/../out")
++    ext.androidHostOut = file("$rootDir/out")
+     ext.androidHostDist = new File(ext.androidHostOut, "dist")
+ }
+ 
+@@ -64,14 +50,9 @@ if (System.env.DIST_DIR != null && System.env.OUT_DIR != null) {
+ buildDir = new File(ext.androidHostOut, "build/root")
+ 
+ 
+-// apply this after the buildDir has been changed.
+-apply plugin: 'sdk-tools'
+-
+ 
+ ext.localRepo = project.hasProperty('localRepo') ? localRepo : "$ext.androidHostOut/repo"
+ 
+-apply from: "$rootDir/buildSrc/base/version.gradle"
+-
+ subprojects { Project project ->
+     // Change buildDir first so that all plugins pick up the new value.
+     project.buildDir = project.file("$project.parent.buildDir/../$project.name/build")
+@@ -117,17 +98,12 @@ task setupGradleInIde << {
+     if (gradleDistLink.exists()) {
+         gradleDistLink.delete()
+     }
+-    String link = dir.path.substring(project.ext.androidHostOut.path.length() + 1)
+-    String command = "ln -s $link ${gradleDistLink.path}"
+-    command.execute()
+ }
+ 
+ // basic task for custom distribution of project should the build server.
+ task dist << {
+ }
+ 
+-apply plugin: 'offline-repo'
+-
+ task clean << {
+   delete 'build'
+ 
+@@ -137,7 +113,6 @@ task clean << {
+     }
+   }
+ }
+-apply plugin: 'presubmit-runner'
+ // Task for initializing a fresh repo.
+ task init {
+   dependsOn prepareRepo
+@@ -150,4 +125,3 @@ task init {
+ // The hierarchy viewer tests require loading SWT jar files.
+ // That fails with the error saying "can't load 32 bit library on 64 bit JVM
+ // Disable these tests from running until that is fixed
+-tasks.findByPath(':swt:hierarchyviewer2lib:test').enabled = false
diff --git a/debian/patches/disable-lint.patch b/debian/patches/disable-lint.patch
new file mode 100644
index 0000000..c913129
--- /dev/null
+++ b/debian/patches/disable-lint.patch
@@ -0,0 +1,9620 @@
+From: Markus Koschany <apo at debian.org>
+Date: Wed, 17 Feb 2016 18:55:28 +0100
+Subject: disable lint
+
+Temporarily necessary until lombok-ast is available in Debian and Lint can be
+built from source.
+
+Forwarded: not-needed
+---
+ .../com/android/builder/model/AndroidProject.java  |    6 -
+ base/build-system/gradle-core/build.gradle         |    2 +-
+ .../com/android/build/gradle/AndroidConfig.java    |    4 -
+ .../gradle/internal/ApplicationTaskManager.java    |    1 -
+ .../build/gradle/internal/LibraryTaskManager.java  |   73 +-
+ .../build/gradle/internal/LintGradleClient.java    |  198 --
+ .../build/gradle/internal/LintGradleProject.java   |  658 -----
+ .../build/gradle/internal/LintGradleRequest.java   |   69 -
+ .../android/build/gradle/internal/TaskManager.java |  108 +-
+ .../build/gradle/internal/dsl/LintOptions.java     |  798 ------
+ .../internal/model/DefaultAndroidProject.java      |   11 -
+ .../build/gradle/internal/model/ModelBuilder.java  |    5 -
+ .../internal/variant/LibraryVariantData.java       |   15 +-
+ .../build/gradle/tasks/ExtractAnnotations.groovy   |  265 --
+ .../build/gradle/tasks/GroovyGradleDetector.java   |  242 --
+ .../com/android/build/gradle/tasks/Lint.groovy     |  295 ---
+ .../build/gradle/tasks/PackageApplication.java     |   46 -
+ .../build/gradle/tasks/ResourceUsageAnalyzer.java  | 2568 --------------------
+ .../build/gradle/tasks/ShrinkResources.groovy      |  220 --
+ .../gradle/tasks/annotations/ApiDatabase.java      |  356 ---
+ .../annotations/ExtractAnnotationsDriver.java      |  400 ---
+ .../build/gradle/tasks/annotations/Extractor.java  | 2484 -------------------
+ .../gradle/tasks/annotations/TypedefCollector.java |  154 --
+ .../gradle/tasks/annotations/TypedefRemover.java   |  164 --
+ .../com/android/build/gradle/BaseExtension.java    |   19 -
+ 25 files changed, 4 insertions(+), 9157 deletions(-)
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleRequest.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/dsl/LintOptions.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ExtractAnnotations.groovy
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/GroovyGradleDetector.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/Lint.groovy
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ResourceUsageAnalyzer.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ShrinkResources.groovy
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ApiDatabase.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ExtractAnnotationsDriver.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/Extractor.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefCollector.java
+ delete mode 100644 base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefRemover.java
+
+diff --git a/base/build-system/builder-model/src/main/java/com/android/builder/model/AndroidProject.java b/base/build-system/builder-model/src/main/java/com/android/builder/model/AndroidProject.java
+index 068f365..2dfa09c 100644
+--- a/base/build-system/builder-model/src/main/java/com/android/builder/model/AndroidProject.java
++++ b/base/build-system/builder-model/src/main/java/com/android/builder/model/AndroidProject.java
+@@ -185,12 +185,6 @@ public interface AndroidProject {
+     AaptOptions getAaptOptions();
+ 
+     /**
+-     * Returns the lint options.
+-     */
+-    @NonNull
+-    LintOptions getLintOptions();
+-
+-    /**
+      * Returns the dependencies that were not successfully resolved. The returned list gets
+      * populated only if the system property {@link #PROPERTY_BUILD_MODEL_ONLY} has been
+      * set to {@code true}.
+diff --git a/base/build-system/gradle-core/build.gradle b/base/build-system/gradle-core/build.gradle
+index e36483b..f8ed473 100644
+--- a/base/build-system/gradle-core/build.gradle
++++ b/base/build-system/gradle-core/build.gradle
+@@ -16,7 +16,7 @@ ext.proguardVersion = "5.2.1"
+ 
+ dependencies {
+     compile project(':base:builder')
+-    compile project(':base:lint')
++    //compile project(':base:lint')
+     compile "net.sf.proguard:proguard-gradle:${project.ext.proguardVersion}"
+ 
+     // Add gradleApi to classpath for compilation, but use provided configuration so that groovy is
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/AndroidConfig.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/AndroidConfig.java
+index ec7373f..46eca5e 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/AndroidConfig.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/AndroidConfig.java
+@@ -26,7 +26,6 @@ import com.android.build.gradle.internal.dsl.AdbOptions;
+ import com.android.build.gradle.internal.dsl.CoreBuildType;
+ import com.android.build.gradle.internal.dsl.CoreProductFlavor;
+ import com.android.build.gradle.internal.dsl.DexOptions;
+-import com.android.build.gradle.internal.dsl.LintOptions;
+ import com.android.build.gradle.internal.dsl.PackagingOptions;
+ import com.android.build.gradle.internal.dsl.PreprocessingOptions;
+ import com.android.build.gradle.internal.dsl.Splits;
+@@ -99,9 +98,6 @@ public interface AndroidConfig {
+     /** JaCoCo options. */
+     JacocoExtension getJacoco();
+ 
+-    /** Lint options. */
+-    LintOptions getLintOptions();
+-
+     /** Packaging options. */
+     PackagingOptions getPackagingOptions();
+ 
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/ApplicationTaskManager.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/ApplicationTaskManager.java
+index 649c43e..3badeb9 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/ApplicationTaskManager.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/ApplicationTaskManager.java
+@@ -216,7 +216,6 @@ public class ApplicationTaskManager extends TaskManager {
+                 new Recorder.Block<Void>() {
+                     @Override
+                     public Void call() {
+-                        createLintTasks(tasks, variantScope);
+                         return null;
+                     }
+                 });
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LibraryTaskManager.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LibraryTaskManager.java
+index 2f2c7a3..f2af17d 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LibraryTaskManager.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LibraryTaskManager.java
+@@ -36,7 +36,7 @@ import com.android.build.gradle.internal.variant.BaseVariantOutputData;
+ import com.android.build.gradle.internal.variant.LibVariantOutputData;
+ import com.android.build.gradle.internal.variant.LibraryVariantData;
+ import com.android.build.gradle.internal.variant.VariantHelper;
+-import com.android.build.gradle.tasks.ExtractAnnotations;
++//import com.android.build.gradle.tasks.ExtractAnnotations;
+ import com.android.build.gradle.tasks.MergeResources;
+ import com.android.builder.core.AndroidBuilder;
+ import com.android.builder.core.BuilderConstants;
+@@ -306,26 +306,9 @@ public class LibraryTaskManager extends TaskManager {
+ 
+                 });
+ 
+-        // copy lint.jar into the bundle folder
+-        Copy lintCopy = project.getTasks().create(
+-                variantScope.getTaskName("copy", "Lint"), Copy.class);
+-        lintCopy.dependsOn(LINT_COMPILE);
+-        lintCopy.from(new File(
+-                variantScope.getGlobalScope().getIntermediatesDir(),
+-                "lint/lint.jar"));
+-        lintCopy.into(new File(
+-                variantScope.getGlobalScope().getIntermediatesDir(),
+-                DIR_BUNDLES + "/" + dirName));
+ 
+         final Zip bundle = project.getTasks().create(variantScope.getTaskName("bundle"), Zip.class);
+ 
+-        if (variantData.getVariantDependency().isAnnotationsPresent()) {
+-            libVariantData.generateAnnotationsTask =
+-                    createExtractAnnotations(project, variantData);
+-        }
+-        if (libVariantData.generateAnnotationsTask != null) {
+-            bundle.dependsOn(libVariantData.generateAnnotationsTask);
+-        }
+ 
+         final boolean instrumented = variantConfig.getBuildType().isTestCoverageEnabled();
+ 
+@@ -438,18 +421,11 @@ public class LibraryTaskManager extends TaskManager {
+                                 jar.exclude(packageName + "/Manifest$*.class");
+                                 jar.exclude(packageName + "/BuildConfig.class");
+                             }
+-
+-                            if (libVariantData.generateAnnotationsTask != null) {
+-                                // In case extract annotations strips out private typedef annotation classes
+-                                jar.dependsOn(libVariantData.generateAnnotationsTask);
+-                            }
+                             return null;
+                         }
+                     });
+         }
+ 
+-        bundle.dependsOn(packageRes.getName(), packageRenderscript, lintCopy, packageJniLibs,
+-                mergeProGuardFileTask);
+         TaskManager.optionalDependsOn(bundle, pcData.getClassGeneratingTasks());
+         TaskManager.optionalDependsOn(bundle, pcData.getLibraryGeneratingTasks());
+ 
+@@ -551,58 +527,11 @@ public class LibraryTaskManager extends TaskManager {
+                 new Recorder.Block<Void>() {
+                     @Override
+                     public Void call() throws Exception {
+-                        createLintTasks(tasks, variantScope);
+                         return null;
+                     }
+                 });
+     }
+ 
+-    public ExtractAnnotations createExtractAnnotations(
+-            final Project project,
+-            final BaseVariantData variantData) {
+-        final GradleVariantConfiguration config = variantData.getVariantConfiguration();
+-
+-        final ExtractAnnotations task = project.getTasks().create(
+-                variantData.getScope().getTaskName("extract", "Annotations"),
+-                ExtractAnnotations.class);
+-        task.setDescription(
+-                "Extracts Android annotations for the " + variantData.getVariantConfiguration()
+-                        .getFullName()
+-                        + " variant into the archive file");
+-        task.setGroup(BasePlugin.BUILD_GROUP);
+-        task.variant = variantData;
+-        task.setDestinationDir(new File(
+-                variantData.getScope().getGlobalScope().getIntermediatesDir(),
+-                ANNOTATIONS + "/" + config.getDirName()));
+-        task.output = new File(task.getDestinationDir(), FN_ANNOTATIONS_ZIP);
+-        task.classDir = new File(variantData.getScope().getGlobalScope().getIntermediatesDir(),
+-                "classes/" + variantData.getVariantConfiguration().getDirName());
+-        task.setSource(variantData.getJavaSources());
+-        task.encoding = getExtension().getCompileOptions().getEncoding();
+-        task.setSourceCompatibility(
+-                getExtension().getCompileOptions().getSourceCompatibility().toString());
+-        ConventionMappingHelper.map(task, "classpath", new Callable<ConfigurableFileCollection>() {
+-            @Override
+-            public ConfigurableFileCollection call() throws Exception {
+-                return project.files(androidBuilder.getCompileClasspath(config));
+-            }
+-        });
+-        task.dependsOn(variantData.getScope().getJavacTask().getName());
+-
+-        // Setup the boot classpath just before the task actually runs since this will
+-        // force the sdk to be parsed. (Same as in compileTask)
+-        task.doFirst(new Action<Task>() {
+-            @Override
+-            public void execute(Task task) {
+-                if (task instanceof ExtractAnnotations) {
+-                    ExtractAnnotations extractAnnotations = (ExtractAnnotations) task;
+-                    extractAnnotations.bootClasspath = androidBuilder.getBootClasspathAsStrings();
+-                }
+-            }
+-        });
+-
+-        return task;
+-    }
+ 
+     private Task getAssembleDefault() {
+         if (assembleDefault == null) {
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java
+deleted file mode 100644
+index 34d2240..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java
++++ /dev/null
+@@ -1,198 +0,0 @@
+-/*
+- * Copyright (C) 2013 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.build.gradle.internal;
+-
+-import static com.android.builder.model.AndroidProject.FD_INTERMEDIATES;
+-import static java.io.File.separator;
+-
+-import com.android.annotations.NonNull;
+-import com.android.annotations.Nullable;
+-import com.android.builder.model.AndroidProject;
+-import com.android.builder.model.Variant;
+-import com.android.tools.lint.LintCliClient;
+-import com.android.tools.lint.LintCliFlags;
+-import com.android.tools.lint.Warning;
+-import com.android.tools.lint.client.api.IssueRegistry;
+-import com.android.tools.lint.client.api.LintRequest;
+-import com.android.tools.lint.detector.api.Issue;
+-import com.android.tools.lint.detector.api.Project;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-import com.google.common.collect.Sets;
+-
+-import java.io.File;
+-import java.io.IOException;
+-import java.util.Collections;
+-import java.util.List;
+-import java.util.Map;
+-
+-public class LintGradleClient extends LintCliClient {
+-    private final AndroidProject mModelProject;
+-    private final String mVariantName;
+-    private final org.gradle.api.Project mGradleProject;
+-    private List<File> mCustomRules = Lists.newArrayList();
+-    private File mSdkHome;
+-
+-    public LintGradleClient(
+-            @NonNull IssueRegistry registry,
+-            @NonNull LintCliFlags flags,
+-            @NonNull org.gradle.api.Project gradleProject,
+-            @NonNull AndroidProject modelProject,
+-            @Nullable File sdkHome,
+-            @Nullable String variantName) {
+-        super(flags);
+-        mGradleProject = gradleProject;
+-        mModelProject = modelProject;
+-        mVariantName = variantName;
+-        mSdkHome = sdkHome;
+-        mRegistry = registry;
+-    }
+-
+-    public void setCustomRules(List<File> customRules) {
+-        mCustomRules = customRules;
+-    }
+-
+-    @NonNull
+-    @Override
+-    public List<File> findRuleJars(@NonNull Project project) {
+-        return mCustomRules;
+-    }
+-
+-    @NonNull
+-    @Override
+-    protected Project createProject(@NonNull File dir, @NonNull File referenceDir) {
+-        // Should not be called by lint since we supply an explicit set of projects
+-        // to the LintRequest
+-        throw new IllegalStateException();
+-    }
+-
+-    @Override
+-    public File getSdkHome() {
+-        if (mSdkHome != null) {
+-            return mSdkHome;
+-        }
+-        return super.getSdkHome();
+-    }
+-
+-    @Override
+-    @Nullable
+-    public File getCacheDir(boolean create) {
+-        File dir = new File(mGradleProject.getRootProject().getBuildDir(),
+-                FD_INTERMEDIATES + separator + "lint-cache"); //$NON-NLS-1$
+-        if (dir.exists() || create && dir.mkdirs()) {
+-            return dir;
+-        }
+-
+-        return super.getCacheDir(create);
+-    }
+-
+-    @Override
+-    @NonNull
+-    protected LintRequest createLintRequest(@NonNull List<File> files) {
+-        return new LintGradleRequest(this, mModelProject, mGradleProject, mVariantName, files);
+-    }
+-
+-    /** Run lint with the given registry and return the resulting warnings */
+-    @NonNull
+-    public List<Warning> run(@NonNull IssueRegistry registry) throws IOException {
+-        run(registry, Collections.<File>emptyList());
+-        return mWarnings;
+-    }
+-
+-    /**
+-     * Given a list of results from separate variants, merge them into a single
+-     * list of warnings, and mark their
+-     * @param warningMap a map from variant to corresponding warnings
+-     * @param project the project model
+-     * @return a merged list of issues
+-     */
+-    @NonNull
+-    public static List<Warning> merge(
+-            @NonNull Map<Variant,List<Warning>> warningMap,
+-            @NonNull AndroidProject project) {
+-        // Easy merge?
+-        if (warningMap.size() == 1) {
+-            return warningMap.values().iterator().next();
+-        }
+-        int maxCount = 0;
+-        for (List<Warning> warnings : warningMap.values()) {
+-            int size = warnings.size();
+-            maxCount = Math.max(size, maxCount);
+-        }
+-        if (maxCount == 0) {
+-            return Collections.emptyList();
+-        }
+-
+-        int totalVariantCount = project.getVariants().size();
+-
+-        List<Warning> merged = Lists.newArrayListWithExpectedSize(2 * maxCount);
+-
+-        // Map fro issue to message to line number to file name to canonical warning
+-        Map<Issue,Map<String, Map<Integer, Map<String, Warning>>>> map =
+-                Maps.newHashMapWithExpectedSize(2 * maxCount);
+-
+-        for (Map.Entry<Variant,List<Warning>> entry : warningMap.entrySet()) {
+-            Variant variant = entry.getKey();
+-            List<Warning> warnings = entry.getValue();
+-            for (Warning warning : warnings) {
+-                Map<String,Map<Integer,Map<String,Warning>>> messageMap = map.get(warning.issue);
+-                if (messageMap == null) {
+-                    messageMap = Maps.newHashMap();
+-                    map.put(warning.issue, messageMap);
+-                }
+-                Map<Integer, Map<String, Warning>> lineMap = messageMap.get(warning.message);
+-                if (lineMap == null) {
+-                    lineMap = Maps.newHashMap();
+-                    messageMap.put(warning.message, lineMap);
+-                }
+-                Map<String, Warning> fileMap = lineMap.get(warning.line);
+-                if (fileMap == null) {
+-                    fileMap = Maps.newHashMap();
+-                    lineMap.put(warning.line, fileMap);
+-                }
+-                String fileName = warning.file != null ? warning.file.getName() : "<unknown>";
+-                Warning canonical = fileMap.get(fileName);
+-                if (canonical == null) {
+-                    canonical = warning;
+-                    fileMap.put(fileName, canonical);
+-                    canonical.variants = Sets.newHashSet();
+-                    canonical.gradleProject = project;
+-                    merged.add(canonical);
+-                }
+-                canonical.variants.add(variant);
+-            }
+-        }
+-
+-        // Clear out variants on any nodes that define all
+-        for (Warning warning : merged) {
+-            if (warning.variants != null && warning.variants.size() == totalVariantCount) {
+-                // If this error is present in all variants, just clear it out
+-                warning.variants = null;
+-            }
+-
+-        }
+-
+-        Collections.sort(merged);
+-        return merged;
+-    }
+-
+-    @Override
+-    protected void addProgressPrinter() {
+-        // No progress printing from the Gradle lint task; gradle tasks
+-        // do not really do that, even for long-running jobs.
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java
+deleted file mode 100644
+index 8193a8e..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java
++++ /dev/null
+@@ -1,658 +0,0 @@
+-package com.android.build.gradle.internal;
+-
+-import static com.android.SdkConstants.APPCOMPAT_LIB_ARTIFACT;
+-import static com.android.SdkConstants.SUPPORT_LIB_ARTIFACT;
+-import static java.io.File.separatorChar;
+-
+-import com.android.annotations.NonNull;
+-import com.android.annotations.Nullable;
+-import com.android.builder.model.AndroidArtifact;
+-import com.android.builder.model.AndroidLibrary;
+-import com.android.builder.model.AndroidProject;
+-import com.android.builder.model.ApiVersion;
+-import com.android.builder.model.BuildTypeContainer;
+-import com.android.builder.model.Dependencies;
+-import com.android.builder.model.JavaLibrary;
+-import com.android.builder.model.ProductFlavor;
+-import com.android.builder.model.ProductFlavorContainer;
+-import com.android.builder.model.SourceProvider;
+-import com.android.builder.model.SourceProviderContainer;
+-import com.android.builder.model.Variant;
+-import com.android.sdklib.AndroidTargetHash;
+-import com.android.sdklib.AndroidVersion;
+-import com.android.tools.lint.detector.api.LintUtils;
+-import com.android.tools.lint.detector.api.Project;
+-import com.android.utils.Pair;
+-import com.android.utils.XmlUtils;
+-import com.google.common.base.Charsets;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Sets;
+-import com.google.common.io.Files;
+-
+-import org.w3c.dom.Document;
+-
+-import java.io.File;
+-import java.io.IOException;
+-import java.util.ArrayList;
+-import java.util.Collection;
+-import java.util.Collections;
+-import java.util.List;
+-import java.util.Set;
+-
+-/**
+- * An implementation of Lint's {@link Project} class wrapping a Gradle model (project or
+- * library)
+- */
+-public class LintGradleProject extends Project {
+-    protected AndroidVersion mMinSdkVersion;
+-    protected AndroidVersion mTargetSdkVersion;
+-
+-    private LintGradleProject(
+-            @NonNull LintGradleClient client,
+-            @NonNull File dir,
+-            @NonNull File referenceDir,
+-            @NonNull File manifest) {
+-        super(client, dir, referenceDir);
+-        mGradleProject = true;
+-        mMergeManifests = true;
+-        mDirectLibraries = Lists.newArrayList();
+-        readManifest(manifest);
+-    }
+-
+-    /**
+-     * Creates a {@link com.android.build.gradle.internal.LintGradleProject} from
+-     * the given {@link com.android.builder.model.AndroidProject} definition for
+-     * a given {@link com.android.builder.model.Variant}, and returns it along with
+-     * a set of lint custom rule jars applicable for the given model project.
+-     *
+-     * @param client the client
+-     * @param project the model project
+-     * @param variant the variant
+-     * @param gradleProject the gradle project
+-     * @return a pair of new project and list of custom rule jars
+-     */
+-    @NonNull
+-    public static Pair<LintGradleProject, List<File>> create(
+-            @NonNull LintGradleClient client,
+-            @NonNull AndroidProject project,
+-            @NonNull Variant variant,
+-            @NonNull org.gradle.api.Project gradleProject) {
+-        File dir = gradleProject.getProjectDir();
+-        AppGradleProject lintProject = new AppGradleProject(client, dir,
+-                dir, project, variant);
+-
+-        List<File> customRules = Lists.newArrayList();
+-        File appLintJar = new File(gradleProject.getBuildDir(),
+-                "lint" + separatorChar + "lint.jar");
+-        if (appLintJar.exists()) {
+-            customRules.add(appLintJar);
+-        }
+-
+-        Set<AndroidLibrary> libraries = Sets.newHashSet();
+-        Dependencies dependencies = variant.getMainArtifact().getDependencies();
+-        for (AndroidLibrary library : dependencies.getLibraries()) {
+-            lintProject.addDirectLibrary(createLibrary(client, library, libraries, customRules));
+-        }
+-
+-        return Pair.<LintGradleProject,List<File>>of(lintProject, customRules);
+-    }
+-
+-    @Override
+-    protected void initialize() {
+-        // Deliberately not calling super; that code is for ADT compatibility
+-    }
+-
+-    protected void readManifest(File manifest) {
+-        if (manifest.exists()) {
+-            try {
+-                String xml = Files.toString(manifest, Charsets.UTF_8);
+-                Document document = XmlUtils.parseDocumentSilently(xml, true);
+-                if (document != null) {
+-                    readManifest(document);
+-                }
+-            } catch (IOException e) {
+-                mClient.log(e, "Could not read manifest %1$s", manifest);
+-            }
+-        }
+-    }
+-
+-    @Override
+-    public boolean isGradleProject() {
+-        return true;
+-    }
+-
+-    protected static boolean dependsOn(@NonNull Dependencies dependencies,
+-            @NonNull String artifact) {
+-        for (AndroidLibrary library : dependencies.getLibraries()) {
+-            if (dependsOn(library, artifact)) {
+-                return true;
+-            }
+-        }
+-        return false;
+-    }
+-
+-    protected static boolean dependsOn(@NonNull AndroidLibrary library, @NonNull String artifact) {
+-        if (SUPPORT_LIB_ARTIFACT.equals(artifact)) {
+-            if (library.getJarFile().getName().startsWith("support-v4-")) {
+-                return true;
+-            }
+-
+-        } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) {
+-            File bundle = library.getBundle();
+-            if (bundle.getName().startsWith("appcompat-v7-")) {
+-                return true;
+-            }
+-        }
+-
+-        for (AndroidLibrary dependency : library.getLibraryDependencies()) {
+-            if (dependsOn(dependency, artifact)) {
+-                return true;
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    void addDirectLibrary(@NonNull Project project) {
+-        mDirectLibraries.add(project);
+-    }
+-
+-    @NonNull
+-    private static LibraryProject createLibrary(@NonNull LintGradleClient client,
+-            @NonNull AndroidLibrary library,
+-            @NonNull Set<AndroidLibrary> seen, List<File> customRules) {
+-        seen.add(library);
+-        File dir = library.getFolder();
+-        LibraryProject project = new LibraryProject(client, dir, dir, library);
+-
+-        File ruleJar = library.getLintJar();
+-        if (ruleJar.exists()) {
+-            customRules.add(ruleJar);
+-        }
+-
+-        for (AndroidLibrary dependent : library.getLibraryDependencies()) {
+-            if (!seen.contains(dependent)) {
+-                project.addDirectLibrary(createLibrary(client, dependent, seen, customRules));
+-            }
+-        }
+-
+-        return project;
+-    }
+-
+-    private static class AppGradleProject extends LintGradleProject {
+-        private AndroidProject mProject;
+-        private Variant mVariant;
+-        private List<SourceProvider> mProviders;
+-        private List<SourceProvider> mTestProviders;
+-
+-        private AppGradleProject(
+-                @NonNull LintGradleClient client,
+-                @NonNull File dir,
+-                @NonNull File referenceDir,
+-                @NonNull AndroidProject project,
+-                @NonNull Variant variant) {
+-            //TODO FIXME: handle multi-apk
+-            super(client, dir, referenceDir,
+-                    variant.getMainArtifact().getOutputs().iterator().next().getGeneratedManifest());
+-
+-            mProject = project;
+-            mVariant = variant;
+-        }
+-
+-        @Override
+-        public boolean isLibrary() {
+-            return mProject.isLibrary();
+-        }
+-
+-        @Override
+-        public AndroidProject getGradleProjectModel() {
+-            return mProject;
+-        }
+-
+-        @Override
+-        public Variant getCurrentVariant() {
+-            return mVariant;
+-        }
+-
+-        private List<SourceProvider> getSourceProviders() {
+-            if (mProviders == null) {
+-                List<SourceProvider> providers = Lists.newArrayList();
+-                AndroidArtifact mainArtifact = mVariant.getMainArtifact();
+-
+-                providers.add(mProject.getDefaultConfig().getSourceProvider());
+-
+-                for (String flavorName : mVariant.getProductFlavors()) {
+-                    for (ProductFlavorContainer flavor : mProject.getProductFlavors()) {
+-                        if (flavorName.equals(flavor.getProductFlavor().getName())) {
+-                            providers.add(flavor.getSourceProvider());
+-                            break;
+-                        }
+-                    }
+-                }
+-
+-                SourceProvider multiProvider = mainArtifact.getMultiFlavorSourceProvider();
+-                if (multiProvider != null) {
+-                    providers.add(multiProvider);
+-                }
+-
+-                String buildTypeName = mVariant.getBuildType();
+-                for (BuildTypeContainer buildType : mProject.getBuildTypes()) {
+-                    if (buildTypeName.equals(buildType.getBuildType().getName())) {
+-                        providers.add(buildType.getSourceProvider());
+-                        break;
+-                    }
+-                }
+-
+-                SourceProvider variantProvider =  mainArtifact.getVariantSourceProvider();
+-                if (variantProvider != null) {
+-                    providers.add(variantProvider);
+-                }
+-
+-                mProviders = providers;
+-            }
+-
+-            return mProviders;
+-        }
+-
+-        private List<SourceProvider> getTestSourceProviders() {
+-            if (mTestProviders == null) {
+-                List<SourceProvider> providers = Lists.newArrayList();
+-
+-                ProductFlavorContainer defaultConfig = mProject.getDefaultConfig();
+-                for (SourceProviderContainer extra : defaultConfig.getExtraSourceProviders()) {
+-                    String artifactName = extra.getArtifactName();
+-                    if (AndroidProject.ARTIFACT_ANDROID_TEST.equals(artifactName)) {
+-                        providers.add(extra.getSourceProvider());
+-                    }
+-                }
+-
+-                for (String flavorName : mVariant.getProductFlavors()) {
+-                    for (ProductFlavorContainer flavor : mProject.getProductFlavors()) {
+-                        if (flavorName.equals(flavor.getProductFlavor().getName())) {
+-                            for (SourceProviderContainer extra : flavor.getExtraSourceProviders()) {
+-                                String artifactName = extra.getArtifactName();
+-                                if (AndroidProject.ARTIFACT_ANDROID_TEST.equals(artifactName)) {
+-                                    providers.add(extra.getSourceProvider());
+-                                }
+-                            }
+-                        }
+-                    }
+-                }
+-
+-                String buildTypeName = mVariant.getBuildType();
+-                for (BuildTypeContainer buildType : mProject.getBuildTypes()) {
+-                    if (buildTypeName.equals(buildType.getBuildType().getName())) {
+-                        for (SourceProviderContainer extra : buildType.getExtraSourceProviders()) {
+-                            String artifactName = extra.getArtifactName();
+-                            if (AndroidProject.ARTIFACT_ANDROID_TEST.equals(artifactName)) {
+-                                providers.add(extra.getSourceProvider());
+-                            }
+-                        }
+-                    }
+-                }
+-
+-                mTestProviders = providers;
+-            }
+-
+-            return mTestProviders;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getManifestFiles() {
+-            if (mManifestFiles == null) {
+-                mManifestFiles = Lists.newArrayList();
+-                for (SourceProvider provider : getSourceProviders()) {
+-                    File manifestFile = provider.getManifestFile();
+-                    if (manifestFile.exists()) { // model returns path whether or not it exists
+-                        mManifestFiles.add(manifestFile);
+-                    }
+-                }
+-            }
+-
+-            return mManifestFiles;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getProguardFiles() {
+-            if (mProguardFiles == null) {
+-                ProductFlavor flavor = mProject.getDefaultConfig().getProductFlavor();
+-                mProguardFiles = Lists.newArrayList();
+-                for (File file : flavor.getProguardFiles()) {
+-                    if (file.exists()) {
+-                        mProguardFiles.add(file);
+-                    }
+-                }
+-                try {
+-                    for (File file : flavor.getConsumerProguardFiles()) {
+-                        if (file.exists()) {
+-                            mProguardFiles.add(file);
+-                        }
+-                    }
+-                } catch (Throwable t) {
+-                    // On some models, this threw
+-                    //   org.gradle.tooling.model.UnsupportedMethodException:
+-                    //    Unsupported method: BaseConfig.getConsumerProguardFiles().
+-                    // Playing it safe for a while.
+-                }
+-            }
+-
+-            return mProguardFiles;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getResourceFolders() {
+-            if (mResourceFolders == null) {
+-                mResourceFolders = Lists.newArrayList();
+-                for (SourceProvider provider : getSourceProviders()) {
+-                    Collection<File> resDirs = provider.getResDirectories();
+-                    for (File res : resDirs) {
+-                        if (res.exists()) { // model returns path whether or not it exists
+-                            mResourceFolders.add(res);
+-                        }
+-                    }
+-                }
+-
+-                for (File file : mVariant.getMainArtifact().getGeneratedResourceFolders()) {
+-                    if (file.exists()) {
+-                        mResourceFolders.add(file);
+-                    }
+-                }
+-
+-            }
+-
+-            return mResourceFolders;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getJavaSourceFolders() {
+-            if (mJavaSourceFolders == null) {
+-                mJavaSourceFolders = Lists.newArrayList();
+-                for (SourceProvider provider : getSourceProviders()) {
+-                    Collection<File> srcDirs = provider.getJavaDirectories();
+-                    for (File srcDir : srcDirs) {
+-                        if (srcDir.exists()) { // model returns path whether or not it exists
+-                            mJavaSourceFolders.add(srcDir);
+-                        }
+-                    }
+-                }
+-
+-                for (File file : mVariant.getMainArtifact().getGeneratedSourceFolders()) {
+-                    if (file.exists()) {
+-                        mJavaSourceFolders.add(file);
+-                    }
+-                }
+-            }
+-
+-            return mJavaSourceFolders;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getTestSourceFolders() {
+-            if (mTestSourceFolders == null) {
+-                mTestSourceFolders = Lists.newArrayList();
+-                for (SourceProvider provider : getTestSourceProviders()) {
+-                    Collection<File> srcDirs = provider.getJavaDirectories();
+-                    for (File srcDir : srcDirs) {
+-                        if (srcDir.exists()) { // model returns path whether or not it exists
+-                            mTestSourceFolders.add(srcDir);
+-                        }
+-                    }
+-                }
+-            }
+-
+-            return mTestSourceFolders;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getJavaClassFolders() {
+-            if (mJavaClassFolders == null) {
+-                mJavaClassFolders = new ArrayList<File>(1);
+-                File outputClassFolder = mVariant.getMainArtifact().getClassesFolder();
+-                if (outputClassFolder.exists()) {
+-                    mJavaClassFolders.add(outputClassFolder);
+-                }
+-            }
+-
+-            return mJavaClassFolders;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getJavaLibraries() {
+-            if (mJavaLibraries == null) {
+-                Collection<JavaLibrary> libs = mVariant.getMainArtifact().getDependencies().getJavaLibraries();
+-                mJavaLibraries = Lists.newArrayListWithExpectedSize(libs.size());
+-                for (JavaLibrary lib : libs) {
+-                    File jar = lib.getJarFile();
+-                    if (jar.exists()) {
+-                        mJavaLibraries.add(jar);
+-                    }
+-                }
+-            }
+-            return mJavaLibraries;
+-        }
+-
+-        @Nullable
+-        @Override
+-        public String getPackage() {
+-            // For now, lint only needs the manifest package; not the potentially variant specific
+-            // package. As part of the Gradle work on the Lint API we should make two separate
+-            // package lookup methods -- one for the manifest package, one for the build package
+-            if (mPackage == null) { // only used as a fallback in case manifest somehow is null
+-                String packageName = mProject.getDefaultConfig().getProductFlavor().getApplicationId();
+-                if (packageName != null) {
+-                    return packageName;
+-                }
+-            }
+-
+-            return mPackage; // from manifest
+-        }
+-
+-        @Override
+-        @NonNull
+-        public AndroidVersion getMinSdkVersion() {
+-            if (mMinSdkVersion == null) {
+-                ApiVersion minSdk = mVariant.getMergedFlavor().getMinSdkVersion();
+-                if (minSdk == null) {
+-                    ProductFlavor flavor = mProject.getDefaultConfig().getProductFlavor();
+-                    minSdk = flavor.getMinSdkVersion();
+-                }
+-                if (minSdk != null) {
+-                    mMinSdkVersion = LintUtils.convertVersion(minSdk, mClient.getTargets());
+-                } else {
+-                    mMinSdkVersion = super.getMinSdkVersion(); // from manifest
+-                }
+-            }
+-
+-            return mMinSdkVersion;
+-        }
+-
+-        @Override
+-        @NonNull
+-        public AndroidVersion getTargetSdkVersion() {
+-            if (mTargetSdkVersion == null) {
+-                ApiVersion targetSdk = mVariant.getMergedFlavor().getTargetSdkVersion();
+-                if (targetSdk == null) {
+-                    ProductFlavor flavor = mProject.getDefaultConfig().getProductFlavor();
+-                    targetSdk = flavor.getTargetSdkVersion();
+-                }
+-                if (targetSdk != null) {
+-                    mTargetSdkVersion = LintUtils.convertVersion(targetSdk, mClient.getTargets());
+-                } else {
+-                    mTargetSdkVersion = super.getTargetSdkVersion(); // from manifest
+-                }
+-            }
+-
+-            return mTargetSdkVersion;
+-        }
+-
+-        @Override
+-        public int getBuildSdk() {
+-            String compileTarget = mProject.getCompileTarget();
+-            AndroidVersion version = AndroidTargetHash.getPlatformVersion(compileTarget);
+-            if (version != null) {
+-                return version.getApiLevel();
+-            }
+-
+-            return super.getBuildSdk();
+-        }
+-
+-        @Nullable
+-        @Override
+-        public Boolean dependsOn(@NonNull String artifact) {
+-            if (SUPPORT_LIB_ARTIFACT.equals(artifact)) {
+-                if (mSupportLib == null) {
+-                    Dependencies dependencies = mVariant.getMainArtifact().getDependencies();
+-                    mSupportLib = dependsOn(dependencies, artifact);
+-                }
+-                return mSupportLib;
+-            } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) {
+-                if (mAppCompat == null) {
+-                    Dependencies dependencies = mVariant.getMainArtifact().getDependencies();
+-                    mAppCompat = dependsOn(dependencies, artifact);
+-                }
+-                return mAppCompat;
+-            } else {
+-                return super.dependsOn(artifact);
+-            }
+-        }
+-    }
+-
+-    private static class LibraryProject extends LintGradleProject {
+-        private AndroidLibrary mLibrary;
+-
+-        private LibraryProject(
+-                @NonNull LintGradleClient client,
+-                @NonNull File dir,
+-                @NonNull File referenceDir,
+-                @NonNull AndroidLibrary library) {
+-            super(client, dir, referenceDir, library.getManifest());
+-            mLibrary = library;
+-
+-            // TODO: Make sure we don't use this project for any source library projects!
+-            mReportIssues = false;
+-        }
+-
+-        @Override
+-        public boolean isLibrary() {
+-            return true;
+-        }
+-
+-        @Override
+-        public AndroidLibrary getGradleLibraryModel() {
+-            return mLibrary;
+-        }
+-
+-        @Override
+-        public Variant getCurrentVariant() {
+-            return null;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getManifestFiles() {
+-            if (mManifestFiles == null) {
+-                File manifest = mLibrary.getManifest();
+-                if (manifest.exists()) {
+-                    mManifestFiles = Collections.singletonList(manifest);
+-                } else {
+-                    mManifestFiles = Collections.emptyList();
+-                }
+-            }
+-
+-            return mManifestFiles;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getProguardFiles() {
+-            if (mProguardFiles == null) {
+-                File proguardRules = mLibrary.getProguardRules();
+-                if (proguardRules.exists()) {
+-                    mProguardFiles = Collections.singletonList(proguardRules);
+-                } else {
+-                    mProguardFiles = Collections.emptyList();
+-                }
+-            }
+-
+-            return mProguardFiles;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getResourceFolders() {
+-            if (mResourceFolders == null) {
+-                File folder = mLibrary.getResFolder();
+-                if (folder.exists()) {
+-                    mResourceFolders = Collections.singletonList(folder);
+-                } else {
+-                    mResourceFolders = Collections.emptyList();
+-                }
+-            }
+-
+-            return mResourceFolders;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getJavaSourceFolders() {
+-            return Collections.emptyList();
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getTestSourceFolders() {
+-            return Collections.emptyList();
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getJavaClassFolders() {
+-            return Collections.emptyList();
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<File> getJavaLibraries() {
+-            if (mJavaLibraries == null) {
+-                mJavaLibraries = Lists.newArrayList();
+-                File jarFile = mLibrary.getJarFile();
+-                if (jarFile.exists()) {
+-                    mJavaLibraries.add(jarFile);
+-                }
+-
+-                for (File local : mLibrary.getLocalJars()) {
+-                    if (local.exists()) {
+-                        mJavaLibraries.add(local);
+-                    }
+-                }
+-            }
+-
+-            return mJavaLibraries;
+-        }
+-
+-        @Nullable
+-        @Override
+-        public Boolean dependsOn(@NonNull String artifact) {
+-            if (SUPPORT_LIB_ARTIFACT.equals(artifact)) {
+-                if (mSupportLib == null) {
+-                    mSupportLib = dependsOn(mLibrary, artifact);
+-                }
+-                return mSupportLib;
+-            } else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) {
+-                if (mAppCompat == null) {
+-                    mAppCompat = dependsOn(mLibrary, artifact);
+-                }
+-                return mAppCompat;
+-            } else {
+-                return super.dependsOn(artifact);
+-            }
+-        }
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleRequest.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleRequest.java
+deleted file mode 100644
+index 8a13bcb..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/LintGradleRequest.java
++++ /dev/null
+@@ -1,69 +0,0 @@
+-package com.android.build.gradle.internal;
+-
+-import com.android.annotations.NonNull;
+-import com.android.annotations.Nullable;
+-import com.android.builder.model.AndroidProject;
+-import com.android.builder.model.Variant;
+-import com.android.tools.lint.client.api.LintRequest;
+-import com.android.tools.lint.detector.api.Project;
+-import com.android.utils.Pair;
+-
+-import java.io.File;
+-import java.util.Collection;
+-import java.util.Collections;
+-import java.util.List;
+-
+-class LintGradleRequest extends LintRequest {
+-    @NonNull private final LintGradleClient mLintClient;
+-    @NonNull private final org.gradle.api.Project mGradleProject;
+-    @Nullable private final String mVariantName;
+-    @NonNull private final AndroidProject mModelProject;
+-
+-    public LintGradleRequest(
+-            @NonNull LintGradleClient client,
+-            @NonNull AndroidProject modelProject,
+-            @NonNull org.gradle.api.Project gradleProject,
+-            @Nullable String variantName,
+-            @NonNull List<File> files) {
+-        super(client, files);
+-        mLintClient = client;
+-        mModelProject = modelProject;
+-        mGradleProject = gradleProject;
+-        mVariantName = variantName;
+-    }
+-
+-    @Nullable
+-    @Override
+-    public Collection<Project> getProjects() {
+-        if (mProjects == null) {
+-            Variant variant = findVariant(mModelProject, mVariantName);
+-            if (variant == null) {
+-                mProjects = Collections.emptyList();
+-                return mProjects;
+-            }
+-            Pair<LintGradleProject,List<File>> result = LintGradleProject.create(
+-                    mLintClient, mModelProject, variant, mGradleProject);
+-            mProjects = Collections.<Project>singletonList(result.getFirst());
+-            mLintClient.setCustomRules(result.getSecond());
+-        }
+-
+-        return mProjects;
+-    }
+-
+-    private static Variant findVariant(@NonNull AndroidProject project,
+-            @Nullable String variantName) {
+-        if (variantName != null) {
+-            for (Variant variant : project.getVariants()) {
+-                if (variantName.equals(variant.getName())) {
+-                    return variant;
+-                }
+-            }
+-        }
+-
+-        if (!project.getVariants().isEmpty()) {
+-            return project.getVariants().iterator().next();
+-        }
+-
+-        return null;
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/TaskManager.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/TaskManager.java
+index 4c646b5..0db3585 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/TaskManager.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/TaskManager.java
+@@ -96,7 +96,6 @@ import com.android.build.gradle.tasks.GenerateSplitAbiRes;
+ import com.android.build.gradle.tasks.JackTask;
+ import com.android.build.gradle.tasks.JavaResourcesProvider;
+ import com.android.build.gradle.tasks.JillTask;
+-import com.android.build.gradle.tasks.Lint;
+ import com.android.build.gradle.tasks.MergeAssets;
+ import com.android.build.gradle.tasks.MergeManifests;
+ import com.android.build.gradle.tasks.MergeResources;
+@@ -109,7 +108,7 @@ import com.android.build.gradle.tasks.ProcessAndroidResources;
+ import com.android.build.gradle.tasks.ProcessManifest;
+ import com.android.build.gradle.tasks.ProcessTestManifest;
+ import com.android.build.gradle.tasks.RenderscriptCompile;
+-import com.android.build.gradle.tasks.ShrinkResources;
++//import com.android.build.gradle.tasks.ShrinkResources;
+ import com.android.build.gradle.tasks.SplitZipAlign;
+ import com.android.build.gradle.tasks.ZipAlign;
+ import com.android.build.gradle.tasks.factory.JavaCompileConfigAction;
+@@ -368,24 +367,12 @@ public abstract class TaskManager {
+             }
+         });
+ 
+-        tasks.create(LINT, Lint.class, new Action<Lint>() {
+-            @Override
+-            public void execute(Lint lintTask) {
+-                lintTask.setDescription("Runs lint on all variants.");
+-                lintTask.setVariantName("");
+-                lintTask.setGroup(JavaBasePlugin.VERIFICATION_GROUP);
+-                lintTask.setLintOptions(getExtension().getLintOptions());
+-                lintTask.setSdkHome(sdkHandler.getSdkFolder());
+-                lintTask.setToolingRegistry(toolingRegistry);
+-            }
+-        });
+         tasks.named(JavaBasePlugin.CHECK_TASK_NAME, new Action<Task>() {
+             @Override
+             public void execute(Task it) {
+                 it.dependsOn(LINT);
+             }
+         });
+-        createLintCompileTask(tasks);
+     }
+ 
+     public void createMockableJarTask() {
+@@ -1166,100 +1153,21 @@ public abstract class TaskManager {
+     }
+ 
+     // TODO - should compile src/lint/java from src/lint/java and jar it into build/lint/lint.jar
+-    private void createLintCompileTask(TaskFactory tasks) {
+-
+-        // TODO: move doFirst into dedicated task class.
+-        tasks.create(LINT_COMPILE, Task.class,
+-                new Action<Task>() {
+-                    @Override
+-                    public void execute(Task lintCompile) {
+-                        final File outputDir =
+-                                new File(getGlobalScope().getIntermediatesDir(), "lint");
+-
+-                        lintCompile.doFirst(new Action<Task>() {
+-                            @Override
+-                            public void execute(Task task) {
+-                                // create the directory for lint output if it does not exist.
+-                                if (!outputDir.exists()) {
+-                                    boolean mkdirs = outputDir.mkdirs();
+-                                    if (!mkdirs) {
+-                                        throw new GradleException(
+-                                                "Unable to create lint output directory.");
+-                                    }
+-                                }
+-                            }
+-                        });
+-                    }
+-                });
+-    }
+ 
+     /**
+      * Is the given variant relevant for lint?
+      */
+-    private static boolean isLintVariant(
+-            @NonNull BaseVariantData<? extends BaseVariantOutputData> baseVariantData) {
+-        // Only create lint targets for variants like debug and release, not debugTest
+-        VariantConfiguration config = baseVariantData.getVariantConfiguration();
+-        return !config.getType().isForTesting();
+-    }
+ 
+     /**
+      * Add tasks for running lint on individual variants. We've already added a
+      * lint task earlier which runs on all variants.
+      */
+-    public void createLintTasks(TaskFactory tasks, final VariantScope scope) {
+-        final BaseVariantData<? extends BaseVariantOutputData> baseVariantData =
+-                scope.getVariantData();
+-        if (!isLintVariant(baseVariantData)) {
+-            return;
+-        }
+ 
+         // wire the main lint task dependency.
+-        tasks.named(LINT, new Action<Task>() {
+-            @Override
+-            public void execute(Task it) {
+-                it.dependsOn(LINT_COMPILE);
+-                it.dependsOn(scope.getJavacTask().getName());
+-            }
+-        });
+-
+-        AndroidTask<Lint> variantLintCheck = androidTasks.create(
+-                tasks, new Lint.ConfigAction(scope));
+-        variantLintCheck.dependsOn(tasks, LINT_COMPILE, scope.getJavacTask());
+-    }
+ 
+-    private void createLintVitalTask(@NonNull ApkVariantData variantData) {
+-        checkState(getExtension().getLintOptions().isCheckReleaseBuilds());
+-        // TODO: re-enable with Jack when possible
+-        if (!variantData.getVariantConfiguration().getBuildType().isDebuggable() &&
+-                !variantData.getVariantConfiguration().getUseJack()) {
+-            String variantName = variantData.getVariantConfiguration().getFullName();
+-            String capitalizedVariantName = StringHelper.capitalize(variantName);
+-            String taskName = "lintVital" + capitalizedVariantName;
+-            final Lint lintReleaseCheck = project.getTasks().create(taskName, Lint.class);
+-            // TODO: Make this task depend on lintCompile too (resolve initialization order first)
+-            optionalDependsOn(lintReleaseCheck, variantData.javacTask);
+-            lintReleaseCheck.setLintOptions(getExtension().getLintOptions());
+-            lintReleaseCheck.setSdkHome(sdkHandler.getSdkFolder());
+-            lintReleaseCheck.setVariantName(variantName);
+-            lintReleaseCheck.setToolingRegistry(toolingRegistry);
+-            lintReleaseCheck.setFatalOnly(true);
+-            lintReleaseCheck.setDescription(
+-                    "Runs lint on just the fatal issues in the " + capitalizedVariantName
+-                            + " build.");
+-            //variantData.assembleVariantTask.dependsOn lintReleaseCheck
+ 
+             // If lint is being run, we do not need to run lint vital.
+             // TODO: Find a better way to do this.
+-            project.getGradle().getTaskGraph().whenReady(new Closure<Void>(this, this) {
+-                public void doCall(TaskExecutionGraph taskGraph) {
+-                    if (taskGraph.hasTask(LINT)) {
+-                        lintReleaseCheck.setEnabled(false);
+-                    }
+-                }
+-            });
+-        }
+-    }
+ 
+     private void createUnitTestTask(@NonNull TaskFactory tasks,
+             @NonNull final TestVariantData variantData) {
+@@ -1981,16 +1889,6 @@ public abstract class TaskManager {
+             // we insert the ShrinkResources task into the chain, such that its
+             // input is the ProcessAndroidResources packageOutputFile, and its
+             // output is what the PackageApplication task reads.
+-            AndroidTask<ShrinkResources> shrinkTask = null;
+-
+-            if (config.isMinifyEnabled() && config.getBuildType().isShrinkResources() &&
+-                    !config.getUseJack()) {
+-                shrinkTask = androidTasks.create(
+-                        tasks, new ShrinkResources.ConfigAction(variantOutputScope));
+-                shrinkTask.dependsOn(tasks, variantScope.getObfuscationTask(),
+-                        variantOutputScope.getManifestProcessorTask(),
+-                        variantOutputScope.getProcessResourcesTask());
+-            }
+ 
+             AndroidTask<PackageApplication> packageApp = androidTasks.create(
+                     tasks, new PackageApplication.ConfigAction(variantOutputScope));
+@@ -2001,7 +1899,6 @@ public abstract class TaskManager {
+ 
+             packageApp.optionalDependsOn(
+                     tasks,
+-                    shrinkTask,
+                     // TODO: When Jack is converted, add activeDexTask to VariantScope.
+                     variantOutputScope.getVariantScope().getDexTask(),
+                     variantOutputScope.getVariantScope().getJavaCompilerTask(),
+@@ -2157,9 +2054,6 @@ public abstract class TaskManager {
+             installTask.dependsOn(tasks, variantData.assembleVariantTask);
+         }
+ 
+-        if (getExtension().getLintOptions().isCheckReleaseBuilds()) {
+-            createLintVitalTask(variantData);
+-        }
+ 
+         // add an uninstall task
+         final AndroidTask<UninstallTask> uninstallTask = androidTasks.create(
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/dsl/LintOptions.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/dsl/LintOptions.java
+deleted file mode 100644
+index eff135e..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/dsl/LintOptions.java
++++ /dev/null
+@@ -1,798 +0,0 @@
+-/*
+- * Copyright (C) 2013 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.build.gradle.internal.dsl;
+-
+-import static com.android.SdkConstants.DOT_XML;
+-import static com.android.builder.model.AndroidProject.FD_OUTPUTS;
+-import static com.android.tools.lint.detector.api.Severity.ERROR;
+-import static com.android.tools.lint.detector.api.Severity.FATAL;
+-import static com.android.tools.lint.detector.api.Severity.IGNORE;
+-import static com.android.tools.lint.detector.api.Severity.INFORMATIONAL;
+-import static com.android.tools.lint.detector.api.Severity.WARNING;
+-
+-import com.android.annotations.NonNull;
+-import com.android.annotations.Nullable;
+-import com.android.tools.lint.HtmlReporter;
+-import com.android.tools.lint.LintCliClient;
+-import com.android.tools.lint.LintCliFlags;
+-import com.android.tools.lint.TextReporter;
+-import com.android.tools.lint.XmlReporter;
+-import com.android.tools.lint.checks.BuiltinIssueRegistry;
+-import com.android.tools.lint.detector.api.Issue;
+-import com.android.tools.lint.detector.api.Severity;
+-import com.google.common.collect.Maps;
+-import com.google.common.collect.Sets;
+-
+-import org.gradle.api.GradleException;
+-import org.gradle.api.tasks.Input;
+-import org.gradle.api.tasks.InputFile;
+-import org.gradle.api.tasks.Optional;
+-import org.gradle.api.tasks.OutputFile;
+-
+-import java.io.BufferedWriter;
+-import java.io.File;
+-import java.io.FileWriter;
+-import java.io.IOException;
+-import java.io.PrintWriter;
+-import java.io.Serializable;
+-import java.io.Writer;
+-import java.util.Map;
+-import java.util.Set;
+-
+-/**
+- * DSL object for configuring lint options.
+- */
+-public class LintOptions implements com.android.builder.model.LintOptions, Serializable {
+-    public static final String STDOUT = "stdout";
+-    public static final String STDERR = "stderr";
+-    private static final long serialVersionUID = 1L;
+-
+-    @NonNull
+-    private Set<String> disable = Sets.newHashSet();
+-    @NonNull
+-    private Set<String> enable = Sets.newHashSet();
+-    @Nullable
+-    private Set<String> check = Sets.newHashSet();
+-    private boolean abortOnError = true;
+-    private boolean absolutePaths = true;
+-    private boolean noLines;
+-    private boolean quiet;
+-    private boolean checkAllWarnings;
+-    private boolean ignoreWarnings;
+-    private boolean warningsAsErrors;
+-    private boolean showAll;
+-    private boolean checkReleaseBuilds = true;
+-    private boolean explainIssues = true;
+-    @Nullable
+-    private File lintConfig;
+-    private boolean textReport;
+-    @Nullable
+-    private File textOutput;
+-    private boolean htmlReport = true;
+-    @Nullable
+-    private File htmlOutput;
+-    private boolean xmlReport = true;
+-    @Nullable
+-    private File xmlOutput;
+-
+-    private Map<String,Severity> severities = Maps.newHashMap();
+-
+-    public LintOptions() {
+-    }
+-
+-    public LintOptions(
+-            @NonNull Set<String> disable,
+-            @NonNull Set<String> enable,
+-            @Nullable Set<String> check,
+-            @Nullable File lintConfig,
+-            boolean textReport,
+-            @Nullable File textOutput,
+-            boolean htmlReport,
+-            @Nullable File htmlOutput,
+-            boolean xmlReport,
+-            @Nullable File xmlOutput,
+-            boolean abortOnError,
+-            boolean absolutePaths,
+-            boolean noLines,
+-            boolean quiet,
+-            boolean checkAllWarnings,
+-            boolean ignoreWarnings,
+-            boolean warningsAsErrors,
+-            boolean showAll,
+-            boolean explainIssues,
+-            boolean checkReleaseBuilds,
+-            @Nullable Map<String,Integer> severityOverrides) {
+-        this.disable = disable;
+-        this.enable = enable;
+-        this.check = check;
+-        this.lintConfig = lintConfig;
+-        this.textReport = textReport;
+-        this.textOutput = textOutput;
+-        this.htmlReport = htmlReport;
+-        this.htmlOutput = htmlOutput;
+-        this.xmlReport = xmlReport;
+-        this.xmlOutput = xmlOutput;
+-        this.abortOnError = abortOnError;
+-        this.absolutePaths = absolutePaths;
+-        this.noLines = noLines;
+-        this.quiet = quiet;
+-        this.checkAllWarnings = checkAllWarnings;
+-        this.ignoreWarnings = ignoreWarnings;
+-        this.warningsAsErrors = warningsAsErrors;
+-        this.showAll = showAll;
+-        this.explainIssues = explainIssues;
+-        this.checkReleaseBuilds = checkReleaseBuilds;
+-
+-        if (severityOverrides != null) {
+-            for (Map.Entry<String,Integer> entry : severityOverrides.entrySet()) {
+-                severities.put(entry.getKey(), convert(entry.getValue()));
+-            }
+-        }
+-    }
+-
+-    @NonNull
+-    public static com.android.builder.model.LintOptions create(@NonNull com.android.builder.model.LintOptions source) {
+-        return new LintOptions(
+-                source.getDisable(),
+-                source.getEnable(),
+-                source.getCheck(),
+-                source.getLintConfig(),
+-                source.getTextReport(),
+-                source.getTextOutput(),
+-                source.getHtmlReport(),
+-                source.getHtmlOutput(),
+-                source.getXmlReport(),
+-                source.getXmlOutput(),
+-                source.isAbortOnError(),
+-                source.isAbsolutePaths(),
+-                source.isNoLines(),
+-                source.isQuiet(),
+-                source.isCheckAllWarnings(),
+-                source.isIgnoreWarnings(),
+-                source.isWarningsAsErrors(),
+-                source.isShowAll(),
+-                source.isExplainIssues(),
+-                source.isCheckReleaseBuilds(),
+-                source.getSeverityOverrides()
+-        );
+-    }
+-
+-    /**
+-     * Returns the set of issue id's to suppress. Callers are allowed to modify this collection.
+-     */
+-    @Override
+-    @NonNull
+-    @Input
+-    public Set<String> getDisable() {
+-        return disable;
+-    }
+-
+-    /**
+-     * Sets the set of issue id's to suppress. Callers are allowed to modify this collection.
+-     * Note that these ids add to rather than replace the given set of ids.
+-     */
+-    public void setDisable(@Nullable Set<String> ids) {
+-        disable.addAll(ids);
+-    }
+-
+-    /**
+-     * Returns the set of issue id's to enable. Callers are allowed to modify this collection.
+-     * To enable a given issue, add the issue ID to the returned set.
+-     */
+-    @Override
+-    @NonNull
+-    @Input
+-    public Set<String> getEnable() {
+-        return enable;
+-    }
+-
+-    /**
+-     * Sets the set of issue id's to enable. Callers are allowed to modify this collection.
+-     * Note that these ids add to rather than replace the given set of ids.
+-     */
+-    public void setEnable(@Nullable Set<String> ids) {
+-        enable.addAll(ids);
+-    }
+-
+-    /**
+-     * Returns the exact set of issues to check, or null to run the issues that are enabled
+-     * by default plus any issues enabled via {@link #getEnable} and without issues disabled
+-     * via {@link #getDisable}. If non-null, callers are allowed to modify this collection.
+-     */
+-    @Override
+-    @Nullable
+-    @Optional
+-    @Input
+-    public Set<String> getCheck() {
+-        return check;
+-    }
+-
+-    /**
+-     * Sets the <b>exact</b> set of issues to check.
+-     * @param ids the set of issue id's to check
+-     */
+-    public void setCheck(@NonNull Set<String> ids) {
+-        check.addAll(ids);
+-    }
+-
+-    /** Whether lint should set the exit code of the process if errors are found */
+-    @Override
+-    @Input
+-    public boolean isAbortOnError() {
+-        return abortOnError;
+-    }
+-
+-    /** Sets whether lint should set the exit code of the process if errors are found */
+-    public void setAbortOnError(boolean abortOnError) {
+-        this.abortOnError = abortOnError;
+-    }
+-
+-    /**
+-     * Whether lint should display full paths in the error output. By default the paths
+-     * are relative to the path lint was invoked from.
+-     */
+-    @Override
+-    @Input
+-    public boolean isAbsolutePaths() {
+-        return absolutePaths;
+-    }
+-
+-    /**
+-     * Sets whether lint should display full paths in the error output. By default the paths
+-     * are relative to the path lint was invoked from.
+-     */
+-    public void setAbsolutePaths(boolean absolutePaths) {
+-        this.absolutePaths = absolutePaths;
+-    }
+-
+-    /**
+-     * Whether lint should include the source lines in the output where errors occurred
+-     * (true by default)
+-     */
+-    @Override
+-    @Input
+-    public boolean isNoLines() {
+-        return this.noLines;
+-    }
+-
+-    /**
+-     * Sets whether lint should include the source lines in the output where errors occurred
+-     * (true by default)
+-     */
+-    public void setNoLines(boolean noLines) {
+-        this.noLines = noLines;
+-    }
+-
+-    /**
+-     * Returns whether lint should be quiet (for example, not write informational messages
+-     * such as paths to report files written)
+-     */
+-    @Override
+-    @Input
+-    public boolean isQuiet() {
+-        return quiet;
+-    }
+-
+-    /**
+-     * Sets whether lint should be quiet (for example, not write informational messages
+-     * such as paths to report files written)
+-     */
+-    public void setQuiet(boolean quiet) {
+-        this.quiet = quiet;
+-    }
+-
+-    /** Returns whether lint should check all warnings, including those off by default */
+-    @Override
+-    @Input
+-    public boolean isCheckAllWarnings() {
+-        return checkAllWarnings;
+-    }
+-
+-    /** Sets whether lint should check all warnings, including those off by default */
+-    public void setCheckAllWarnings(boolean warnAll) {
+-        this.checkAllWarnings = warnAll;
+-    }
+-
+-    /** Returns whether lint will only check for errors (ignoring warnings) */
+-    @Override
+-    @Input
+-    public boolean isIgnoreWarnings() {
+-        return ignoreWarnings;
+-    }
+-
+-    /** Sets whether lint will only check for errors (ignoring warnings) */
+-    public void setIgnoreWarnings(boolean noWarnings) {
+-        this.ignoreWarnings = noWarnings;
+-    }
+-
+-    /** Returns whether lint should treat all warnings as errors */
+-    @Override
+-    @Input
+-    public boolean isWarningsAsErrors() {
+-        return warningsAsErrors;
+-    }
+-
+-    /** Sets whether lint should treat all warnings as errors */
+-    public void setWarningsAsErrors(boolean allErrors) {
+-        this.warningsAsErrors = allErrors;
+-    }
+-
+-    /** Returns whether lint should include explanations for issue errors. (Note that
+-     * HTML and XML reports intentionally do this unconditionally, ignoring this setting.) */
+-    @Override
+-    @Input
+-    public boolean isExplainIssues() {
+-        return explainIssues;
+-    }
+-
+-    public void setExplainIssues(boolean explainIssues) {
+-        this.explainIssues = explainIssues;
+-    }
+-
+-    /**
+-     * Returns whether lint should include all output (e.g. include all alternate
+-     * locations, not truncating long messages, etc.)
+-     */
+-    @Override
+-    @Input
+-    public boolean isShowAll() {
+-        return showAll;
+-    }
+-
+-    /**
+-     * Sets whether lint should include all output (e.g. include all alternate
+-     * locations, not truncating long messages, etc.)
+-     */
+-    public void setShowAll(boolean showAll) {
+-        this.showAll = showAll;
+-    }
+-
+-    /**
+-     * Returns whether lint should check for fatal errors during release builds. Default is true.
+-     * If issues with severity "fatal" are found, the release build is aborted.
+-     */
+-    @Override
+-    @Input
+-    public boolean isCheckReleaseBuilds() {
+-        return checkReleaseBuilds;
+-    }
+-
+-    public void setCheckReleaseBuilds(boolean checkReleaseBuilds) {
+-        this.checkReleaseBuilds = checkReleaseBuilds;
+-    }
+-
+-    /**
+-     * Returns the default configuration file to use as a fallback
+-     */
+-    @Override
+-    @Optional @InputFile
+-    public File getLintConfig() {
+-        return lintConfig;
+-    }
+-
+-    /** Whether we should write an text report. Default false. The location can be
+-     * controlled by {@link #getTextOutput()}. */
+-    @Override
+-    @Input
+-    public boolean getTextReport() {
+-        return textReport;
+-    }
+-
+-    public void setTextReport(boolean textReport) {
+-        this.textReport = textReport;
+-    }
+-
+-    public void setHtmlReport(boolean htmlReport) {
+-        this.htmlReport = htmlReport;
+-    }
+-
+-    public void setHtmlOutput(@NonNull File htmlOutput) {
+-        this.htmlOutput = htmlOutput;
+-    }
+-
+-    public void setXmlReport(boolean xmlReport) {
+-        this.xmlReport = xmlReport;
+-    }
+-
+-    public void setXmlOutput(@NonNull File xmlOutput) {
+-        this.xmlOutput = xmlOutput;
+-    }
+-
+-    /**
+-     * The optional path to where a text report should be written. The special value
+-     * "stdout" can be used to point to standard output.
+-     */
+-    @Override
+-    @Nullable
+-    @Optional
+-    @Input
+-    public File getTextOutput() {
+-        return textOutput;
+-    }
+-
+-    /** Whether we should write an HTML report. Default true. The location can be
+-     * controlled by {@link #getHtmlOutput()}. */
+-    @Override
+-    @Input
+-    public boolean getHtmlReport() {
+-        return htmlReport;
+-    }
+-
+-    /** The optional path to where an HTML report should be written */
+-    @Override
+-    @Nullable
+-    @Optional
+-    @OutputFile
+-    public File getHtmlOutput() {
+-        return htmlOutput;
+-    }
+-
+-    /** Whether we should write an XML report. Default true. The location can be
+-     * controlled by {@link #getXmlOutput()}. */
+-    @Override
+-    @Input
+-    public boolean getXmlReport() {
+-        return xmlReport;
+-    }
+-
+-    /** The optional path to where an XML report should be written */
+-    @Override
+-    @Nullable
+-    @Optional
+-    @OutputFile
+-    public File getXmlOutput() {
+-        return xmlOutput;
+-    }
+-
+-    /**
+-     * Sets the default config file to use as a fallback. This corresponds to a {@code lint.xml}
+-     * file with severities etc to use when a project does not have more specific information.
+-     */
+-    public void setLintConfig(@NonNull File lintConfig) {
+-        this.lintConfig = lintConfig;
+-    }
+-
+-    public void syncTo(
+-            @NonNull LintCliClient client,
+-            @NonNull LintCliFlags flags,
+-            @Nullable String variantName,
+-            @Nullable org.gradle.api.Project project,
+-            boolean report) {
+-        if (disable != null) {
+-            flags.getSuppressedIds().addAll(disable);
+-        }
+-        if (enable != null) {
+-            flags.getEnabledIds().addAll(enable);
+-        }
+-        if (check != null && !check.isEmpty()) {
+-            flags.setExactCheckedIds(check);
+-        }
+-        flags.setSetExitCode(this.abortOnError);
+-        flags.setFullPath(absolutePaths);
+-        flags.setShowSourceLines(!noLines);
+-        flags.setQuiet(quiet);
+-        flags.setCheckAllWarnings(checkAllWarnings);
+-        flags.setIgnoreWarnings(ignoreWarnings);
+-        flags.setWarningsAsErrors(warningsAsErrors);
+-        flags.setShowEverything(showAll);
+-        flags.setDefaultConfiguration(lintConfig);
+-        flags.setSeverityOverrides(severities);
+-        flags.setExplainIssues(explainIssues);
+-
+-        if (report || flags.isFatalOnly() && this.abortOnError) {
+-            if (textReport || flags.isFatalOnly()) {
+-                File output = textOutput;
+-                if (output == null) {
+-                    output = new File(flags.isFatalOnly() ? STDERR: STDOUT);
+-                } else if (!output.isAbsolute() && !isStdOut(output) && !isStdErr(output)) {
+-                    output = project.file(output.getPath());
+-                }
+-                output = validateOutputFile(output);
+-
+-                Writer writer;
+-                File file = null;
+-                boolean closeWriter;
+-                if (isStdOut(output)) {
+-                    writer = new PrintWriter(System.out, true);
+-                    closeWriter = false;
+-                } else if (isStdErr(output)) {
+-                    writer = new PrintWriter(System.err, true);
+-                    closeWriter = false;
+-                } else {
+-                    file = output;
+-                    try {
+-                        writer = new BufferedWriter(new FileWriter(output));
+-                    } catch (IOException e) {
+-                        throw new org.gradle.api.GradleException("Text invalid argument.", e);
+-                    }
+-                    closeWriter = true;
+-                }
+-                flags.getReporters().add(new TextReporter(client, flags, file, writer,
+-                        closeWriter));
+-            }
+-            if (htmlReport) {
+-                File output = htmlOutput;
+-                if (output == null || flags.isFatalOnly()) {
+-                    output = createOutputPath(project, variantName, ".html", flags.isFatalOnly());
+-                } else if (!output.isAbsolute()) {
+-                    output = project.file(output.getPath());
+-                }
+-                output = validateOutputFile(output);
+-                try {
+-                    flags.getReporters().add(new HtmlReporter(client, output));
+-                } catch (IOException e) {
+-                    throw new GradleException("HTML invalid argument.", e);
+-                }
+-            }
+-            if (xmlReport) {
+-                File output = xmlOutput;
+-                if (output == null || flags.isFatalOnly()) {
+-                    output = createOutputPath(project, variantName, DOT_XML, flags.isFatalOnly());
+-                } else if (!output.isAbsolute()) {
+-                    output = project.file(output.getPath());
+-                }
+-                output = validateOutputFile(output);
+-                try {
+-                    flags.getReporters().add(new XmlReporter(client, output));
+-                } catch (IOException e) {
+-                    throw new org.gradle.api.GradleException("XML invalid argument.", e);
+-                }
+-            }
+-        }
+-    }
+-
+-    private static boolean isStdOut(@NonNull File output) {
+-        return STDOUT.equals(output.getPath());
+-    }
+-
+-    private static boolean isStdErr(@NonNull File output) {
+-        return STDERR.equals(output.getPath());
+-    }
+-
+-    @NonNull
+-    private static File validateOutputFile(@NonNull File output) {
+-        if (isStdOut(output) || isStdErr(output)) {
+-            return output;
+-        }
+-
+-        File parent = output.getParentFile();
+-        if (!parent.exists()) {
+-            parent.mkdirs();
+-        }
+-
+-        output = output.getAbsoluteFile();
+-        if (output.exists()) {
+-            boolean delete = output.delete();
+-            if (!delete) {
+-                throw new org.gradle.api.GradleException("Could not delete old " + output);
+-            }
+-        }
+-        if (output.getParentFile() != null && !output.getParentFile().canWrite()) {
+-            throw new org.gradle.api.GradleException("Cannot write output file " + output);
+-        }
+-
+-        return output;
+-    }
+-
+-    private static File createOutputPath(
+-            @NonNull org.gradle.api.Project project,
+-            @NonNull String variantName,
+-            @NonNull String extension,
+-            boolean fatalOnly) {
+-        StringBuilder base = new StringBuilder();
+-        base.append(FD_OUTPUTS);
+-        base.append(File.separator);
+-        base.append("lint-results");
+-        if (variantName != null) {
+-            base.append("-");
+-            base.append(variantName);
+-        }
+-        if (fatalOnly) {
+-            base.append("-fatal");
+-        }
+-        base.append(extension);
+-        return new File(project.getBuildDir(), base.toString());
+-    }
+-
+-    /**
+-     * An optional map of severity overrides. The map maps from issue id's to the corresponding
+-     * severity to use, which must be "fatal", "error", "warning", or "ignore".
+-     *
+-     * @return a map of severity overrides, or null. The severities are one of the constants
+-     *  {@link #SEVERITY_FATAL}, {@link #SEVERITY_ERROR}, {@link #SEVERITY_WARNING},
+-     *  {@link #SEVERITY_INFORMATIONAL}, {@link #SEVERITY_IGNORE}
+-     */
+-    @Override
+-    @Nullable
+-    public Map<String, Integer> getSeverityOverrides() {
+-        if (severities == null || severities.isEmpty()) {
+-            return null;
+-        }
+-
+-        Map<String, Integer> map =
+-                Maps.newHashMapWithExpectedSize(severities.size());
+-        for (Map.Entry<String,Severity> entry : severities.entrySet()) {
+-            map.put(entry.getKey(), convert(entry.getValue()));
+-        }
+-
+-        return map;
+-    }
+-
+-    // -- DSL Methods.
+-
+-    /**
+-     * Adds the id to the set of issues to check.
+-     */
+-    public void check(String id) {
+-        check.add(id);
+-    }
+-
+-    /**
+-     * Adds the ids to the set of issues to check.
+-     */
+-    public void check(String... ids) {
+-        for (String id : ids) {
+-            check(id);
+-        }
+-    }
+-
+-    /**
+-     * Adds the id to the set of issues to enable.
+-     */
+-    public void enable(String id) {
+-        enable.add(id);
+-        Issue issue = new BuiltinIssueRegistry().getIssue(id);
+-        severities.put(id, issue != null ? issue.getDefaultSeverity() : WARNING);
+-    }
+-
+-    /**
+-     * Adds the ids to the set of issues to enable.
+-     */
+-    public void enable(String... ids) {
+-        for (String id : ids) {
+-            enable(id);
+-        }
+-    }
+-
+-    /**
+-     * Adds the id to the set of issues to enable.
+-     */
+-    public void disable(String id) {
+-        disable.add(id);
+-        severities.put(id, IGNORE);
+-    }
+-
+-    /**
+-     * Adds the ids to the set of issues to enable.
+-     */
+-    public void disable(String... ids) {
+-        for (String id : ids) {
+-            disable(id);
+-        }
+-    }
+-
+-    // For textOutput 'stdout' or 'stderr' (normally a file)
+-    public void textOutput(String textOutput) {
+-        this.textOutput = new File(textOutput);
+-    }
+-
+-    // For textOutput file()
+-    public void textOutput(File textOutput) {
+-        this.textOutput = textOutput;
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void fatal(String id) {
+-        severities.put(id, FATAL);
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void fatal(String... ids) {
+-        for (String id : ids) {
+-            fatal(id);
+-        }
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void error(String id) {
+-        severities.put(id, ERROR);
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void error(String... ids) {
+-        for (String id : ids) {
+-            error(id);
+-        }
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void warning(String id) {
+-        severities.put(id, WARNING);
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void warning(String... ids) {
+-        for (String id : ids) {
+-            warning(id);
+-        }
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void ignore(String id) {
+-        severities.put(id, IGNORE);
+-    }
+-
+-    /**
+-     * Adds a severity override for the given issues.
+-     */
+-    public void ignore(String... ids) {
+-        for (String id : ids) {
+-            ignore(id);
+-        }
+-    }
+-
+-    // Without these qualifiers, Groovy compilation will fail with "Apparent variable
+-    // 'SEVERITY_FATAL' was found in a static scope but doesn't refer to a local variable,
+-    // static field or class"
+-    //@SuppressWarnings("UnnecessaryQualifiedReference")
+-    private static int convert(Severity s) {
+-        switch (s) {
+-            case FATAL:
+-                return com.android.builder.model.LintOptions.SEVERITY_FATAL;
+-            case ERROR:
+-                return com.android.builder.model.LintOptions.SEVERITY_ERROR;
+-            case WARNING:
+-                return com.android.builder.model.LintOptions.SEVERITY_WARNING;
+-            case INFORMATIONAL:
+-                return com.android.builder.model.LintOptions.SEVERITY_INFORMATIONAL;
+-            case IGNORE:
+-            default:
+-                return com.android.builder.model.LintOptions.SEVERITY_IGNORE;
+-        }
+-    }
+-
+-    //@SuppressWarnings("UnnecessaryQualifiedReference")
+-    private static Severity convert(int s) {
+-        switch (s) {
+-            case com.android.builder.model.LintOptions.SEVERITY_FATAL:
+-                return FATAL;
+-            case com.android.builder.model.LintOptions.SEVERITY_ERROR:
+-                return ERROR;
+-            case com.android.builder.model.LintOptions.SEVERITY_WARNING:
+-                return WARNING;
+-            case com.android.builder.model.LintOptions.SEVERITY_INFORMATIONAL:
+-                return INFORMATIONAL;
+-            case com.android.builder.model.LintOptions.SEVERITY_IGNORE:
+-            default:
+-                return IGNORE;
+-        }
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/DefaultAndroidProject.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/DefaultAndroidProject.java
+index 4528821..6224833 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/DefaultAndroidProject.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/DefaultAndroidProject.java
+@@ -24,7 +24,6 @@ import com.android.builder.model.AndroidProject;
+ import com.android.builder.model.ArtifactMetaData;
+ import com.android.builder.model.BuildTypeContainer;
+ import com.android.builder.model.JavaCompileOptions;
+-import com.android.builder.model.LintOptions;
+ import com.android.builder.model.ProductFlavorContainer;
+ import com.android.builder.model.SigningConfig;
+ import com.android.builder.model.SyncIssue;
+@@ -65,8 +64,6 @@ class DefaultAndroidProject implements AndroidProject, Serializable {
+     @NonNull
+     private final JavaCompileOptions javaCompileOptions;
+     @NonNull
+-    private final LintOptions lintOptions;
+-    @NonNull
+     private final File buildFolder;
+     @Nullable
+     private final String resourcePrefix;
+@@ -97,7 +94,6 @@ class DefaultAndroidProject implements AndroidProject, Serializable {
+             @NonNull Collection<String> unresolvedDependencies,
+             @NonNull Collection<SyncIssue> syncIssues,
+             @NonNull CompileOptions compileOptions,
+-            @NonNull LintOptions lintOptions,
+             @NonNull File buildFolder,
+             @Nullable String resourcePrefix,
+             @NonNull Collection<NativeToolchain> nativeToolchains,
+@@ -115,7 +111,6 @@ class DefaultAndroidProject implements AndroidProject, Serializable {
+         this.unresolvedDependencies = unresolvedDependencies;
+         this.syncIssues = syncIssues;
+         javaCompileOptions = new DefaultJavaCompileOptions(compileOptions);
+-        this.lintOptions = lintOptions;
+         this.buildFolder = buildFolder;
+         this.resourcePrefix = resourcePrefix;
+         this.isLibrary = isLibrary;
+@@ -238,12 +233,6 @@ class DefaultAndroidProject implements AndroidProject, Serializable {
+ 
+     @Override
+     @NonNull
+-    public LintOptions getLintOptions() {
+-        return lintOptions;
+-    }
+-
+-    @Override
+-    @NonNull
+     public Collection<String> getUnresolvedDependencies() {
+         return unresolvedDependencies;
+     }
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.java
+index b6e18ee..4cb5424 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/model/ModelBuilder.java
+@@ -49,7 +49,6 @@ import com.android.builder.model.AndroidProject;
+ import com.android.builder.model.ApiVersion;
+ import com.android.builder.model.ArtifactMetaData;
+ import com.android.builder.model.JavaArtifact;
+-import com.android.builder.model.LintOptions;
+ import com.android.builder.model.NativeLibrary;
+ import com.android.builder.model.NativeToolchain;
+ import com.android.builder.model.ProductFlavor;
+@@ -149,9 +148,6 @@ public class ModelBuilder implements ToolingModelBuilder {
+                     variantType.getArtifactType()));
+         }
+ 
+-        LintOptions lintOptions = com.android.build.gradle.internal.dsl.LintOptions.create(
+-                config.getLintOptions());
+-
+         AaptOptions aaptOptions = AaptOptionsImpl.create(config.getAaptOptions());
+ 
+         List<SyncIssue> syncIssues = Lists.newArrayList(extraModelInfo.getSyncIssues().values());
+@@ -174,7 +170,6 @@ public class ModelBuilder implements ToolingModelBuilder {
+                 findUnresolvedDependencies(syncIssues),
+                 syncIssues,
+                 config.getCompileOptions(),
+-                lintOptions,
+                 project.getBuildDir(),
+                 config.getResourcePrefix(),
+                 ImmutableList.copyOf(toolchains.values()),
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java
+index 2aeb1d6..3138cbc 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/internal/variant/LibraryVariantData.java
+@@ -22,7 +22,7 @@ import com.android.build.OutputFile;
+ import com.android.build.gradle.AndroidConfig;
+ import com.android.build.gradle.internal.TaskManager;
+ import com.android.build.gradle.internal.core.GradleVariantConfiguration;
+-import com.android.build.gradle.tasks.ExtractAnnotations;
++//import com.android.build.gradle.tasks.ExtractAnnotations;
+ import com.android.builder.core.VariantType;
+ import com.google.common.collect.Maps;
+ 
+@@ -40,9 +40,6 @@ public class LibraryVariantData extends BaseVariantData<LibVariantOutputData> im
+ 
+     private final Map<VariantType, TestVariantData> testVariants;
+ 
+-    @Nullable
+-    public ExtractAnnotations generateAnnotationsTask = null;
+-
+     public LibraryVariantData(
+             @NonNull AndroidConfig androidConfig,
+             @NonNull TaskManager taskManager,
+@@ -93,11 +90,6 @@ public class LibraryVariantData extends BaseVariantData<LibVariantOutputData> im
+     public void registerJavaGeneratingTask(
+             @NonNull Task task, @NonNull File... generatedSourceFolders) {
+         super.registerJavaGeneratingTask(task, generatedSourceFolders);
+-        if (generateAnnotationsTask != null) {
+-            for (File f : generatedSourceFolders) {
+-                generateAnnotationsTask.source(f);
+-            }
+-        }
+     }
+ 
+     // Overridden to add source folders to a generateAnnotationsTask, if it exists.
+@@ -105,10 +97,5 @@ public class LibraryVariantData extends BaseVariantData<LibVariantOutputData> im
+     public void registerJavaGeneratingTask(
+             @NonNull Task task, @NonNull Collection<File> generatedSourceFolders) {
+         super.registerJavaGeneratingTask(task, generatedSourceFolders);
+-        if (generateAnnotationsTask != null) {
+-            for (File f : generatedSourceFolders) {
+-                generateAnnotationsTask.source(f);
+-            }
+-        }
+     }
+ }
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ExtractAnnotations.groovy b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ExtractAnnotations.groovy
+deleted file mode 100644
+index 4867946..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ExtractAnnotations.groovy
++++ /dev/null
+@@ -1,265 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks
+-
+-import com.android.annotations.NonNull
+-import com.android.build.gradle.internal.tasks.AbstractAndroidCompile
+-import com.android.build.gradle.internal.variant.BaseVariantData
+-import com.android.build.gradle.tasks.annotations.ApiDatabase
+-import com.android.build.gradle.tasks.annotations.Extractor
+-import com.android.tools.lint.EcjParser
+-import com.android.utils.Pair
+-import com.google.common.collect.Lists
+-import com.google.common.collect.Maps
+-import org.eclipse.jdt.core.compiler.IProblem
+-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration
+-import org.eclipse.jdt.internal.compiler.batch.CompilationUnit
+-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit
+-import org.eclipse.jdt.internal.compiler.env.INameEnvironment
+-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions
+-import org.eclipse.jdt.internal.compiler.util.Util
+-import org.gradle.api.file.EmptyFileVisitor
+-import org.gradle.api.file.FileVisitDetails
+-import org.gradle.api.logging.LogLevel
+-import org.gradle.api.tasks.Input
+-import org.gradle.api.tasks.InputFile
+-import org.gradle.api.tasks.Optional
+-import org.gradle.api.tasks.OutputFile
+-import org.gradle.api.tasks.TaskAction
+-import org.gradle.tooling.BuildException
+-
+-import static com.android.SdkConstants.DOT_JAVA
+-import static com.android.SdkConstants.UTF_8
+-
+-/**
+- * Task which extracts annotations from the source files, and writes them to one of
+- * two possible destinations:
+- * <ul>
+- *     <li> A "external annotations" file (pointed to by {@link ExtractAnnotations#output})
+- *          which records the annotations in a zipped XML format for use by the IDE and by
+- *          lint to associate the (source retention) annotations back with the compiled code</li>
+- *     <li> For any {@code Keep} annotated elements, a Proguard keep file (pointed to by
+- *          {@link ExtractAnnotations#proguard}, which lists APIs (classes, methods and fields)
+- *          that should not be removed even if no references in code are found to those APIs.</li>
+- * <p>
+- * We typically only extract external annotations when building libraries; ProGuard annotations
+- * are extracted when building libraries (to record in the AAR), <b>or</b> when building an
+- * app module where ProGuarding is enabled.
+- * </ul>
+- */
+-class ExtractAnnotations extends AbstractAndroidCompile {
+-    public BaseVariantData variant
+-
+-    /** Boot classpath: typically android.jar */
+-    @Input
+-    public List<String> bootClasspath
+-
+-    /** The output .zip file to write the annotations database to, if any */
+-    @Optional
+-    @OutputFile
+-    public File output
+-
+-    /** The output proguard file to write any @Keep rules into, if any */
+-    @Optional
+-    @OutputFile
+-    public File proguard
+-
+-    /**
+-     * An optional pointer to an API file to filter the annotations by (any annotations
+-     * not found in the API file are considered hidden/not exposed.) This is in the same
+-     * format as the api-versions.xml file found in the SDK.
+-     */
+-    @Optional
+-    @InputFile
+-    public File apiFilter
+-
+-    /**
+-     * A list of existing annotation zip files (or dirs) to merge in. This can be used to merge in
+-     * a hardcoded set of annotations that are not present in the source code, such as
+-     * {@code @Contract} annotations we'd like to record without actually having a dependency
+-     * on the IDEA annotations library.
+-     */
+-    @Optional
+-    @InputFile
+-    public List<File> mergeJars
+-
+-    /**
+-     * The encoding to use when reading source files. The output file will ignore this and
+-     * will always be a UTF-8 encoded .xml file inside the annotations zip file.
+-     */
+-    @Optional
+-    @Input
+-    public String encoding
+-
+-    /**
+-     * Location of class files. If set, any non-public typedef source retention annotations
+-     * will be removed prior to .jar packaging.
+-     */
+-    @Optional
+-    @InputFile
+-    public File classDir
+-
+-    /** Whether we allow extraction even in the presence of symbol resolution errors */
+-    @InputFile
+-    public boolean allowErrors = true
+-
+-    @Override
+-    @TaskAction
+-    protected void compile() {
+-        if (!hasAndroidAnnotations()) {
+-            return
+-        }
+-
+-        if (encoding == null) {
+-            encoding = UTF_8
+-        }
+-
+-        Pair<Collection<CompilationUnitDeclaration>, INameEnvironment> result = parseSources()
+-        def parsedUnits = result.first
+-        def environment = result.second
+-
+-        try {
+-            if (!allowErrors) {
+-                for (CompilationUnitDeclaration unit : parsedUnits) {
+-                    // so maybe I don't need my map!!
+-                    def problems = unit.compilationResult().allProblems
+-                    for (IProblem problem : problems) {
+-                        if (problem.error) {
+-                            println "Not extracting annotations (compilation problems encountered)";
+-                            println "Error: " + problem.getOriginatingFileName() + ":" +
+-                                    problem.getSourceLineNumber() + ": " + problem.getMessage()
+-                            // TODO: Consider whether we abort the build at this point!
+-                            return
+-                        }
+-                    }
+-                }
+-            }
+-
+-            // API definition file
+-            ApiDatabase database = null;
+-            if (apiFilter != null && apiFilter.exists()) {
+-                try {
+-                    database = new ApiDatabase(apiFilter);
+-                } catch (IOException e) {
+-                    throw new BuildException("Could not open API database " + apiFilter, e)
+-                }
+-            }
+-
+-
+-            def displayInfo = project.logger.isEnabled(LogLevel.INFO)
+-            def includeClassRetentionAnnotations = false
+-            def sortAnnotations = false
+-
+-            Extractor extractor = new Extractor(database, classDir, displayInfo,
+-                    includeClassRetentionAnnotations, sortAnnotations);
+-            extractor.extractFromProjectSource(parsedUnits)
+-            if (mergeJars != null) {
+-                for (File jar : mergeJars) {
+-                    extractor.mergeExisting(jar);
+-                }
+-            }
+-            extractor.export(output, proguard)
+-            extractor.removeTypedefClasses();
+-        } finally {
+-            if (environment != null) {
+-                environment.cleanup()
+-            }
+-        }
+-    }
+-
+-    @Input
+-    public boolean hasAndroidAnnotations() {
+-        return variant.variantDependency.annotationsPresent
+-    }
+-
+-    @NonNull
+-    private Pair<Collection<CompilationUnitDeclaration>,INameEnvironment> parseSources() {
+-        List<ICompilationUnit> sourceUnits = Lists.newArrayListWithExpectedSize(100);
+-
+-        source.visit(new EmptyFileVisitor() {
+-            @Override
+-            void visitFile(FileVisitDetails fileVisitDetails) {
+-                def file = fileVisitDetails.file;
+-                def path = file.getPath()
+-                if (path.endsWith(DOT_JAVA) && file.isFile()) {
+-                    char[] contents = Util.getFileCharContent(file, encoding);
+-                    ICompilationUnit unit = new CompilationUnit(contents, path, encoding);
+-                    sourceUnits.add(unit);
+-                }
+-            }
+-        })
+-
+-        Map<ICompilationUnit, CompilationUnitDeclaration> outputMap = Maps.
+-                newHashMapWithExpectedSize(sourceUnits.size())
+-        List<String> jars = Lists.newArrayList();
+-        if (bootClasspath != null) {
+-            jars.addAll(bootClasspath)
+-        }
+-        if (classpath != null) {
+-            for (File jar : classpath) {
+-                jars.add(jar.getPath());
+-            }
+-        }
+-
+-        CompilerOptions options = EcjParser.createCompilerOptions();
+-        options.docCommentSupport = true; // So I can find @hide
+-
+-        // Note: We can *not* set options.ignoreMethodBodies=true because it disables
+-        // type attribution!
+-
+-        def level = getLanguageLevel(sourceCompatibility)
+-        options.sourceLevel = level
+-        options.complianceLevel = options.sourceLevel
+-        // We don't generate code, but just in case the parser consults this flag
+-        // and makes sure that it's not greater than the source level:
+-        options.targetJDK = options.sourceLevel
+-        options.originalComplianceLevel = options.sourceLevel;
+-        options.originalSourceLevel = options.sourceLevel;
+-        options.inlineJsrBytecode = true; // >= 1.5
+-
+-        def environment = EcjParser.parse(options, sourceUnits, jars, outputMap, null);
+-        Collection<CompilationUnitDeclaration> parsedUnits = outputMap.values()
+-        Pair.of(parsedUnits, environment);
+-    }
+-
+-    private static long getLanguageLevel(String version) {
+-        if ("1.6".equals(version)) {
+-            return EcjParser.getLanguageLevel(1, 6);
+-        } else if ("1.7".equals(version)) {
+-            return EcjParser.getLanguageLevel(1, 7);
+-        } else if ("1.5") {
+-            return EcjParser.getLanguageLevel(1, 5);
+-        } else {
+-            return EcjParser.getLanguageLevel(1, 7);
+-        }
+-    }
+-
+-    private def addSources(List<ICompilationUnit> sourceUnits, File file) {
+-        if (file.isDirectory()) {
+-            def files = file.listFiles();
+-            if (files != null) {
+-                for (File sub : files) {
+-                    addSources(sourceUnits, sub);
+-                }
+-            }
+-        } else if (file.getPath().endsWith(DOT_JAVA) && file.isFile()) {
+-            char[] contents = Util.getFileCharContent(file, encoding);
+-            ICompilationUnit unit = new CompilationUnit(contents, file.getPath(), encoding);
+-            sourceUnits.add(unit);
+-        }
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/GroovyGradleDetector.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/GroovyGradleDetector.java
+deleted file mode 100644
+index 16ff7d5..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/GroovyGradleDetector.java
++++ /dev/null
+@@ -1,242 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks;
+-
+-import com.android.annotations.NonNull;
+-import com.android.tools.lint.checks.GradleDetector;
+-import com.android.tools.lint.detector.api.Context;
+-import com.android.tools.lint.detector.api.DefaultPosition;
+-import com.android.tools.lint.detector.api.Implementation;
+-import com.android.tools.lint.detector.api.Location;
+-import com.android.tools.lint.detector.api.Scope;
+-import com.android.utils.Pair;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-
+-import org.codehaus.groovy.ast.ASTNode;
+-import org.codehaus.groovy.ast.CodeVisitorSupport;
+-import org.codehaus.groovy.ast.GroovyCodeVisitor;
+-import org.codehaus.groovy.ast.builder.AstBuilder;
+-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+-import org.codehaus.groovy.ast.expr.ClosureExpression;
+-import org.codehaus.groovy.ast.expr.Expression;
+-import org.codehaus.groovy.ast.expr.MapEntryExpression;
+-import org.codehaus.groovy.ast.expr.MethodCallExpression;
+-import org.codehaus.groovy.ast.expr.NamedArgumentListExpression;
+-import org.codehaus.groovy.ast.expr.TupleExpression;
+-import org.codehaus.groovy.ast.stmt.BlockStatement;
+-import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+-import org.codehaus.groovy.ast.stmt.ReturnStatement;
+-import org.codehaus.groovy.ast.stmt.Statement;
+-
+-import java.util.List;
+-import java.util.Map;
+-
+-/**
+- * Implementation of the {@link GradleDetector} using a real Groovy AST,
+- * which the Gradle plugin has access to
+- */
+-public class GroovyGradleDetector extends GradleDetector {
+-    static final Implementation IMPLEMENTATION = new Implementation(
+-            GroovyGradleDetector.class,
+-            Scope.GRADLE_SCOPE);
+-
+-    @Override
+-    public void visitBuildScript(@NonNull final Context context, Map<String, Object> sharedData) {
+-        try {
+-            visitQuietly(context, sharedData);
+-        } catch (Throwable t) {
+-            // ignore
+-            // Parsing the build script can involve class loading that we sometimes can't
+-            // handle. This happens for example when running lint in build-system/tests/api/.
+-            // This is a lint limitation rather than a user error, so don't complain
+-            // about these. Consider reporting a Issue#LINT_ERROR.
+-        }
+-    }
+-
+-    private void visitQuietly(@NonNull final Context context, Map<String, Object> sharedData) {
+-        String source = context.getContents();
+-        if (source == null) {
+-            return;
+-        }
+-
+-        List<ASTNode> astNodes = new AstBuilder().buildFromString(source);
+-        GroovyCodeVisitor visitor = new CodeVisitorSupport() {
+-            private List<MethodCallExpression> mMethodCallStack = Lists.newArrayList();
+-            @Override
+-            public void visitMethodCallExpression(MethodCallExpression expression) {
+-                mMethodCallStack.add(expression);
+-                super.visitMethodCallExpression(expression);
+-                Expression arguments = expression.getArguments();
+-                String parent = expression.getMethodAsString();
+-                String parentParent = getParentParent();
+-                if (arguments instanceof ArgumentListExpression) {
+-                    ArgumentListExpression ale = (ArgumentListExpression)arguments;
+-                    List<Expression> expressions = ale.getExpressions();
+-                    if (expressions.size() == 1 &&
+-                            expressions.get(0) instanceof ClosureExpression) {
+-                        if (isInterestingBlock(parent, parentParent)) {
+-                            ClosureExpression closureExpression =
+-                                    (ClosureExpression)expressions.get(0);
+-                            Statement block = closureExpression.getCode();
+-                            if (block instanceof BlockStatement) {
+-                                BlockStatement bs = (BlockStatement)block;
+-                                for (Statement statement : bs.getStatements()) {
+-                                    if (statement instanceof ExpressionStatement) {
+-                                        ExpressionStatement e = (ExpressionStatement)statement;
+-                                        if (e.getExpression() instanceof MethodCallExpression) {
+-                                            checkDslProperty(parent,
+-                                                    (MethodCallExpression)e.getExpression(),
+-                                                    parentParent);
+-                                        }
+-                                    } else if (statement instanceof ReturnStatement) {
+-                                        // Single item in block
+-                                        ReturnStatement e = (ReturnStatement)statement;
+-                                        if (e.getExpression() instanceof MethodCallExpression) {
+-                                            checkDslProperty(parent,
+-                                                    (MethodCallExpression)e.getExpression(),
+-                                                    parentParent);
+-                                        }
+-                                    }
+-                                }
+-                            }
+-                        }
+-                    }
+-                } else if (arguments instanceof TupleExpression) {
+-                    if (isInterestingStatement(parent, parentParent)) {
+-                        TupleExpression te = (TupleExpression) arguments;
+-                        Map<String, String> namedArguments = Maps.newHashMap();
+-                        List<String> unnamedArguments = Lists.newArrayList();
+-                        for (Expression subExpr : te.getExpressions()) {
+-                            if (subExpr instanceof NamedArgumentListExpression) {
+-                                NamedArgumentListExpression nale = (NamedArgumentListExpression) subExpr;
+-                                for (MapEntryExpression mae : nale.getMapEntryExpressions()) {
+-                                    namedArguments.put(mae.getKeyExpression().getText(),
+-                                            mae.getValueExpression().getText());
+-                                }
+-                            }
+-                        }
+-                        checkMethodCall(context, parent, parentParent, namedArguments, unnamedArguments, expression);
+-                    }
+-                }
+-                assert !mMethodCallStack.isEmpty();
+-                assert mMethodCallStack.get(mMethodCallStack.size() - 1) == expression;
+-                mMethodCallStack.remove(mMethodCallStack.size() - 1);
+-            }
+-
+-            private String getParentParent() {
+-                for (int i = mMethodCallStack.size() - 2; i >= 0; i--) {
+-                    MethodCallExpression expression = mMethodCallStack.get(i);
+-                    Expression arguments = expression.getArguments();
+-                    if (arguments instanceof ArgumentListExpression) {
+-                        ArgumentListExpression ale = (ArgumentListExpression)arguments;
+-                        List<Expression> expressions = ale.getExpressions();
+-                        if (expressions.size() == 1 &&
+-                                expressions.get(0) instanceof ClosureExpression) {
+-                            return expression.getMethodAsString();
+-                        }
+-                    }
+-                }
+-
+-                return null;
+-            }
+-
+-            private void checkDslProperty(String parent, MethodCallExpression c,
+-                    String parentParent) {
+-                String property = c.getMethodAsString();
+-                if (isInterestingProperty(property, parent, getParentParent())) {
+-                    String value = getText(c.getArguments());
+-                    checkDslPropertyAssignment(context, property, value, parent, parentParent, c, c);
+-                }
+-            }
+-
+-            private String getText(ASTNode node) {
+-                String source = context.getContents();
+-                Pair<Integer, Integer> offsets = getOffsets(node, context);
+-                return source.substring(offsets.getFirst(), offsets.getSecond());
+-            }
+-        };
+-
+-        for (ASTNode node : astNodes) {
+-            node.visit(visitor);
+-        }
+-    }
+-
+-    @NonNull
+-    private static Pair<Integer, Integer> getOffsets(ASTNode node, Context context) {
+-        if (node.getLastLineNumber() == -1 && node instanceof TupleExpression) {
+-            // Workaround: TupleExpressions yield bogus offsets, so use its
+-            // children instead
+-            TupleExpression exp = (TupleExpression) node;
+-            List<Expression> expressions = exp.getExpressions();
+-            if (!expressions.isEmpty()) {
+-                return Pair.of(
+-                        getOffsets(expressions.get(0), context).getFirst(),
+-                        getOffsets(expressions.get(expressions.size() - 1), context).getSecond());
+-            }
+-        }
+-        String source = context.getContents();
+-        assert source != null; // because we successfully parsed
+-        int start = 0;
+-        int end = source.length();
+-        int line = 1;
+-        int startLine = node.getLineNumber();
+-        int startColumn = node.getColumnNumber();
+-        int endLine = node.getLastLineNumber();
+-        int endColumn = node.getLastColumnNumber();
+-        int column = 1;
+-        for (int index = 0, len = end; index < len; index++) {
+-            if (line == startLine && column == startColumn) {
+-                start = index;
+-            }
+-            if (line == endLine && column == endColumn) {
+-                end = index;
+-                break;
+-            }
+-
+-            char c = source.charAt(index);
+-            if (c == '\n') {
+-                line++;
+-                column = 1;
+-            } else {
+-                column++;
+-            }
+-        }
+-
+-        return Pair.of(start, end);
+-    }
+-
+-    @Override
+-    protected int getStartOffset(@NonNull Context context, @NonNull Object cookie) {
+-        ASTNode node = (ASTNode) cookie;
+-        Pair<Integer, Integer> offsets = getOffsets(node, context);
+-        return offsets.getFirst();
+-    }
+-
+-    @Override
+-    protected Location createLocation(@NonNull Context context, @NonNull Object cookie) {
+-        ASTNode node = (ASTNode) cookie;
+-        Pair<Integer, Integer> offsets = getOffsets(node, context);
+-        int fromLine = node.getLineNumber() - 1;
+-        int fromColumn = node.getColumnNumber() - 1;
+-        int toLine = node.getLastLineNumber() - 1;
+-        int toColumn = node.getLastColumnNumber() - 1;
+-        return Location.create(context.file,
+-                new DefaultPosition(fromLine, fromColumn, offsets.getFirst()),
+-                new DefaultPosition(toLine, toColumn, offsets.getSecond()));
+-    }
+-}
+\ No newline at end of file
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/Lint.groovy b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/Lint.groovy
+deleted file mode 100644
+index d3b4e42..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/Lint.groovy
++++ /dev/null
+@@ -1,295 +0,0 @@
+-/*
+- * Copyright (C) 2013 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.build.gradle.tasks
+-import com.android.annotations.NonNull
+-import com.android.annotations.Nullable
+-import com.android.build.gradle.internal.LintGradleClient
+-import com.android.build.gradle.internal.dsl.LintOptions
+-import com.android.build.gradle.internal.scope.TaskConfigAction
+-import com.android.build.gradle.internal.scope.VariantScope
+-import com.android.build.gradle.internal.tasks.DefaultAndroidTask
+-import com.android.builder.model.AndroidProject
+-import com.android.builder.model.Variant
+-import com.android.tools.lint.LintCliFlags
+-import com.android.tools.lint.Reporter
+-import com.android.tools.lint.Warning
+-import com.android.tools.lint.checks.BuiltinIssueRegistry
+-import com.android.tools.lint.checks.GradleDetector
+-import com.android.tools.lint.client.api.IssueRegistry
+-import com.android.tools.lint.detector.api.Issue
+-import com.android.tools.lint.detector.api.Severity
+-import com.google.common.collect.Maps
+-import org.gradle.api.GradleException
+-import org.gradle.api.Project
+-import org.gradle.api.plugins.JavaBasePlugin
+-import org.gradle.api.tasks.ParallelizableTask
+-import org.gradle.api.tasks.TaskAction
+-import org.gradle.tooling.provider.model.ToolingModelBuilder
+-import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
+-
+- at ParallelizableTask
+-public class Lint extends DefaultAndroidTask {
+-    @NonNull private LintOptions mLintOptions
+-    @Nullable private File mSdkHome
+-    private boolean mFatalOnly
+-    private ToolingModelBuilderRegistry mToolingRegistry
+-
+-    public void setLintOptions(@NonNull LintOptions lintOptions) {
+-        mLintOptions = lintOptions
+-    }
+-
+-    public void setSdkHome(@NonNull File sdkHome) {
+-        mSdkHome = sdkHome
+-    }
+-
+-    void setToolingRegistry(ToolingModelBuilderRegistry toolingRegistry) {
+-        mToolingRegistry = toolingRegistry
+-    }
+-
+-    public void setFatalOnly(boolean fatalOnly) {
+-        mFatalOnly = fatalOnly
+-    }
+-
+-    @SuppressWarnings("GroovyUnusedDeclaration")
+-    @TaskAction
+-    public void lint() {
+-        def modelProject = createAndroidProject(project)
+-        if (getVariantName() != null) {
+-            lintSingleVariant(modelProject, getVariantName())
+-        } else {
+-            lintAllVariants(modelProject)
+-        }
+-    }
+-
+-    /**
+-     * Runs lint individually on all the variants, and then compares the results
+-     * across variants and reports these
+-     */
+-    public void lintAllVariants(@NonNull AndroidProject modelProject) {
+-        Map<Variant,List<Warning>> warningMap = Maps.newHashMap()
+-        for (Variant variant : modelProject.getVariants()) {
+-            try {
+-                List<Warning> warnings = runLint(modelProject, variant.getName(), false)
+-                warningMap.put(variant, warnings)
+-            } catch (IOException e) {
+-                throw new GradleException("Invalid arguments.", e)
+-            }
+-        }
+-
+-        // Compute error matrix
+-        def quiet = mLintOptions.quiet
+-
+-
+-        for (Map.Entry<Variant,List<Warning>> entry : warningMap.entrySet()) {
+-            def variant = entry.getKey()
+-            def warnings = entry.getValue()
+-            if (!mFatalOnly && !quiet) {
+-                println "Ran lint on variant " + variant.getName() + ": " + warnings.size() +
+-                        " issues found"
+-            }
+-        }
+-
+-        List<Warning> mergedWarnings = LintGradleClient.merge(warningMap, modelProject)
+-        int errorCount = 0
+-        int warningCount = 0
+-        for (Warning warning : mergedWarnings) {
+-            if (warning.severity == Severity.ERROR || warning.severity == Severity.FATAL) {
+-                errorCount++
+-            } else if (warning.severity == Severity.WARNING) {
+-                warningCount++
+-            }
+-        }
+-
+-        IssueRegistry registry = new BuiltinIssueRegistry()
+-        LintCliFlags flags = new LintCliFlags()
+-        LintGradleClient client = new LintGradleClient(registry, flags, project, modelProject,
+-                mSdkHome, null)
+-        syncOptions(mLintOptions, client, flags, null, project, true, mFatalOnly)
+-
+-        for (Reporter reporter : flags.getReporters()) {
+-            reporter.write(errorCount, warningCount, mergedWarnings)
+-        }
+-
+-        if (flags.isSetExitCode() && errorCount > 0) {
+-            abort()
+-        }
+-    }
+-
+-    private void abort() {
+-        def message;
+-        if (mFatalOnly) {
+-            message = "" +
+-                    "Lint found fatal errors while assembling a release target.\n" +
+-                    "\n" +
+-                    "To proceed, either fix the issues identified by lint, or modify your build script as follows:\n" +
+-                    "...\n" +
+-                    "android {\n" +
+-                    "    lintOptions {\n" +
+-                    "        checkReleaseBuilds false\n" +
+-                    "        // Or, if you prefer, you can continue to check for errors in release builds,\n" +
+-                    "        // but continue the build even when errors are found:\n" +
+-                    "        abortOnError false\n" +
+-                    "    }\n" +
+-                    "}\n" +
+-                    "..."
+-                    ""
+-        } else {
+-            message = "" +
+-                    "Lint found errors in the project; aborting build.\n" +
+-                    "\n" +
+-                    "Fix the issues identified by lint, or add the following to your build script to proceed with errors:\n" +
+-                    "...\n" +
+-                    "android {\n" +
+-                    "    lintOptions {\n" +
+-                    "        abortOnError false\n" +
+-                    "    }\n" +
+-                    "}\n" +
+-                    "..."
+-        }
+-        throw new GradleException(message);
+-    }
+-
+-    /**
+-     * Runs lint on a single specified variant
+-     */
+-    public void lintSingleVariant(@NonNull AndroidProject modelProject, String variantName) {
+-        runLint(modelProject, variantName, true)
+-    }
+-
+-    /** Runs lint on the given variant and returns the set of warnings */
+-    private List<Warning> runLint(
+-            @NonNull AndroidProject modelProject,
+-            @NonNull String variantName,
+-            boolean report) {
+-        IssueRegistry registry = createIssueRegistry()
+-        LintCliFlags flags = new LintCliFlags()
+-        LintGradleClient client = new LintGradleClient(registry, flags, project, modelProject,
+-                mSdkHome, variantName)
+-        if (mFatalOnly) {
+-            if (!mLintOptions.isCheckReleaseBuilds()) {
+-                return
+-            }
+-            flags.setFatalOnly(true)
+-        }
+-        syncOptions(mLintOptions, client, flags, variantName, project, report, mFatalOnly)
+-        if (!report || mFatalOnly) {
+-            flags.setQuiet(true)
+-        }
+-
+-        List<Warning> warnings;
+-        try {
+-            warnings = client.run(registry)
+-        } catch (IOException e) {
+-            throw new GradleException("Invalid arguments.", e)
+-        }
+-
+-        if (report && client.haveErrors() && flags.isSetExitCode()) {
+-            abort()
+-        }
+-
+-        return warnings;
+-    }
+-
+-    private static syncOptions(
+-            @NonNull LintOptions options,
+-            @NonNull LintGradleClient client,
+-            @NonNull LintCliFlags flags,
+-            @NonNull String variantName,
+-            @NonNull Project project,
+-            boolean report,
+-            boolean fatalOnly) {
+-        options.syncTo(client, flags, variantName, project, report)
+-
+-        if (fatalOnly || flags.quiet) {
+-            for (Reporter reporter : flags.getReporters()) {
+-                reporter.setDisplayEmpty(false)
+-            }
+-        }
+-    }
+-
+-    private AndroidProject createAndroidProject(@NonNull Project gradleProject) {
+-        String modelName = AndroidProject.class.getName()
+-        ToolingModelBuilder modelBuilder = mToolingRegistry.getBuilder(modelName)
+-        assert modelBuilder != null
+-        return (AndroidProject) modelBuilder.buildAll(modelName, gradleProject)
+-    }
+-
+-    private static BuiltinIssueRegistry createIssueRegistry() {
+-        return new LintGradleIssueRegistry()
+-    }
+-
+-    // Issue registry when Lint is run inside Gradle: we replace the Gradle
+-    // detector with a local implementation which directly references Groovy
+-    // for parsing. In Studio on the other hand, the implementation is replaced
+-    // by a PSI-based check. (This is necessary for now since we don't have a
+-    // tool-agnostic API for the Groovy AST and we don't want to add a 6.3MB dependency
+-    // on Groovy itself quite yet.
+-    public static class LintGradleIssueRegistry extends BuiltinIssueRegistry {
+-        private boolean mInitialized;
+-
+-        public LintGradleIssueRegistry() {
+-        }
+-
+-        @NonNull
+-        @Override
+-        public List<Issue> getIssues() {
+-            List<Issue> issues = super.getIssues();
+-            if (!mInitialized) {
+-                mInitialized = true;
+-                for (Issue issue : issues) {
+-                    if (issue.getImplementation().getDetectorClass() == GradleDetector.class) {
+-                        issue.setImplementation(GroovyGradleDetector.IMPLEMENTATION);
+-                    }
+-                }
+-            }
+-
+-            return issues;
+-        }
+-    }
+-
+-    public static class ConfigAction implements TaskConfigAction<Lint> {
+-
+-        @NonNull
+-        VariantScope scope
+-
+-        ConfigAction(@NonNull VariantScope scope) {
+-            this.scope = scope
+-        }
+-
+-        @Override
+-        @NonNull
+-        String getName() {
+-            return scope.getTaskName("lint")
+-        }
+-
+-        @Override
+-        @NonNull
+-        Class<Lint> getType() {
+-            return Lint
+-        }
+-
+-        @Override
+-        void execute(Lint lint) {
+-            lint.setLintOptions(scope.globalScope.getExtension().lintOptions)
+-            lint.setSdkHome(scope.globalScope.sdkHandler.getSdkFolder())
+-            lint.setVariantName(scope.variantConfiguration.fullName)
+-            lint.setToolingRegistry(scope.globalScope.toolingRegistry)
+-            lint.description = "Runs lint on the " + scope.variantConfiguration.fullName.capitalize() + " build."
+-            lint.group = JavaBasePlugin.VERIFICATION_GROUP
+-        }
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/PackageApplication.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/PackageApplication.java
+index 16ab90c..52f085b 100644
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/PackageApplication.java
++++ b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/PackageApplication.java
+@@ -286,22 +286,6 @@ public class PackageApplication extends IncrementalTask implements FileSupplier
+             packageApp.setVariantName(
+                     scope.getVariantScope().getVariantConfiguration().getFullName());
+ 
+-            if (config.isMinifyEnabled() && config.getBuildType().isShrinkResources() && !config
+-                    .getUseJack()) {
+-                ConventionMappingHelper.map(packageApp, "resourceFile", new Callable<File>() {
+-                    @Override
+-                    public File call() {
+-                        return scope.getCompressedResourceFile();
+-                    }
+-                });
+-            } else {
+-                ConventionMappingHelper.map(packageApp, "resourceFile", new Callable<File>() {
+-                    @Override
+-                    public File call() {
+-                        return variantOutputData.processResourcesTask.getPackageOutputFile();
+-                    }
+-                });
+-            }
+ 
+             ConventionMappingHelper.map(packageApp, "dexFolder", new Callable<File>() {
+                 @Override
+@@ -437,36 +421,6 @@ public class PackageApplication extends IncrementalTask implements FileSupplier
+             });
+         }
+ 
+-        private ShrinkResources createShrinkResourcesTask(
+-                final ApkVariantOutputData variantOutputData) {
+-            BaseVariantData<?> variantData = (BaseVariantData<?>) variantOutputData.variantData;
+-            ShrinkResources task = scope.getGlobalScope().getProject().getTasks()
+-                    .create("shrink" + StringGroovyMethods
+-                            .capitalize(variantOutputData.getFullName())
+-                            + "Resources", ShrinkResources.class);
+-            task.setAndroidBuilder(scope.getGlobalScope().getAndroidBuilder());
+-            task.setVariantName(scope.getVariantScope().getVariantConfiguration().getFullName());
+-            task.variantOutputData = variantOutputData;
+-
+-            final String outputBaseName = variantOutputData.getBaseName();
+-            task.setCompressedResources(new File(
+-                    scope.getGlobalScope().getBuildDir() + "/" + FD_INTERMEDIATES + "/res/" +
+-                            "resources-" + outputBaseName + "-stripped.ap_"));
+-
+-            ConventionMappingHelper.map(task, "uncompressedResources", new Callable<File>() {
+-                @Override
+-                public File call() {
+-                    return variantOutputData.processResourcesTask.getPackageOutputFile();
+-                }
+-            });
+-
+-            task.dependsOn(
+-                    scope.getVariantScope().getObfuscationTask().getName(),
+-                    scope.getManifestProcessorTask().getName(),
+-                    variantOutputData.processResourcesTask);
+-
+-            return task;
+-        }
+ 
+         private static File getOptionalDir(File dir) {
+             if (dir.isDirectory()) {
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ResourceUsageAnalyzer.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ResourceUsageAnalyzer.java
+deleted file mode 100644
+index 649a8d0..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ResourceUsageAnalyzer.java
++++ /dev/null
+@@ -1,2568 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks;
+-
+-import static com.android.SdkConstants.ANDROID_STYLE_RESOURCE_PREFIX;
+-import static com.android.SdkConstants.ANDROID_URI;
+-import static com.android.SdkConstants.ATTR_NAME;
+-import static com.android.SdkConstants.ATTR_PARENT;
+-import static com.android.SdkConstants.ATTR_TYPE;
+-import static com.android.SdkConstants.DOT_CLASS;
+-import static com.android.SdkConstants.DOT_GIF;
+-import static com.android.SdkConstants.DOT_JPEG;
+-import static com.android.SdkConstants.DOT_JPG;
+-import static com.android.SdkConstants.DOT_PNG;
+-import static com.android.SdkConstants.DOT_XML;
+-import static com.android.SdkConstants.FD_RES_VALUES;
+-import static com.android.SdkConstants.PREFIX_ANDROID;
+-import static com.android.SdkConstants.STYLE_RESOURCE_PREFIX;
+-import static com.android.SdkConstants.TAG_ITEM;
+-import static com.android.SdkConstants.TAG_RESOURCES;
+-import static com.android.SdkConstants.TAG_STYLE;
+-import static com.android.SdkConstants.TOOLS_URI;
+-import static com.android.utils.SdkUtils.endsWith;
+-import static com.android.utils.SdkUtils.endsWithIgnoreCase;
+-import static com.google.common.base.Charsets.UTF_8;
+-import static org.objectweb.asm.ClassReader.SKIP_DEBUG;
+-import static org.objectweb.asm.ClassReader.SKIP_FRAMES;
+-
+-import com.android.SdkConstants;
+-import com.android.annotations.NonNull;
+-import com.android.annotations.Nullable;
+-import com.android.annotations.VisibleForTesting;
+-import com.android.ide.common.resources.ResourceUrl;
+-import com.android.ide.common.resources.configuration.DensityQualifier;
+-import com.android.ide.common.resources.configuration.FolderConfiguration;
+-import com.android.ide.common.resources.configuration.ResourceQualifier;
+-import com.android.ide.common.xml.XmlPrettyPrinter;
+-import com.android.resources.FolderTypeRelationship;
+-import com.android.resources.ResourceFolderType;
+-import com.android.resources.ResourceType;
+-import com.android.tools.lint.checks.StringFormatDetector;
+-import com.android.tools.lint.client.api.DefaultConfiguration;
+-import com.android.tools.lint.detector.api.LintUtils;
+-import com.android.utils.XmlUtils;
+-import com.google.common.base.Joiner;
+-import com.google.common.base.Splitter;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-import com.google.common.collect.Sets;
+-import com.google.common.io.ByteStreams;
+-import com.google.common.io.Closeables;
+-import com.google.common.io.Files;
+-
+-import org.objectweb.asm.AnnotationVisitor;
+-import org.objectweb.asm.ClassReader;
+-import org.objectweb.asm.ClassVisitor;
+-import org.objectweb.asm.FieldVisitor;
+-import org.objectweb.asm.MethodVisitor;
+-import org.objectweb.asm.Opcodes;
+-import org.w3c.dom.Attr;
+-import org.w3c.dom.Document;
+-import org.w3c.dom.Element;
+-import org.w3c.dom.NamedNodeMap;
+-import org.w3c.dom.Node;
+-import org.w3c.dom.NodeList;
+-import org.xml.sax.SAXException;
+-
+-import java.io.File;
+-import java.io.FileInputStream;
+-import java.io.FileOutputStream;
+-import java.io.IOException;
+-import java.util.ArrayList;
+-import java.util.Collections;
+-import java.util.Comparator;
+-import java.util.IdentityHashMap;
+-import java.util.List;
+-import java.util.Map;
+-import java.util.Set;
+-import java.util.jar.JarEntry;
+-import java.util.jar.JarInputStream;
+-import java.util.jar.JarOutputStream;
+-import java.util.regex.Matcher;
+-import java.util.regex.Pattern;
+-import java.util.regex.PatternSyntaxException;
+-import java.util.zip.ZipEntry;
+-import java.util.zip.ZipInputStream;
+-
+-import javax.xml.parsers.ParserConfigurationException;
+-
+-/**
+- * Class responsible for searching through a Gradle built tree (after resource merging,
+- * compilation and ProGuarding has been completed, but before final .apk assembly), which
+- * figures out which resources if any are unused, and removes them.
+- * <p>
+- * It does this by examining
+- * <ul>
+- *     <li>The merged manifest, to find root resource references (such as drawables
+- *         used for activity icons)</li>
+- *     <li>The merged R class (to find the actual integer constants assigned to resources)</li>
+- *     <li>The ProGuard log files (to find the mapping from original symbol names to
+- *         short names)</li>*
+- *     <li>The merged resources (to find which resources reference other resources, e.g.
+- *         drawable state lists including other drawables, or layouts including other
+- *         layouts, or styles referencing other drawables, or menus items including action
+- *         layouts, etc.)</li>
+- *     <li>The ProGuard output classes (to find resource references in code that are
+- *         actually reachable)</li>
+- * </ul>
+- * From all this, it builds up a reference graph, and based on the root references (e.g.
+- * from the manifest and from the remaining code) it computes which resources are actually
+- * reachable in the app, and anything that is not reachable is then marked for deletion.
+- * <p>
+- * A resource is referenced in code if either the field R.type.name is referenced (which
+- * is the case for non-final resource references, e.g. in libraries), or if the corresponding
+- * int value is referenced (for final resource values). We check this by looking at the
+- * ProGuard output classes with an ASM visitor. One complication is that code can also
+- * call {@code Resources#getIdentifier(String,String,String)} where they can pass in the names
+- * of resources to look up. To handle this scenario, we use the ClassVisitor to see if
+- * there are any calls to the specific {@code Resources#getIdentifier} method. If not,
+- * great, the usage analysis is completely accurate. If we <b>do</b> find one, we check
+- * <b>all</b> the string constants found anywhere in the app, and look to see if any look
+- * relevant. For example, if we find the string "string/foo" or "my.pkg:string/foo", we
+- * will then mark the string resource named foo (if any) as potentially used. Similarly,
+- * if we find just "foo" or "/foo", we will mark <b>all</b> resources named "foo" as
+- * potentially used. However, if the string is "bar/foo" or " foo " these strings are
+- * ignored. This means we can potentially miss resources usages where the resource name
+- * is completed computed (e.g. by concatenating individual characters or taking substrings
+- * of strings that do not look like resource names), but that seems extremely unlikely
+- * to be a real-world scenario.
+- * <p>
+- * For now, for reasons detailed in the code, this only applies to file-based resources
+- * like layouts, menus and drawables, not value-based resources like strings and dimensions.
+- */
+-public class ResourceUsageAnalyzer {
+-    private static final String ANDROID_RES = "android_res/";
+-
+-    /**
+-     Whether we support running aapt twice, to regenerate the resources.arsc file
+-     such that we can strip out value resources as well. We don't do this yet, for
+-     reasons detailed in the ShrinkResources task
+-
+-     We have two options:
+-     (1) Copy the resource files over to a new destination directory, filtering out
+-     removed file resources and rewriting value resource files by stripping out
+-     the declarations for removed value resources. We then re-run aapt on this
+-     new destination directory.
+-
+-     The problem with this approach is that when we re-run aapt it will assign new
+-     id's to all the resources, so we have to create dummy placeholders for all the
+-     removed resources. (The alternative would be to then run compilation one more
+-     time -- regenerating classes.jar, regenerating .dex) -- this would really slow
+-     down builds.)
+-
+-     A cleaner solution than this is to get aapt to support using a predefined set
+-     of id's. It can emit R.txt symbol files now; if we can get it to read R.txt
+-     and use those numbers in its assignment, we can solve this cleanly. This request
+-     is tracked in https://code.google.com/p/android/issues/detail?id=70869
+-
+-     (2) Just rewrite the .ap_ file directly. It's just a .zip file which contains
+-     (a) binary files for bitmaps and XML file resources such as layouts and menus
+-     (b) a binary file, resources.arsc, containing all the values.
+-     The resources.arsc format is opaque to us. However, MOST of the resource bulk
+-     comes from the bitmap and other resource files.
+-
+-     So here we don't even need to run aapt a second time; we simply rewrite the
+-     .ap_ zip file directly, filtering out res/ files we know to be unused.
+-
+-     Approach #2 gives us most of the space savings without the risk of #1 (running aapt
+-     a second time introduces the possibility of aapt compilation errors if we haven't
+-     been careful enough to insert resource aliases for all necessary items (such as
+-     inline @+id declarations), or if we haven't carefully not created aliases for items
+-     already defined in other value files as aliases, and perhaps most importantly,
+-     introduces risk that aapt will pick a different resource order anyway, which we can
+-     only guard against by doing a full compilation over again.
+-
+-     Therefore, for now the below code uses #2, but since we can solve #1 with support
+-     from aapt), we're preserving all the code to rewrite resource files since that will
+-     give additional space savings, particularly for apps with a lot of strings or a lot
+-     of translations.
+-     */
+-    @SuppressWarnings("SpellCheckingInspection") // arsc
+-    public static final boolean TWO_PASS_AAPT = false;
+-    public static final int TYPICAL_RESOURCE_COUNT = 200;
+-
+-    /** Name of keep attribute in XML */
+-    private static final String ATTR_KEEP = "keep";
+-    /** Name of discard attribute in XML (to mark resources as not referenced, despite guesses) */
+-    private static final String ATTR_DISCARD = "discard";
+-    /** Name of attribute in XML to control whether we should guess resources to keep */
+-    private static final String ATTR_SHRINK_MODE = "shrinkMode";
+-    /** @{linkplain #ATTR_SHRINK_MODE} value to only shrink explicitly encountered resources */
+-    private static final String VALUE_STRICT = "strict";
+-    /** @{linkplain #ATTR_SHRINK_MODE} value to keep possibly referenced resources */
+-    private static final String VALUE_SAFE = "safe";
+-
+-    /** Special marker regexp which does not match a resource name */
+-    static final String NO_MATCH = "-nomatch-";
+-
+-    private final File mResourceClassDir;
+-    private final File mProguardMapping;
+-    private final File mClassesJar;
+-    private final File mMergedManifest;
+-    private final File mMergedResourceDir;
+-
+-    private boolean mVerbose;
+-    private boolean mDebug;
+-    private boolean mDryRun;
+-
+-    /** The computed set of unused resources */
+-    private List<Resource> mUnused;
+-
+-    /** List of all known resources (parsed from R.java) */
+-    private List<Resource> mResources = Lists.newArrayListWithExpectedSize(TYPICAL_RESOURCE_COUNT);
+-    /** Map from R field value to corresponding resource */
+-    private Map<Integer, Resource> mValueToResource =
+-            Maps.newHashMapWithExpectedSize(TYPICAL_RESOURCE_COUNT);
+-    /** Map from resource type to map from resource name to resource object */
+-    private Map<ResourceType, Map<String, Resource>> mTypeToName =
+-            Maps.newEnumMap(ResourceType.class);
+-    /** Map from resource class owners (VM format class) to corresponding resource types.
+-     * This will typically be the fully qualified names of the R classes, as well as
+-     * any renamed versions of those discovered in the mapping.txt file from ProGuard */
+-    private Map<String, ResourceType> mResourceClassOwners = Maps.newHashMapWithExpectedSize(20);
+-
+-    /**
+-     * Whether we should attempt to guess resources that should be kept based on looking
+-     * at the string pool and assuming some of the strings can be used to dynamically construct
+-     * the resource names. Can be turned off via {@code tools:guessKeep="false"}.
+-     */
+-    private boolean mGuessKeep = true;
+-
+-    public ResourceUsageAnalyzer(
+-            @NonNull File rDir,
+-            @NonNull File classesJar,
+-            @NonNull File manifest,
+-            @Nullable File mapping,
+-            @NonNull File resources) {
+-        mResourceClassDir = rDir;
+-        mProguardMapping = mapping;
+-        mClassesJar = classesJar;
+-        mMergedManifest = manifest;
+-        mMergedResourceDir = resources;
+-    }
+-
+-    public void analyze() throws IOException, ParserConfigurationException, SAXException {
+-        gatherResourceValues(mResourceClassDir);
+-        recordMapping(mProguardMapping);
+-        recordUsages(mClassesJar);
+-        recordManifestUsages(mMergedManifest);
+-        recordResources(mMergedResourceDir);
+-        keepPossiblyReferencedResources();
+-        dumpReferences();
+-        findUnused();
+-    }
+-
+-    public boolean isDryRun() {
+-        return mDryRun;
+-    }
+-
+-    public void setDryRun(boolean dryRun) {
+-        mDryRun = dryRun;
+-    }
+-
+-    public boolean isVerbose() {
+-        return mVerbose;
+-    }
+-
+-    public void setVerbose(boolean verbose) {
+-        mVerbose = verbose;
+-    }
+-
+-
+-    public boolean isDebug() {
+-        return mDebug;
+-    }
+-
+-    public void setDebug(boolean verbose) {
+-        mDebug = verbose;
+-    }
+-
+-    /**
+-     * "Removes" resources from an .ap_ file by writing it out while filtering out
+-     * unused resources. This won't touch the values XML data (resources.arsc) but
+-     * will remove the individual file-based resources, which is where most of
+-     * the data is anyway (usually in drawable bitmaps)
+-     *
+-     * @param source the .ap_ file created by aapt
+-     * @param dest a new .ap_ file with unused file-based resources removed
+-     */
+-    public void rewriteResourceZip(@NonNull File source, @NonNull File dest)
+-            throws IOException {
+-        if (dest.exists()) {
+-            boolean deleted = dest.delete();
+-            if (!deleted) {
+-                throw new IOException("Could not delete " + dest);
+-            }
+-        }
+-
+-        JarInputStream zis = null;
+-        try {
+-            FileInputStream fis = new FileInputStream(source);
+-            try {
+-                FileOutputStream fos = new FileOutputStream(dest);
+-                zis = new JarInputStream(fis);
+-                JarOutputStream zos = new JarOutputStream(fos);
+-                try {
+-                    // Rather than using Deflater.DEFAULT_COMPRESSION we use 9 here,
+-                    // since that seems to match the compressed sizes we observe in source
+-                    // .ap_ files encountered by the resource shrinker:
+-                    zos.setLevel(9);
+-
+-                    ZipEntry entry = zis.getNextEntry();
+-                    while (entry != null) {
+-                        String name = entry.getName();
+-                        boolean directory = entry.isDirectory();
+-                        Resource resource = getResourceByJarPath(name);
+-                        if (resource == null || resource.reachable) {
+-                            // We can't just compress all files; files that are not
+-                            // compressed in the source .ap_ file must be left uncompressed
+-                            // here, since for example RAW files need to remain uncompressed in
+-                            // the APK such that they can be mmap'ed at runtime.
+-                            // Preserve the STORED method of the input entry.
+-                            JarEntry outEntry;
+-                            if (entry.getMethod() == JarEntry.STORED) {
+-                                outEntry = new JarEntry(entry);
+-                            } else {
+-                                // Create a new entry so that the compressed len is recomputed.
+-                                outEntry = new JarEntry(name);
+-                                if (entry.getTime() != -1L) {
+-                                    outEntry.setTime(entry.getTime());
+-                                }
+-                            }
+-
+-                            zos.putNextEntry(outEntry);
+-
+-                            if (!directory) {
+-                                byte[] bytes = ByteStreams.toByteArray(zis);
+-                                if (bytes != null) {
+-                                    zos.write(bytes);
+-                                }
+-                            }
+-
+-                            zos.closeEntry();
+-                        } else if (isVerbose()) {
+-                            System.out.println("Skipped unused resource " + name + ": "
+-                                    + entry.getSize() + " bytes");
+-                        }
+-                        entry = zis.getNextEntry();
+-                    }
+-                    zos.flush();
+-                } finally {
+-                    Closeables.close(zos, false);
+-                }
+-            } finally {
+-                Closeables.close(fis, true);
+-            }
+-        } finally {
+-            Closeables.close(zis, false);
+-        }
+-    }
+-
+-    /**
+-     * Remove resources (already identified by {@link #analyze()}).
+-     *
+-     * This task will copy all remaining used resources over from the full resource
+-     * directory to a new reduced resource directory. However, it can't just
+-     * delete the resources, because it has no way to tell aapt to continue to use
+-     * the same id's for the resources. When we re-run aapt on the stripped resource
+-     * directory, it will assign new id's to some of the resources (to fill the gaps)
+-     * which means the resource id's no longer match the constants compiled into the
+-     * dex files, and as a result, the app crashes at runtime.
+-     * <p>
+-     * Therefore, it needs to preserve all id's by actually keeping all the resource
+-     * names. It can still save a lot of space by making these resources tiny; e.g.
+-     * all strings are set to empty, all styles, arrays and plurals are set to not contain
+-     * any children, and most importantly, all file based resources like bitmaps and
+-     * layouts are replaced by simple resource aliases which just point to @null.
+-     *
+-     * @param destination directory to copy resources into; if null, delete resources in place
+-     * @throws IOException
+-     * @throws ParserConfigurationException
+-     * @throws SAXException
+-     */
+-    public void removeUnused(@Nullable File destination) throws IOException,
+-            ParserConfigurationException, SAXException {
+-        if (TWO_PASS_AAPT) {
+-            assert mUnused != null; // should always call analyze() first
+-
+-            int resourceCount = mUnused.size()
+-                    * 4; // *4: account for some resource folder repetition
+-            boolean inPlace = destination == null;
+-            Set<File> skip = inPlace ? null : Sets.<File>newHashSetWithExpectedSize(resourceCount);
+-            Set<File> rewrite = Sets.newHashSetWithExpectedSize(resourceCount);
+-            for (Resource resource : mUnused) {
+-                if (resource.declarations != null) {
+-                    for (File file : resource.declarations) {
+-                        String folder = file.getParentFile().getName();
+-                        ResourceFolderType folderType = ResourceFolderType.getFolderType(folder);
+-                        if (folderType != null && folderType != ResourceFolderType.VALUES) {
+-                            if (isVerbose()) {
+-                                System.out.println("Deleted unused resource " + file);
+-                            }
+-                            if (inPlace) {
+-                                if (!isDryRun()) {
+-                                    boolean delete = file.delete();
+-                                    if (!delete) {
+-                                        System.err.println("Could not delete " + file);
+-                                    }
+-                                }
+-                            } else {
+-                                assert skip != null;
+-                                skip.add(file);
+-                            }
+-                        } else {
+-                            // Can't delete values immediately; there can be many resources
+-                            // in this file, so we have to process them all
+-                            rewrite.add(file);
+-                        }
+-                    }
+-                }
+-            }
+-
+-            // Special case the base values.xml folder
+-            File values = new File(mMergedResourceDir,
+-                    FD_RES_VALUES + File.separatorChar + "values.xml");
+-            boolean valuesExists = values.exists();
+-            if (valuesExists) {
+-                rewrite.add(values);
+-            }
+-
+-            Map<File, String> rewritten = Maps.newHashMapWithExpectedSize(rewrite.size());
+-
+-            // Delete value resources: Must rewrite the XML files
+-            for (File file : rewrite) {
+-                String xml = Files.toString(file, UTF_8);
+-                Document document = XmlUtils.parseDocument(xml, true);
+-                Element root = document.getDocumentElement();
+-                if (root != null && TAG_RESOURCES.equals(root.getTagName())) {
+-                    List<String> removed = Lists.newArrayList();
+-                    stripUnused(root, removed);
+-                    if (isVerbose()) {
+-                        System.out.println("Removed " + removed.size() +
+-                                " unused resources from " + file + ":\n  " +
+-                                Joiner.on(", ").join(removed));
+-                    }
+-
+-                    String formatted = XmlPrettyPrinter.prettyPrint(document, xml.endsWith("\n"));
+-                    rewritten.put(file, formatted);
+-                }
+-            }
+-
+-            if (isDryRun()) {
+-                return;
+-            }
+-
+-            if (valuesExists) {
+-                String xml = rewritten.get(values);
+-                if (xml == null) {
+-                    xml = Files.toString(values, UTF_8);
+-                }
+-                Document document = XmlUtils.parseDocument(xml, true);
+-                Element root = document.getDocumentElement();
+-
+-                for (Resource resource : mResources) {
+-                    if (resource.type == ResourceType.ID && !resource.hasDefault) {
+-                        Element item = document.createElement(TAG_ITEM);
+-                        item.setAttribute(ATTR_TYPE, resource.type.getName());
+-                        item.setAttribute(ATTR_NAME, resource.name);
+-                        root.appendChild(item);
+-                    } else if (!resource.reachable
+-                            && !resource.hasDefault
+-                            && resource.type != ResourceType.DECLARE_STYLEABLE
+-                            && resource.type != ResourceType.STYLE
+-                            && resource.type != ResourceType.PLURALS
+-                            && resource.type != ResourceType.ARRAY
+-                            && resource.isRelevantType()) {
+-                        Element item = document.createElement(TAG_ITEM);
+-                        item.setAttribute(ATTR_TYPE, resource.type.getName());
+-                        item.setAttribute(ATTR_NAME, resource.name);
+-                        root.appendChild(item);
+-                        String s = "@null";
+-                        item.appendChild(document.createTextNode(s));
+-                    }
+-                }
+-
+-                String formatted = XmlPrettyPrinter.prettyPrint(document, xml.endsWith("\n"));
+-                rewritten.put(values, formatted);
+-            }
+-
+-            if (inPlace) {
+-                for (Map.Entry<File, String> entry : rewritten.entrySet()) {
+-                    File file = entry.getKey();
+-                    String formatted = entry.getValue();
+-                    Files.write(formatted, file, UTF_8);
+-                }
+-            } else {
+-                filteredCopy(mMergedResourceDir, destination, skip, rewritten);
+-            }
+-        } else {
+-            assert false;
+-        }
+-    }
+-
+-    /**
+-     * Copies one resource directory tree into another; skipping some files, replacing
+-     * the contents of some, and passing everything else through unmodified
+-     */
+-    private static void filteredCopy(File source, File destination, Set<File> skip,
+-            Map<File, String> replace) throws IOException {
+-        if (TWO_PASS_AAPT) {
+-            if (source.isDirectory()) {
+-                File[] children = source.listFiles();
+-                if (children != null) {
+-                    if (!destination.exists()) {
+-                        boolean success = destination.mkdirs();
+-                        if (!success) {
+-                            throw new IOException("Could not create " + destination);
+-                        }
+-                    }
+-                    for (File child : children) {
+-                        filteredCopy(child, new File(destination, child.getName()), skip, replace);
+-                    }
+-                }
+-            } else if (!skip.contains(source) && source.isFile()) {
+-                String contents = replace.get(source);
+-                if (contents != null) {
+-                    Files.write(contents, destination, UTF_8);
+-                } else {
+-                    Files.copy(source, destination);
+-                }
+-            }
+-        } else {
+-            assert false;
+-        }
+-    }
+-
+-    private void stripUnused(Element element, List<String> removed) {
+-        if (TWO_PASS_AAPT) {
+-            ResourceType type = getResourceType(element);
+-            if (type == ResourceType.ATTR) {
+-                // Not yet properly handled
+-                return;
+-            }
+-
+-            Resource resource = getResource(element);
+-            if (resource != null) {
+-                if (resource.type == ResourceType.DECLARE_STYLEABLE ||
+-                        resource.type == ResourceType.ATTR) {
+-                    // Don't strip children of declare-styleable; we're not correctly
+-                    // tracking field references of the R_styleable_attr fields yet
+-                    return;
+-                }
+-
+-                if (!resource.reachable &&
+-                        (resource.type == ResourceType.STYLE ||
+-                                resource.type == ResourceType.PLURALS ||
+-                                resource.type == ResourceType.ARRAY)) {
+-                    NodeList children = element.getChildNodes();
+-                    for (int i = children.getLength() - 1; i >= 0; i--) {
+-                        Node child = children.item(i);
+-                        element.removeChild(child);
+-                    }
+-                    return;
+-                }
+-            }
+-
+-            NodeList children = element.getChildNodes();
+-            for (int i = children.getLength() - 1; i >= 0; i--) {
+-                Node child = children.item(i);
+-                if (child.getNodeType() == Node.ELEMENT_NODE) {
+-                    stripUnused((Element) child, removed);
+-                }
+-            }
+-
+-            if (resource != null && !resource.reachable) {
+-                if (mVerbose) {
+-                    removed.add(resource.getUrl());
+-                }
+-                // for themes etc where .'s have been replaced by _'s
+-                String name = element.getAttribute(ATTR_NAME);
+-                if (name.isEmpty()) {
+-                    name = resource.name;
+-                }
+-                Node nextSibling = element.getNextSibling();
+-                Node parent = element.getParentNode();
+-                NodeList oldChildren = element.getChildNodes();
+-                parent.removeChild(element);
+-                Document document = element.getOwnerDocument();
+-                element = document.createElement("item");
+-                for (int i = 0; i < oldChildren.getLength(); i++) {
+-                    element.appendChild(oldChildren.item(i));
+-                }
+-
+-                element.setAttribute(ATTR_NAME, name);
+-                element.setAttribute(ATTR_TYPE, resource.type.getName());
+-                String text = null;
+-                switch (resource.type) {
+-                    case BOOL:
+-                        text = "true";
+-                        break;
+-                    case DIMEN:
+-                        text = "0dp";
+-                        break;
+-                    case INTEGER:
+-                        text = "0";
+-                        break;
+-                }
+-                element.setTextContent(text);
+-                parent.insertBefore(element, nextSibling);
+-            }
+-        } else {
+-            assert false;
+-        }
+-    }
+-
+-    private static String getFieldName(Element element) {
+-        return getFieldName(element.getAttribute(ATTR_NAME));
+-    }
+-
+-    @Nullable
+-    private Resource getResource(Element element) {
+-        ResourceType type = getResourceType(element);
+-        if (type != null) {
+-            String name = getFieldName(element);
+-            return getResource(type, name);
+-        }
+-
+-        return null;
+-    }
+-
+-    @Nullable
+-    private Resource getResourceByJarPath(String path) {
+-        // Jars use forward slash paths, not File.separator
+-        if (path.startsWith("res/")) {
+-            int folderStart = 4; // "res/".length
+-            int folderEnd = path.indexOf('/', folderStart);
+-            if (folderEnd != -1) {
+-                String folderName = path.substring(folderStart, folderEnd);
+-                ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName);
+-                if (folderType != null) {
+-                    int nameStart = folderEnd + 1;
+-                    int nameEnd = path.indexOf('.', nameStart);
+-                    if (nameEnd != -1) {
+-                        String name = path.substring(nameStart, nameEnd);
+-                        List<ResourceType> types =
+-                                FolderTypeRelationship.getRelatedResourceTypes(folderType);
+-                        for (ResourceType type : types) {
+-                            if (type != ResourceType.ID) {
+-                                Resource resource = getResource(type, name);
+-                                if (resource != null) {
+-                                    return resource;
+-                                }
+-                            }
+-                        }
+-                    }
+-                }
+-            }
+-        }
+-
+-        return null;
+-    }
+-
+-    private static ResourceType getResourceType(Element element) {
+-        String tagName = element.getTagName();
+-        if (tagName.equals(TAG_ITEM)) {
+-            String typeName = element.getAttribute(ATTR_TYPE);
+-            if (!typeName.isEmpty()) {
+-                return ResourceType.getEnum(typeName);
+-            }
+-        } else if ("string-array".equals(tagName) || "integer-array".equals(tagName)) {
+-            return ResourceType.ARRAY;
+-        } else {
+-            return ResourceType.getEnum(tagName);
+-        }
+-        return null;
+-    }
+-
+-    private void findUnused() {
+-        List<Resource> roots = Lists.newArrayList();
+-
+-        for (Resource resource : mResources) {
+-            if (resource.reachable && resource.type != ResourceType.ID
+-                    && resource.type != ResourceType.ATTR) {
+-                roots.add(resource);
+-            }
+-        }
+-
+-        if (mDebug) {
+-            System.out.println("The root reachable resources are:\n" +
+-                    Joiner.on(",\n   ").join(roots));
+-        }
+-
+-        Map<Resource,Boolean> seen = new IdentityHashMap<Resource,Boolean>(mResources.size());
+-        for (Resource root : roots) {
+-            visit(root, seen);
+-        }
+-
+-        List<Resource> unused = Lists.newArrayListWithExpectedSize(mResources.size());
+-        for (Resource resource : mResources) {
+-            if (!resource.reachable && resource.isRelevantType()) {
+-                unused.add(resource);
+-            }
+-        }
+-
+-        mUnused = unused;
+-
+-        if (mDebug) {
+-            System.out.println(dumpResourceModel());
+-        }
+-    }
+-
+-    private static void visit(Resource root, Map<Resource, Boolean> seen) {
+-        if (seen.containsKey(root)) {
+-            return;
+-        }
+-        seen.put(root, Boolean.TRUE);
+-        root.reachable = true;
+-        if (root.references != null) {
+-            for (Resource referenced : root.references) {
+-                visit(referenced, seen);
+-            }
+-        }
+-    }
+-
+-    private void dumpReferences() {
+-        if (mDebug) {
+-            System.out.println("Resource Reference Graph:");
+-            for (Resource resource : mResources) {
+-                if (resource.references != null) {
+-                    System.out.println(resource + " => " + resource.references);
+-                }
+-            }
+-        }
+-    }
+-
+-    private void keepPossiblyReferencedResources() {
+-        if ((!mFoundGetIdentifier && !mFoundWebContent) || mStrings == null) {
+-            // No calls to android.content.res.Resources#getIdentifier; no need
+-            // to worry about string references to resources
+-            return;
+-        }
+-
+-        if (!mGuessKeep) {
+-            // User specifically asked for us not to guess resources to keep; they will
+-            // explicitly mark them as kept if necessary instead
+-            return;
+-        }
+-
+-        if (mDebug) {
+-            List<String> strings = new ArrayList<String>(mStrings);
+-            Collections.sort(strings);
+-            System.out.println("android.content.res.Resources#getIdentifier present: "
+-                    + mFoundGetIdentifier);
+-            System.out.println("Web content present: " + mFoundWebContent);
+-            System.out.println("Referenced Strings:");
+-            for (String s : strings) {
+-                s = s.trim().replace("\n", "\\n");
+-                if (s.length() > 40) {
+-                    s = s.substring(0, 37) + "...";
+-                } else if (s.isEmpty()) {
+-                    continue;
+-                }
+-                System.out.println("  " + s);
+-            }
+-        }
+-
+-        int shortest = Integer.MAX_VALUE;
+-        Set<String> names = Sets.newHashSetWithExpectedSize(50);
+-        for (Map<String, Resource> map : mTypeToName.values()) {
+-            for (String name : map.keySet()) {
+-                names.add(name);
+-                int length = name.length();
+-                if (length < shortest) {
+-                    shortest = length;
+-                }
+-            }
+-        }
+-
+-        for (String string : mStrings) {
+-            if (string.length() < shortest) {
+-                continue;
+-            }
+-
+-            // Check whether the string looks relevant
+-            // We consider four types of strings:
+-            //  (1) simple resource names, e.g. "foo" from @layout/foo
+-            //      These might be the parameter to a getIdentifier() call, or could
+-            //      be composed into a fully qualified resource name for the getIdentifier()
+-            //      method. We match these for *all* resource types.
+-            //  (2) Relative source names, e.g. layout/foo, from @layout/foo
+-            //      These might be composed into a fully qualified resource name for
+-            //      getIdentifier().
+-            //  (3) Fully qualified resource names of the form package:type/name.
+-            //  (4) If mFoundWebContent is true, look for android_res/ URL strings as well
+-
+-            if (mFoundWebContent) {
+-                Resource resource = getResourceFromFilePath(string);
+-                if (resource != null) {
+-                    markReachable(resource);
+-                    continue;
+-                } else {
+-                    int start = 0;
+-                    int slash = string.lastIndexOf('/');
+-                    if (slash != -1) {
+-                        start = slash + 1;
+-                    }
+-                    int dot = string.indexOf('.', start);
+-                    String name = string.substring(start, dot != -1 ? dot : string.length());
+-                    if (names.contains(name)) {
+-                        for (Map<String, Resource> map : mTypeToName.values()) {
+-                            resource = map.get(name);
+-                            if (mDebug && resource != null) {
+-                                System.out.println("Marking " + resource + " used because it "
+-                                        + "matches string pool constant " + string);
+-                            }
+-                            markReachable(resource);
+-                        }
+-                    }
+-                }
+-            }
+-
+-            // Look for normal getIdentifier resource URLs
+-            int n = string.length();
+-            boolean justName = true;
+-            boolean formatting = false;
+-            boolean haveSlash = false;
+-            for (int i = 0; i < n; i++) {
+-                char c = string.charAt(i);
+-                if (c == '/') {
+-                    haveSlash = true;
+-                    justName = false;
+-                } else if (c == '.' || c == ':' || c == '%') {
+-                    justName = false;
+-                    if (c == '%') {
+-                        formatting = true;
+-                    }
+-                } else if (!Character.isJavaIdentifierPart(c)) {
+-                    // This shouldn't happen; we've filtered out these strings in
+-                    // the {@link #referencedString} method
+-                    assert false : string;
+-                    break;
+-                }
+-            }
+-
+-            String name;
+-            if (justName) {
+-                // Check name (below)
+-                name = string;
+-
+-                // Check for a simple prefix match, e.g. as in
+-                // getResources().getIdentifier("ic_video_codec_" + codecName, "drawable", ...)
+-                for (Map<String, Resource> map : mTypeToName.values()) {
+-                    for (Resource resource : map.values()) {
+-                        if (resource.name.startsWith(name)) {
+-                            if (mDebug) {
+-                                System.out.println("Marking " + resource + " used because its "
+-                                        + "prefix matches string pool constant " + string);
+-                            }
+-                            markReachable(resource);
+-                        }
+-                    }
+-                }
+-            } else if (!haveSlash) {
+-                if (formatting) {
+-                    // Possibly a formatting string, e.g.
+-                    //   String name = String.format("my_prefix_%1d", index);
+-                    //   int res = getContext().getResources().getIdentifier(name, "drawable", ...)
+-
+-                    try {
+-                        Pattern pattern = Pattern.compile(convertFormatStringToRegexp(string));
+-                        for (Map<String, Resource> map : mTypeToName.values()) {
+-                            for (Resource resource : map.values()) {
+-                                if (pattern.matcher(resource.name).matches()) {
+-                                    if (mDebug) {
+-                                        System.out.println("Marking " + resource + " used because "
+-                                                + "it format-string matches string pool constant "
+-                                                + string);
+-                                    }
+-                                    markReachable(resource);
+-                                }
+-                            }
+-                        }
+-                    } catch (PatternSyntaxException ignored) {
+-                        // Might not have been a formatting string after all!
+-                    }
+-                }
+-
+-                // If we have more than just a symbol name, we expect to also see a slash
+-                //noinspection UnnecessaryContinue
+-                continue;
+-            } else {
+-                // Try to pick out the resource name pieces; if we can find the
+-                // resource type unambiguously; if not, just match on names
+-                int slash = string.indexOf('/');
+-                assert slash != -1; // checked with haveSlash above
+-                name = string.substring(slash + 1);
+-                if (name.isEmpty() || !names.contains(name)) {
+-                    continue;
+-                }
+-                // See if have a known specific resource type
+-                if (slash > 0) {
+-                    int colon = string.indexOf(':');
+-                    String typeName = string.substring(colon != -1 ? colon + 1 : 0, slash);
+-                    ResourceType type = ResourceType.getEnum(typeName);
+-                    if (type == null) {
+-                        continue;
+-                    }
+-                    Resource resource = getResource(type, name);
+-                    if (mDebug && resource != null) {
+-                        System.out.println("Marking " + resource + " used because it "
+-                                + "matches string pool constant " + string);
+-                    }
+-                    markReachable(resource);
+-                    continue;
+-                }
+-
+-                // fall through and check the name
+-            }
+-
+-            if (names.contains(name)) {
+-                for (Map<String, Resource> map : mTypeToName.values()) {
+-                    Resource resource = map.get(name);
+-                    if (mDebug && resource != null) {
+-                        System.out.println("Marking " + resource + " used because it "
+-                                + "matches string pool constant " + string);
+-                    }
+-                    markReachable(resource);
+-                }
+-            } else if (Character.isDigit(name.charAt(0))) {
+-                // Just a number? There are cases where it calls getIdentifier by
+-                // a String number; see for example SuggestionsAdapter in the support
+-                // library which reports supporting a string like "2130837524" and
+-                // "android.resource://com.android.alarmclock/2130837524".
+-                try {
+-                    int id = Integer.parseInt(name);
+-                    if (id != 0) {
+-                        markReachable(mValueToResource.get(id));
+-                    }
+-                } catch (NumberFormatException e) {
+-                    // pass
+-                }
+-            }
+-        }
+-    }
+-
+-    @VisibleForTesting
+-    static String convertFormatStringToRegexp(String formatString) {
+-        StringBuilder regexp = new StringBuilder();
+-        int from = 0;
+-        boolean hasEscapedLetters = false;
+-        Matcher matcher = StringFormatDetector.FORMAT.matcher(formatString);
+-        int length = formatString.length();
+-        while (matcher.find(from)) {
+-            int start = matcher.start();
+-            int end = matcher.end();
+-            if (start == 0 && end == length) {
+-                // Don't match if the entire string literal starts with % and ends with
+-                // the a formatting character, such as just "%d": this just matches absolutely
+-                // everything and is unlikely to be used in a resource lookup
+-                return NO_MATCH;
+-            }
+-            if (start > from) {
+-                hasEscapedLetters |= appendEscapedPattern(formatString, regexp, from, start);
+-            }
+-            // If the wildcard follows a previous wildcard, just skip it
+-            // (e.g. don't convert %s%s into .*.*; .* is enough.
+-            int regexLength = regexp.length();
+-            if (regexLength < 2
+-                    || regexp.charAt(regexLength - 1) != '*'
+-                    || regexp.charAt(regexLength - 2) != '.') {
+-                regexp.append(".*");
+-            }
+-            from = end;
+-        }
+-
+-        if (from < length) {
+-            hasEscapedLetters |= appendEscapedPattern(formatString, regexp, from, length);
+-        }
+-
+-        if (!hasEscapedLetters) {
+-            // If the regexp contains *only* formatting characters, e.g. "%.0f%d", or
+-            // if it contains only formatting characters and punctuation, e.g. "%s_%d",
+-            // don't treat this as a possible resource name pattern string: it is unlikely
+-            // to be intended for actual resource names, and has the side effect of matching
+-            // most names.
+-            return NO_MATCH;
+-        }
+-
+-        return regexp.toString();
+-    }
+-
+-    /**
+-     * Appends the characters in the range [from,to> from formatString as escaped
+-     * regexp characters into the given string builder. Returns true if there were
+-     * any letters in the appended text.
+-     */
+-    private static boolean appendEscapedPattern(@NonNull String formatString,
+-            @NonNull StringBuilder regexp, int from, int to) {
+-        regexp.append(Pattern.quote(formatString.substring(from, to)));
+-
+-        for (int i = from; i < to; i++) {
+-            if (Character.isLetter(formatString.charAt(i))) {
+-                return true;
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    private void recordResources(File resDir)
+-            throws IOException, SAXException, ParserConfigurationException {
+-        File[] resourceFolders = resDir.listFiles();
+-        if (resourceFolders != null) {
+-            for (File folder : resourceFolders) {
+-                ResourceFolderType folderType = ResourceFolderType.getFolderType(folder.getName());
+-                if (folderType != null) {
+-                    recordResources(folderType, folder);
+-                }
+-            }
+-        }
+-    }
+-
+-    private void recordResources(@NonNull ResourceFolderType folderType, File folder)
+-            throws ParserConfigurationException, SAXException, IOException {
+-        File[] files = folder.listFiles();
+-        FolderConfiguration config = FolderConfiguration.getConfigForFolder(folder.getName());
+-        boolean isDefaultFolder = false;
+-        if (config != null) {
+-            isDefaultFolder = true;
+-            for (int i = 0, n = FolderConfiguration.getQualifierCount(); i < n; i++) {
+-                ResourceQualifier qualifier = config.getQualifier(i);
+-                // Densities are special: even if they're present in just (say) drawable-hdpi
+-                // we'll match it on any other density
+-                if (qualifier != null && !(qualifier instanceof DensityQualifier)) {
+-                    isDefaultFolder = false;
+-                    break;
+-                }
+-            }
+-        }
+-
+-        if (files != null) {
+-            for (File file : files) {
+-                String path = file.getPath();
+-                boolean isXml = endsWithIgnoreCase(path, DOT_XML);
+-
+-                Resource from = null;
+-                // Record resource for the whole file
+-                if (folderType != ResourceFolderType.VALUES
+-                        && (isXml
+-                            || endsWith(path, DOT_PNG) //also true for endsWith(name, DOT_9PNG)
+-                            || endsWith(path, DOT_JPG)
+-                            || endsWith(path, DOT_GIF)
+-                            || endsWith(path, DOT_JPEG))) {
+-                    List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(
+-                            folderType);
+-                    ResourceType type = types.get(0);
+-                    assert type != ResourceType.ID : folderType;
+-                    String name = file.getName();
+-                    name = name.substring(0, name.indexOf('.'));
+-                    Resource resource = getResource(type, name);
+-                    if (resource != null) {
+-                        resource.addLocation(file);
+-                        if (isDefaultFolder) {
+-                            resource.hasDefault = true;
+-                        }
+-                        from = resource;
+-                    }
+-                }
+-
+-                if (isXml) {
+-                    // For value files, and drawables and colors etc also pull in resource
+-                    // references inside the file
+-                    recordXmlResourcesUsages(file, isDefaultFolder, from);
+-                    if (folderType == ResourceFolderType.XML) {
+-                        tokenizeUnknownText(Files.toString(file, UTF_8));
+-                    }
+-                } else if (folderType == ResourceFolderType.RAW) {
+-                    // Is this an HTML, CSS or JavaScript document bundled with the app?
+-                    // If so tokenize and look for resource references.
+-                    if (endsWithIgnoreCase(path, ".html") || endsWithIgnoreCase(path, ".htm")) {
+-                        tokenizeHtml(from, Files.toString(file, UTF_8));
+-                    } else if (endsWithIgnoreCase(path, ".css")) {
+-                        tokenizeCss(from, Files.toString(file, UTF_8));
+-                    } else if (endsWithIgnoreCase(path, ".js")) {
+-                        tokenizeJs(from, Files.toString(file, UTF_8));
+-                    } else if (file.isFile() && !LintUtils.isBitmapFile(file)) {
+-                        tokenizeUnknownBinary(file);
+-                    }
+-                }
+-            }
+-        }
+-    }
+-
+-    private void recordMapping(@Nullable File mapping) throws IOException {
+-        if (mapping == null || !mapping.exists()) {
+-            return;
+-        }
+-        final String ARROW = " -> ";
+-        final String RESOURCE = ".R$";
+-        for (String line : Files.readLines(mapping, UTF_8)) {
+-            if (line.startsWith(" ") || line.startsWith("\t")) {
+-                continue;
+-            }
+-            int index = line.indexOf(RESOURCE);
+-            if (index == -1) {
+-                continue;
+-            }
+-            int arrow = line.indexOf(ARROW, index + 3);
+-            if (arrow == -1) {
+-                continue;
+-            }
+-            String typeName = line.substring(index + RESOURCE.length(), arrow);
+-            ResourceType type = ResourceType.getEnum(typeName);
+-            if (type == null) {
+-                continue;
+-            }
+-            int end = line.indexOf(':', arrow + ARROW.length());
+-            if (end == -1) {
+-                end = line.length();
+-            }
+-            String target = line.substring(arrow + ARROW.length(), end).trim();
+-            String ownerName = target.replace('.', '/');
+-            mResourceClassOwners.put(ownerName, type);
+-        }
+-    }
+-
+-    private void recordManifestUsages(File manifest)
+-            throws IOException, ParserConfigurationException, SAXException {
+-        String xml = Files.toString(manifest, UTF_8);
+-        Document document = XmlUtils.parseDocument(xml, true);
+-        recordManifestUsages(document.getDocumentElement());
+-    }
+-
+-    private void recordXmlResourcesUsages(@NonNull File file, boolean isDefaultFolder,
+-            @Nullable Resource from)
+-            throws IOException, ParserConfigurationException, SAXException {
+-        String xml = Files.toString(file, UTF_8);
+-        Document document = XmlUtils.parseDocument(xml, true);
+-        recordResourceReferences(file, isDefaultFolder, document.getDocumentElement(), from);
+-    }
+-
+-    private void tokenizeHtml(@Nullable Resource from, @NonNull String  html) {
+-        // Look for
+-        //    (1) URLs of the form /android_res/drawable/foo.ext
+-        //        which we will use to keep R.drawable.foo
+-        // and
+-        //    (2) Filenames. If the web content is loaded with something like
+-        //        WebView.loadDataWithBaseURL("file:///android_res/drawable/", ...)
+-        //        this is similar to Resources#getIdentifier handling where all
+-        //        *potentially* aliased filenames are kept to play it safe.
+-
+-        // Simple HTML tokenizer
+-        int length = html.length();
+-        final int STATE_TEXT = 1;
+-        final int STATE_SLASH = 2;
+-        final int STATE_ATTRIBUTE_NAME = 3;
+-        final int STATE_BEFORE_TAG = 4;
+-        final int STATE_IN_TAG = 5;
+-        final int STATE_BEFORE_ATTRIBUTE = 6;
+-        final int STATE_ATTRIBUTE_BEFORE_EQUALS = 7;
+-        final int STATE_ATTRIBUTE_AFTER_EQUALS = 8;
+-        final int STATE_ATTRIBUTE_VALUE_NONE = 9;
+-        final int STATE_ATTRIBUTE_VALUE_SINGLE = 10;
+-        final int STATE_ATTRIBUTE_VALUE_DOUBLE = 11;
+-        final int STATE_CLOSE_TAG = 12;
+-
+-        int state = STATE_TEXT;
+-        int offset = 0;
+-        int valueStart = 0;
+-        int tagStart = 0;
+-        String tag = null;
+-        String attribute = null;
+-        int attributeStart = 0;
+-        int prev = -1;
+-        while (offset < length) {
+-            if (offset == prev) {
+-                // Purely here to prevent potential bugs in the state machine from looping
+-                // infinitely
+-                offset++;
+-            }
+-            prev = offset;
+-
+-
+-            char c = html.charAt(offset);
+-
+-            // MAke sure I handle doctypes properly.
+-            // Make sure I handle cdata properly.
+-            // Oh and what about <style> tags? tokenize everything inside as CSS!
+-            // ANd <script> tag content as js!
+-            switch (state) {
+-                case STATE_TEXT: {
+-                    if (c == '<') {
+-                        state = STATE_SLASH;
+-                        offset++;
+-                        continue;
+-                    }
+-
+-                    // Other text is just ignored
+-                    offset++;
+-                    break;
+-                }
+-
+-                case STATE_SLASH: {
+-                    if (c == '!') {
+-                        if (html.startsWith("!--", offset)) {
+-                            // Comment
+-                            int end = html.indexOf("-->", offset + 3);
+-                            if (end == -1) {
+-                                offset = length;
+-                                break;
+-                            }
+-                            offset = end + 3;
+-                            continue;
+-                        } else if (html.startsWith("![CDATA[", offset)) {
+-                            // Skip CDATA text content; HTML text is irrelevant to this tokenizer
+-                            // anyway
+-                            int end = html.indexOf("]]>", offset + 8);
+-                            if (end == -1) {
+-                                offset = length;
+-                                break;
+-                            }
+-                            offset = end + 3;
+-                            continue;
+-                        }
+-                    } else if (c == '/') {
+-                        state = STATE_CLOSE_TAG;
+-                        offset++;
+-                        continue;
+-                    } else if (c == '?') {
+-                        // XML Prologue
+-                        int end = html.indexOf('>', offset + 2);
+-                        if (end == -1) {
+-                            offset = length;
+-                            break;
+-                        }
+-                        offset = end + 1;
+-                        continue;
+-                    }
+-                    state = STATE_IN_TAG;
+-                    tagStart = offset;
+-                    break;
+-                }
+-
+-                case STATE_CLOSE_TAG: {
+-                    if (c == '>') {
+-                        state = STATE_TEXT;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-
+-                case STATE_BEFORE_TAG: {
+-                    if (!Character.isWhitespace(c)) {
+-                        state = STATE_IN_TAG;
+-                        tagStart = offset;
+-                    }
+-                    // (For an end tag we'll include / in the tag name here)
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_IN_TAG: {
+-                    if (Character.isWhitespace(c)) {
+-                        state = STATE_BEFORE_ATTRIBUTE;
+-                        tag = html.substring(tagStart, offset).trim();
+-                    } else if (c == '>') {
+-                        tag = html.substring(tagStart, offset).trim();
+-                        endHtmlTag(from, html, offset, tag);
+-                        state = STATE_TEXT;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_BEFORE_ATTRIBUTE: {
+-                    if (c == '>') {
+-                        endHtmlTag(from, html, offset, tag);
+-                        state = STATE_TEXT;
+-                    } else //noinspection StatementWithEmptyBody
+-                        if (c == '/') {
+-                        // we expect an '>' next to close the tag
+-                    } else if (!Character.isWhitespace(c)) {
+-                        state = STATE_ATTRIBUTE_NAME;
+-                        attributeStart = offset;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_ATTRIBUTE_NAME: {
+-                    if (c == '>') {
+-                        endHtmlTag(from, html, offset, tag);
+-                        state = STATE_TEXT;
+-                    } else if (c == '=') {
+-                        attribute = html.substring(attributeStart, offset);
+-                        state = STATE_ATTRIBUTE_AFTER_EQUALS;
+-                    } else if (Character.isWhitespace(c)) {
+-                        attribute = html.substring(attributeStart, offset);
+-                        state = STATE_ATTRIBUTE_BEFORE_EQUALS;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_ATTRIBUTE_BEFORE_EQUALS: {
+-                    if (c == '=') {
+-                        state = STATE_ATTRIBUTE_AFTER_EQUALS;
+-                    } else if (c == '>') {
+-                        endHtmlTag(from, html, offset, tag);
+-                        state = STATE_TEXT;
+-                    } else if (!Character.isWhitespace(c)) {
+-                        // Attribute value not specified (used for some boolean attributes)
+-                        state = STATE_ATTRIBUTE_NAME;
+-                        attributeStart = offset;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-
+-                case STATE_ATTRIBUTE_AFTER_EQUALS: {
+-                    if (c == '\'') {
+-                        // a='b'
+-                        state = STATE_ATTRIBUTE_VALUE_SINGLE;
+-                        valueStart = offset + 1;
+-                    } else if (c == '"') {
+-                        // a="b"
+-                        state = STATE_ATTRIBUTE_VALUE_DOUBLE;
+-                        valueStart = offset + 1;
+-                    } else if (!Character.isWhitespace(c)) {
+-                        // a=b
+-                        state = STATE_ATTRIBUTE_VALUE_NONE;
+-                        valueStart = offset + 1;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-
+-                case STATE_ATTRIBUTE_VALUE_SINGLE: {
+-                    if (c == '\'') {
+-                        state = STATE_BEFORE_ATTRIBUTE;
+-                        recordHtmlAttributeValue(from, tag, attribute,
+-                                html.substring(valueStart, offset));
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_ATTRIBUTE_VALUE_DOUBLE: {
+-                    if (c == '"') {
+-                        state = STATE_BEFORE_ATTRIBUTE;
+-                        recordHtmlAttributeValue(from, tag, attribute,
+-                                html.substring(valueStart, offset));
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_ATTRIBUTE_VALUE_NONE: {
+-                    if (c == '>') {
+-                        recordHtmlAttributeValue(from, tag, attribute,
+-                                html.substring(valueStart, offset));
+-                        endHtmlTag(from, html, offset, tag);
+-                        state = STATE_TEXT;
+-                    } else if (Character.isWhitespace(c)) {
+-                        state = STATE_BEFORE_ATTRIBUTE;
+-                        recordHtmlAttributeValue(from, tag, attribute,
+-                                html.substring(valueStart, offset));
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                default:
+-                    assert false : state;
+-            }
+-        }
+-    }
+-
+-    private void endHtmlTag(@Nullable Resource from, @NonNull String html, int offset,
+-            @Nullable String tag) {
+-        if ("script".equals(tag)) {
+-            int end = html.indexOf("</script>", offset + 1);
+-            if (end != -1) {
+-                // Attempt to tokenize the text as JavaScript
+-                String js = html.substring(offset + 1, end);
+-                tokenizeJs(from, js);
+-            }
+-        } else if ("style".equals(tag)) {
+-            int end = html.indexOf("</style>", offset + 1);
+-            if (end != -1) {
+-                // Attempt to tokenize the text as CSS
+-                String css = html.substring(offset + 1, end);
+-                tokenizeCss(from, css);
+-            }
+-        }
+-    }
+-
+-    private void tokenizeJs(@Nullable Resource from, @NonNull String js) {
+-        // Simple JavaScript tokenizer: only looks for literal strings,
+-        // and records those as string references
+-        int length = js.length();
+-        final int STATE_INIT = 1;
+-        final int STATE_SLASH = 2;
+-        final int STATE_STRING_DOUBLE = 3;
+-        final int STATE_STRING_DOUBLE_QUOTED = 4;
+-        final int STATE_STRING_SINGLE = 5;
+-        final int STATE_STRING_SINGLE_QUOTED = 6;
+-
+-        int state = STATE_INIT;
+-        int offset = 0;
+-        int stringStart = 0;
+-        int prev = -1;
+-        while (offset < length) {
+-            if (offset == prev) {
+-                // Purely here to prevent potential bugs in the state machine from looping
+-                // infinitely
+-                offset++;
+-            }
+-            prev = offset;
+-
+-            char c = js.charAt(offset);
+-            switch (state) {
+-                case STATE_INIT: {
+-                    if (c == '/') {
+-                        state = STATE_SLASH;
+-                    } else if (c == '"') {
+-                        stringStart = offset + 1;
+-                        state = STATE_STRING_DOUBLE;
+-                    } else if (c == '\'') {
+-                        stringStart = offset + 1;
+-                        state = STATE_STRING_SINGLE;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_SLASH: {
+-                    if (c == '*') {
+-                        // Comment block
+-                        state = STATE_INIT;
+-                        int end = js.indexOf("*/", offset + 1);
+-                        if (end == -1) {
+-                            offset = length; // unterminated
+-                            break;
+-                        }
+-                        offset = end + 2;
+-                        continue;
+-                    } else if (c == '/') {
+-                        // Line comment
+-                        state = STATE_INIT;
+-                        int end = js.indexOf('\n', offset + 1);
+-                        if (end == -1) {
+-                            offset = length;
+-                            break;
+-                        }
+-                        offset = end + 1;
+-                        continue;
+-                    } else {
+-                        // division - just continue
+-                        state = STATE_INIT;
+-                        offset++;
+-                        break;
+-                    }
+-                }
+-                case STATE_STRING_DOUBLE: {
+-                    if (c == '"') {
+-                        recordJsString(js.substring(stringStart, offset));
+-                        state = STATE_INIT;
+-                    } else if (c == '\\') {
+-                        state = STATE_STRING_DOUBLE_QUOTED;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_STRING_DOUBLE_QUOTED: {
+-                    state = STATE_STRING_DOUBLE;
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_STRING_SINGLE: {
+-                    if (c == '\'') {
+-                        recordJsString(js.substring(stringStart, offset));
+-                        state = STATE_INIT;
+-                    } else if (c == '\\') {
+-                        state = STATE_STRING_SINGLE_QUOTED;
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_STRING_SINGLE_QUOTED: {
+-                    state = STATE_STRING_SINGLE;
+-                    offset++;
+-                    break;
+-                }
+-                default:
+-                    assert false : state;
+-            }
+-        }
+-    }
+-
+-    private void tokenizeCss(@Nullable Resource from, @NonNull String  css) {
+-        // Simple CSS tokenizer: Only looks for URL references, and records those
+-        // filenames. Skips everything else (unrelated to images).
+-        int length = css.length();
+-        final int STATE_INIT = 1;
+-        final int STATE_SLASH = 2;
+-        int state = STATE_INIT;
+-        int offset = 0;
+-        int prev = -1;
+-        while (offset < length) {
+-            if (offset == prev) {
+-                // Purely here to prevent potential bugs in the state machine from looping
+-                // infinitely
+-                offset++;
+-            }
+-            prev = offset;
+-
+-            char c = css.charAt(offset);
+-            switch (state) {
+-                case STATE_INIT: {
+-                    if (c == '/') {
+-                        state = STATE_SLASH;
+-                    } else if (c == 'u' && css.startsWith("url(", offset) && offset > 0) {
+-                        char prevChar = css.charAt(offset-1);
+-                        if (Character.isWhitespace(prevChar) || prevChar == ':') {
+-                            int end = css.indexOf(')', offset);
+-                            offset += 4; // skip url(
+-                            while (offset < length && Character.isWhitespace(css.charAt(offset))) {
+-                                offset++;
+-                            }
+-                            if (end != -1 && end > offset + 1) {
+-                                while (end > offset
+-                                        && Character.isWhitespace(css.charAt(end - 1))) {
+-                                    end--;
+-                                }
+-                                if ((css.charAt(offset) == '"'
+-                                        && css.charAt(end - 1) == '"')
+-                                        || (css.charAt(offset) == '\''
+-                                        && css.charAt(end - 1) == '\'')) {
+-                                    // Strip " or '
+-                                    offset++;
+-                                    end--;
+-                                }
+-                                recordCssUrl(from, css.substring(offset, end).trim());
+-                            }
+-                            offset = end + 1;
+-                            continue;
+-                        }
+-
+-                    }
+-                    offset++;
+-                    break;
+-                }
+-                case STATE_SLASH: {
+-                    if (c == '*') {
+-                        // CSS comment? Skip the whole block rather than staying within the
+-                        // character tokenizer.
+-                        int end = css.indexOf("*/", offset + 1);
+-                        if (end == -1) {
+-                            offset = length;
+-                            break;
+-                        }
+-                        offset = end + 2;
+-                        continue;
+-                    }
+-                    state = STATE_INIT;
+-                    offset++;
+-                    break;
+-                }
+-                default:
+-                    assert false : state;
+-            }
+-        }
+-    }
+-
+-    private static byte[] sAndroidResBytes;
+-
+-    /** Look through binary/unknown files looking for resource URLs */
+-    private void tokenizeUnknownBinary(@NonNull File file) {
+-        try {
+-            if (sAndroidResBytes == null) {
+-                sAndroidResBytes = ANDROID_RES.getBytes(SdkConstants.UTF_8);
+-            }
+-            byte[] bytes = Files.toByteArray(file);
+-            int index = 0;
+-            while (index != -1) {
+-                index = indexOf(bytes, sAndroidResBytes, index);
+-                if (index != -1) {
+-                    index += sAndroidResBytes.length;
+-
+-                    // Find the end of the URL
+-                    int begin = index;
+-                    int end = begin;
+-                    for (; end < bytes.length; end++) {
+-                        byte c = bytes[end];
+-                        if (c != '/' && !Character.isJavaIdentifierPart((char)c)) {
+-                            // android_res/raw/my_drawable.png => @raw/my_drawable
+-                            String url = "@" + new String(bytes, begin, end - begin, UTF_8);
+-                            markReachable(getResourceFromUrl(url));
+-                            break;
+-                        }
+-                    }
+-                }
+-            }
+-        } catch (IOException e) {
+-            // Ignore
+-        }
+-    }
+-
+-    /**
+-     * Returns the index of the given target array in the first array, looking from the given
+-     * index
+-     */
+-    private static int indexOf(byte[] array, byte[] target, int fromIndex) {
+-        outer:
+-        for (int i = fromIndex; i < array.length - target.length + 1; i++) {
+-            for (int j = 0; j < target.length; j++) {
+-                if (array[i + j] != target[j]) {
+-                    continue outer;
+-                }
+-            }
+-            return i;
+-        }
+-        return -1;
+-    }
+-
+-    /** Look through text files of unknown structure looking for resource URLs */
+-    private void tokenizeUnknownText(@NonNull String text) {
+-        int index = 0;
+-        while (index != -1) {
+-            index = text.indexOf(ANDROID_RES, index);
+-            if (index != -1) {
+-                index += ANDROID_RES.length();
+-
+-                // Find the end of the URL
+-                int begin = index;
+-                int end = begin;
+-                int length = text.length();
+-                for (; end < length; end++) {
+-                    char c = text.charAt(end);
+-                    if (c != '/' && !Character.isJavaIdentifierPart(c)) {
+-                        // android_res/raw/my_drawable.png => @raw/my_drawable
+-                        markReachable(getResourceFromUrl("@" + text.substring(begin, end)));
+-                        break;
+-                    }
+-                }
+-            }
+-        }
+-    }
+-
+-    private void recordCssUrl(@Nullable Resource from, @NonNull String value) {
+-        if (!referencedUrl(from, value)) {
+-            referencedString(value);
+-            mFoundWebContent = true;
+-        }
+-    }
+-
+-    /**
+-     * See if the given URL is a URL that we can resolve to a specific resource; if so,
+-     * record it and return true, otherwise returns false.
+-     */
+-    private boolean referencedUrl(@Nullable Resource from, @NonNull String url) {
+-        Resource resource = getResourceFromFilePath(url);
+-        if (resource != null) {
+-            if (from != null) {
+-                from.addReference(resource);
+-            } else {
+-                // We don't have an inclusion context, so just assume this resource is reachable
+-                markReachable(resource);
+-            }
+-            return true;
+-        }
+-
+-        return false;
+-    }
+-
+-    private void recordHtmlAttributeValue(@Nullable Resource from, @Nullable String tagName,
+-            @Nullable String attribute, @NonNull String value) {
+-        if ("href".equals(attribute) || "src".equals(attribute)) {
+-            // In general we'd need to unescape the HTML here (e.g. remove entities) but
+-            // those wouldn't be valid characters in the resource name anyway
+-            if (!referencedUrl(from, value)) {
+-                referencedString(value);
+-                mFoundWebContent = true;
+-            }
+-
+-            // If this document includes another, record the reachability of that script/resource
+-            if (from != null) {
+-                from.addReference(getResourceFromFilePath(attribute));
+-            }
+-        }
+-    }
+-
+-    private void recordJsString(@NonNull String string) {
+-        referencedString(string);
+-    }
+-
+-    @Nullable
+-    private Resource getResource(@NonNull ResourceType type, @NonNull String name) {
+-        Map<String, Resource> nameMap = mTypeToName.get(type);
+-        if (nameMap != null) {
+-            return nameMap.get(getFieldName(name));
+-        }
+-        return null;
+-    }
+-
+-    @Nullable
+-    private Resource getResourceFromUrl(@NonNull String possibleUrlReference) {
+-        ResourceUrl url = ResourceUrl.parse(possibleUrlReference);
+-        if (url != null && !url.framework) {
+-            return getResource(url.type, url.name);
+-        }
+-
+-        return null;
+-    }
+-
+-    @Nullable
+-    private Resource getResourceFromFilePath(@NonNull String url) {
+-        int nameSlash = url.lastIndexOf('/');
+-        if (nameSlash == -1) {
+-            return null;
+-        }
+-
+-        // Look for
+-        //   (1) a full resource URL: /android_res/type/name.ext
+-        //   (2) a partial URL that uniquely identifies a given resource: drawable/name.ext
+-        // e.g. file:///android_res/drawable/bar.png
+-        int androidRes = url.indexOf(ANDROID_RES);
+-        if (androidRes != -1) {
+-            androidRes += ANDROID_RES.length();
+-            int slash = url.indexOf('/', androidRes);
+-            if (slash != -1) {
+-                String folderName = url.substring(androidRes, slash);
+-                ResourceFolderType folderType = ResourceFolderType.getFolderType(folderName);
+-                if (folderType != null) {
+-                    List<ResourceType> types = FolderTypeRelationship.getRelatedResourceTypes(
+-                            folderType);
+-                    if (!types.isEmpty()) {
+-                        ResourceType type = types.get(0);
+-                        int nameBegin = slash + 1;
+-                        int dot = url.indexOf('.', nameBegin);
+-                        String name = url.substring(nameBegin, dot != -1 ? dot : url.length());
+-                        return getResource(type, name);
+-                    }
+-                }
+-            }
+-        }
+-
+-        // Some other relative path. Just look from the end:
+-        int typeSlash = url.lastIndexOf('/', nameSlash - 1);
+-        ResourceType type = ResourceType.getEnum(url.substring(typeSlash + 1, nameSlash));
+-        if (type != null) {
+-            int nameBegin = nameSlash + 1;
+-            int dot = url.indexOf('.', nameBegin);
+-            String name = url.substring(nameBegin, dot != -1 ? dot : url.length());
+-            return getResource(type, name);
+-        }
+-
+-        return null;
+-    }
+-
+-    private void recordManifestUsages(Node node) {
+-        short nodeType = node.getNodeType();
+-        if (nodeType == Node.ELEMENT_NODE) {
+-            Element element = (Element) node;
+-            NamedNodeMap attributes = element.getAttributes();
+-            for (int i = 0, n = attributes.getLength(); i < n; i++) {
+-                Attr attr = (Attr) attributes.item(i);
+-                markReachable(getResourceFromUrl(attr.getValue()));
+-            }
+-        } else if (nodeType == Node.TEXT_NODE) {
+-            // Does this apply to any manifests??
+-            String text = node.getNodeValue().trim();
+-            markReachable(getResourceFromUrl(text));
+-        }
+-
+-        NodeList children = node.getChildNodes();
+-        for (int i = 0, n = children.getLength(); i < n; i++) {
+-            Node child = children.item(i);
+-            recordManifestUsages(child);
+-        }
+-    }
+-
+-
+-    private void recordResourceReferences(@NonNull File file, boolean isDefaultFolder,
+-            @NonNull Node node, @Nullable Resource from) {
+-        short nodeType = node.getNodeType();
+-        if (nodeType == Node.ELEMENT_NODE) {
+-            Element element = (Element) node;
+-            if (from != null) {
+-                NamedNodeMap attributes = element.getAttributes();
+-                for (int i = 0, n = attributes.getLength(); i < n; i++) {
+-                    Attr attr = (Attr) attributes.item(i);
+-
+-                    // Ignore tools: namespace attributes, unless it's
+-                    // a keep attribute
+-                    if (TOOLS_URI.equals(attr.getNamespaceURI())) {
+-                        handleToolsAttribute(attr);
+-                        // Skip all other tools: attributes
+-                        continue;
+-                    }
+-
+-                    Resource resource = getResourceFromUrl(attr.getValue());
+-                    if (resource != null) {
+-                        from.addReference(resource);
+-                    }
+-                }
+-
+-                // Android Wear. We *could* limit ourselves to only doing this in files
+-                // referenced from a manifest meta-data element, e.g.
+-                // <meta-data android:name="com.google.android.wearable.beta.app"
+-                //    android:resource="@xml/wearable_app_desc"/>
+-                // but given that that property has "beta" in the name, it seems likely
+-                // to change and therefore hardcoding it for that key risks breakage
+-                // in the future.
+-                if ("rawPathResId".equals(element.getTagName())) {
+-                    StringBuilder sb = new StringBuilder();
+-                    NodeList children = node.getChildNodes();
+-                    for (int i = 0, n = children.getLength(); i < n; i++) {
+-                        Node child = children.item(i);
+-                        if (child.getNodeType() == Element.TEXT_NODE
+-                                || child.getNodeType() == Element.CDATA_SECTION_NODE) {
+-                            sb.append(child.getNodeValue());
+-                        }
+-                    }
+-                    if (sb.length() > 0) {
+-                        Resource resource = getResource(ResourceType.RAW, sb.toString().trim());
+-                        from.addReference(resource);
+-                    }
+-                }
+-            } else {
+-                // Look for keep attributes everywhere else since they don't require a source
+-                handleToolsAttribute(element.getAttributeNodeNS(TOOLS_URI, ATTR_KEEP));
+-                handleToolsAttribute(element.getAttributeNodeNS(TOOLS_URI, ATTR_DISCARD));
+-                handleToolsAttribute(element.getAttributeNodeNS(TOOLS_URI, ATTR_SHRINK_MODE));
+-            }
+-
+-            Resource definition = getResource(element);
+-            if (definition != null) {
+-                from = definition;
+-                definition.addLocation(file);
+-                if (isDefaultFolder) {
+-                    definition.hasDefault = true;
+-                }
+-            }
+-
+-            String tagName = element.getTagName();
+-            if (TAG_STYLE.equals(tagName)) {
+-                if (element.hasAttribute(ATTR_PARENT)) {
+-                    String parent = element.getAttribute(ATTR_PARENT);
+-                    if (!parent.isEmpty() && !parent.startsWith(ANDROID_STYLE_RESOURCE_PREFIX) &&
+-                            !parent.startsWith(PREFIX_ANDROID)) {
+-                        String parentStyle = parent;
+-                        if (!parentStyle.startsWith(STYLE_RESOURCE_PREFIX)) {
+-                            parentStyle = STYLE_RESOURCE_PREFIX + parentStyle;
+-                        }
+-                        Resource ps = getResourceFromUrl(getFieldName(parentStyle));
+-                        if (ps != null && definition != null) {
+-                            definition.addReference(ps);
+-                        }
+-                    }
+-                } else {
+-                    // Implicit parent styles by name
+-                    String name = getFieldName(element);
+-                    while (true) {
+-                        int index = name.lastIndexOf('_');
+-                        if (index != -1) {
+-                            name = name.substring(0, index);
+-                            Resource ps = getResourceFromUrl(
+-                                    STYLE_RESOURCE_PREFIX + getFieldName(name));
+-                            if (ps != null && definition != null) {
+-                                definition.addReference(ps);
+-                            }
+-                        } else {
+-                            break;
+-                        }
+-                    }
+-                }
+-            }
+-
+-            if (TAG_ITEM.equals(tagName)) {
+-                // In style? If so the name: attribute can be a reference
+-                if (element.getParentNode() != null
+-                        && element.getParentNode().getNodeName().equals(TAG_STYLE)) {
+-                    String name = element.getAttributeNS(ANDROID_URI, ATTR_NAME);
+-                    if (!name.isEmpty() && !name.startsWith("android:")) {
+-                        Resource resource = getResource(ResourceType.ATTR, name);
+-                        if (definition == null) {
+-                            Element style = (Element) element.getParentNode();
+-                            definition = getResource(style);
+-                            if (definition != null) {
+-                                from = definition;
+-                                definition.addReference(resource);
+-                            }
+-                        }
+-                    }
+-                }
+-            }
+-        } else if (nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) {
+-            String text = node.getNodeValue().trim();
+-            Resource textResource = getResourceFromUrl(getFieldName(text));
+-            if (textResource != null && from != null) {
+-                from.addReference(textResource);
+-            }
+-        }
+-
+-        NodeList children = node.getChildNodes();
+-        for (int i = 0, n = children.getLength(); i < n; i++) {
+-            Node child = children.item(i);
+-            recordResourceReferences(file, isDefaultFolder, child, from);
+-        }
+-    }
+-
+-    private void handleToolsAttribute(@Nullable Attr attr) {
+-        if (attr == null) {
+-            return;
+-        }
+-        String localName = attr.getLocalName();
+-        String value = attr.getValue();
+-        if (ATTR_KEEP.equals(localName)) {
+-            handleKeepAttribute(value);
+-        } else if (ATTR_DISCARD.equals(localName)) {
+-            handleRemoveAttribute(value);
+-        } else if (ATTR_SHRINK_MODE.equals(localName)) {
+-            if (VALUE_STRICT.equals(value)) {
+-                mGuessKeep = false;
+-            } else if (VALUE_SAFE.equals(value)) {
+-                mGuessKeep = true;
+-            } else if (mDebug) {
+-                System.out.println("Ignoring unknown " + ATTR_SHRINK_MODE + " " + value);
+-            }
+-            if (mDebug) {
+-                System.out.println("Setting shrink mode to " + value);
+-            }
+-        }
+-    }
+-
+-    public static String getFieldName(@NonNull String styleName) {
+-        return styleName.replace('.', '_').replace('-', '_').replace(':', '_');
+-    }
+-
+-    /**
+-     * Marks the given resource (if non-null) as reachable, and returns true if
+-     * this is the first time the resource is marked reachable
+-     */
+-    private static boolean markReachable(@Nullable Resource resource) {
+-        if (resource != null) {
+-            boolean wasReachable = resource.reachable;
+-            resource.reachable = true;
+-            return !wasReachable;
+-        }
+-
+-        return false;
+-    }
+-
+-    private static void markUnreachable(@Nullable Resource resource) {
+-        if (resource != null) {
+-            resource.reachable = false;
+-        }
+-    }
+-
+-    /**
+-     * Called for a tools:keep attribute containing a resource URL where that resource name
+-     * is not referencing a known resource
+-     *
+-     * @param value The keep value
+-     */
+-    private void handleKeepAttribute(@NonNull String value) {
+-        // Handle comma separated lists of URLs and globs
+-        if (value.indexOf(',') != -1) {
+-            for (String portion : Splitter.on(',').omitEmptyStrings().trimResults().split(value)) {
+-                handleKeepAttribute(portion);
+-            }
+-            return;
+-        }
+-
+-        ResourceUrl url = ResourceUrl.parse(value);
+-        if (url == null || url.framework) {
+-            return;
+-        }
+-
+-        Resource resource = getResource(url.type, url.name);
+-        if (resource != null) {
+-            if (mDebug) {
+-                System.out.println("Marking " + resource + " used because it "
+-                        + "matches keep attribute " + value);
+-            }
+-            markReachable(resource);
+-        } else if (url.name.contains("*") || url.name.contains("?")) {
+-            // Look for globbing patterns
+-            String regexp = DefaultConfiguration.globToRegexp(getFieldName(url.name));
+-            try {
+-                Pattern pattern = Pattern.compile(regexp);
+-                Map<String, Resource> nameMap = mTypeToName.get(url.type);
+-                if (nameMap != null) {
+-                    for (Resource r : nameMap.values()) {
+-                        if (pattern.matcher(r.name).matches()) {
+-                            if (mDebug) {
+-                                System.out.println("Marking " + r + " used because it "
+-                                        + "matches keep globbing pattern " + url.name);
+-                            }
+-
+-                            markReachable(r);
+-                        }
+-                    }
+-                }
+-            } catch (PatternSyntaxException ignored) {
+-                if (mDebug) {
+-                    System.out.println("Could not compute keep globbing pattern for " +
+-                            url.name + ": tried regexp " + regexp + "(" + ignored + ")");
+-                }
+-            }
+-        }
+-    }
+-
+-    private void handleRemoveAttribute(@NonNull String value) {
+-        // Handle comma separated lists of URLs and globs
+-        if (value.indexOf(',') != -1) {
+-            for (String portion : Splitter.on(',').omitEmptyStrings().trimResults().split(value)) {
+-                handleRemoveAttribute(portion);
+-            }
+-            return;
+-        }
+-
+-        ResourceUrl url = ResourceUrl.parse(value);
+-        if (url == null || url.framework) {
+-            return;
+-        }
+-
+-        Resource resource = getResource(url.type, url.name);
+-        if (resource != null) {
+-            if (mDebug) {
+-                System.out.println("Marking " + resource + " used because it "
+-                        + "matches remove attribute " + value);
+-            }
+-            markUnreachable(resource);
+-        } else if (url.name.contains("*") || url.name.contains("?")) {
+-            // Look for globbing patterns
+-            String regexp = DefaultConfiguration.globToRegexp(getFieldName(url.name));
+-            try {
+-                Pattern pattern = Pattern.compile(regexp);
+-                Map<String, Resource> nameMap = mTypeToName.get(url.type);
+-                if (nameMap != null) {
+-                    for (Resource r : nameMap.values()) {
+-                        if (pattern.matcher(r.name).matches()) {
+-                            if (mDebug) {
+-                                System.out.println("Marking " + r + " used because it "
+-                                        + "matches remove globbing pattern " + url.name);
+-                            }
+-
+-                            markUnreachable(r);
+-                        }
+-                    }
+-                }
+-            } catch (PatternSyntaxException ignored) {
+-                if (mDebug) {
+-                    System.out.println("Could not compute remove globbing pattern for " +
+-                            url.name + ": tried regexp " + regexp + "(" + ignored + ")");
+-                }
+-            }
+-        }
+-    }
+-
+-    private Set<String> mStrings;
+-    private boolean mFoundGetIdentifier;
+-    private boolean mFoundWebContent;
+-
+-    private void referencedString(@NonNull String string) {
+-        // See if the string is at all eligible; ignore strings that aren't
+-        // identifiers (has java identifier chars and nothing but .:/), or are empty or too long
+-        // We also allow "%", used for formatting strings.
+-        if (string.isEmpty() || string.length() > 80) {
+-            return;
+-        }
+-        boolean haveIdentifierChar = false;
+-        for (int i = 0, n = string.length(); i < n; i++) {
+-            char c = string.charAt(i);
+-            boolean identifierChar = Character.isJavaIdentifierPart(c);
+-            if (!identifierChar && c != '.' && c != ':' && c != '/' && c != '%') {
+-                // .:/ are for the fully qualified resource names, or for resource URLs or
+-                // relative file names
+-                return;
+-            } else if (identifierChar) {
+-                haveIdentifierChar = true;
+-            }
+-        }
+-        if (!haveIdentifierChar) {
+-            return;
+-        }
+-
+-        if (mStrings == null) {
+-            mStrings = Sets.newHashSetWithExpectedSize(300);
+-        }
+-        mStrings.add(string);
+-
+-        if (!mFoundWebContent && string.contains(ANDROID_RES)) {
+-            mFoundWebContent = true;
+-        }
+-    }
+-
+-    private void recordUsages(File jarFile) throws IOException {
+-        if (!jarFile.exists()) {
+-            return;
+-        }
+-        ZipInputStream zis = null;
+-        try {
+-            FileInputStream fis = new FileInputStream(jarFile);
+-            try {
+-                zis = new ZipInputStream(fis);
+-                ZipEntry entry = zis.getNextEntry();
+-                while (entry != null) {
+-                    String name = entry.getName();
+-                    if (name.endsWith(DOT_CLASS) &&
+-                            // Skip resource type classes like R$drawable; they will
+-                            // reference the integer id's we're looking for, but these aren't
+-                            // actual usages we need to track; if somebody references the
+-                            // field elsewhere, we'll catch that
+-                            !isResourceClass(name)) {
+-                        byte[] bytes = ByteStreams.toByteArray(zis);
+-                        if (bytes != null) {
+-                            ClassReader classReader = new ClassReader(bytes);
+-                            classReader.accept(new UsageVisitor(jarFile, name),
+-                                    SKIP_DEBUG | SKIP_FRAMES);
+-                        }
+-                    }
+-
+-                    entry = zis.getNextEntry();
+-                }
+-            } finally {
+-                Closeables.close(fis, true);
+-            }
+-        } finally {
+-            Closeables.close(zis, true);
+-        }
+-    }
+-
+-    /** Returns whether the given class path points to an aapt-generated compiled R class */
+-    @VisibleForTesting
+-    static boolean isResourceClass(@NonNull String name) {
+-        assert name.endsWith(DOT_CLASS) : name;
+-        int index = name.lastIndexOf('/');
+-        if (index != -1 && name.startsWith("R$", index + 1)) {
+-            String typeName = name.substring(index + 3, name.length() - DOT_CLASS.length());
+-            return ResourceType.getEnum(typeName) != null;
+-        }
+-
+-        return false;
+-    }
+-
+-    private void gatherResourceValues(File file) throws IOException {
+-        if (file.isDirectory()) {
+-            File[] children = file.listFiles();
+-            if (children != null) {
+-                for (File child : children) {
+-                    gatherResourceValues(child);
+-                }
+-            }
+-        } else if (file.isFile() && file.getName().equals(SdkConstants.FN_RESOURCE_CLASS)) {
+-            parseResourceClass(file);
+-        }
+-    }
+-
+-    // TODO: Use Lombok/ECJ here
+-    private void parseResourceClass(File file) throws IOException {
+-        String s = Files.toString(file, UTF_8);
+-        // Simple parser which handles only aapt's special R output
+-        String pkg = null;
+-        int index = s.indexOf("package ");
+-        if (index != -1) {
+-            int end = s.indexOf(';', index);
+-            pkg = s.substring(index + "package ".length(), end).trim().replace('.', '/');
+-        }
+-        index = 0;
+-        int length = s.length();
+-        String classDeclaration = "public static final class ";
+-        while (true) {
+-            index = s.indexOf(classDeclaration, index);
+-            if (index == -1) {
+-                break;
+-            }
+-            int start = index + classDeclaration.length();
+-            int end = s.indexOf(' ', start);
+-            if (end == -1) {
+-                break;
+-            }
+-            String typeName = s.substring(start, end);
+-            ResourceType type = ResourceType.getEnum(typeName);
+-            if (type == null) {
+-                break;
+-            }
+-
+-            if (pkg != null) {
+-                mResourceClassOwners.put(pkg + "/R$" + type.getName(), type);
+-            }
+-
+-            index = end;
+-
+-            // Find next declaration
+-            for (; index < length - 1; index++) {
+-                char c = s.charAt(index);
+-                if (Character.isWhitespace(c)) {
+-                    //noinspection UnnecessaryContinue
+-                    continue;
+-                } else if (c == '/') {
+-                    char next = s.charAt(index + 1);
+-                    if (next == '*') {
+-                        // Scan forward to comment end
+-                        end = index + 2;
+-                        while (end < length -2) {
+-                            c = s.charAt(end);
+-                            if (c == '*' && s.charAt(end + 1) == '/') {
+-                                end++;
+-                                break;
+-                            } else {
+-                                end++;
+-                            }
+-                        }
+-                        index = end;
+-                    } else if (next == '/') {
+-                        // Scan forward to next newline
+-                        assert false : s.substring(index - 1, index + 50); // we don't put line comments in R files
+-                    } else {
+-                        assert false : s.substring(index - 1, index + 50); // unexpected division
+-                    }
+-                } else if (c == 'p' && s.startsWith("public ", index)) {
+-                    if (type == ResourceType.STYLEABLE) {
+-                        start = s.indexOf(" int", index);
+-                        if (s.startsWith(" int[] ", start)) {
+-                            end = s.indexOf('=', start);
+-                            assert end != -1;
+-                            String styleable = s.substring(start, end).trim();
+-                            addResource(ResourceType.DECLARE_STYLEABLE, styleable, null);
+-
+-                            // TODO: Read in all the action bar ints!
+-                            // For now, we're simply treating all R.attr fields as used
+-                        } else if (s.startsWith(" int ")) {
+-                            // Read these fields in and correlate with the attr R's. Actually
+-                            // we don't need this for anything; the local attributes are
+-                            // found by the R attr thing. I just need to record the class
+-                            // (style).
+-                            // public static final int ActionBar_background = 10;
+-                            // ignore - jump to end
+-                            index = s.indexOf(';', index);
+-                            if (index == -1) {
+-                                break;
+-                            }
+-                            // For now, we're simply treating all R.attr fields as used
+-                        }
+-                    } else {
+-                        start = s.indexOf(" int ", index);
+-                        if (start != -1) {
+-                            start += " int ".length();
+-                            // e.g. abc_fade_in=0x7f040000;
+-                            end = s.indexOf('=', start);
+-                            assert end != -1;
+-                            String name = s.substring(start, end).trim();
+-                            start = end + 1;
+-                            end = s.indexOf(';', start);
+-                            assert end != -1;
+-                            String value = s.substring(start, end).trim();
+-                            addResource(type, name, value);
+-                        }
+-                    }
+-                } else if (c == '}') {
+-                    // Done with resource class
+-                    break;
+-                }
+-            }
+-        }
+-    }
+-
+-    private void addResource(@NonNull ResourceType type, @NonNull String name,
+-            @Nullable String value) {
+-        int realValue = value != null ? Integer.decode(value) : -1;
+-        Resource resource = getResource(type, name);
+-        if (resource != null) {
+-            //noinspection VariableNotUsedInsideIf
+-            if (value != null) {
+-                if (resource.value == -1) {
+-                    resource.value = realValue;
+-                } else {
+-                    assert realValue == resource.value;
+-                }
+-            }
+-            return;
+-        }
+-
+-        resource = new Resource(type, name, realValue);
+-        mResources.add(resource);
+-        if (realValue != -1) {
+-            mValueToResource.put(realValue, resource);
+-        }
+-        Map<String, Resource> nameMap = mTypeToName.get(type);
+-        if (nameMap == null) {
+-            nameMap = Maps.newHashMapWithExpectedSize(30);
+-            mTypeToName.put(type, nameMap);
+-        }
+-        nameMap.put(name, resource);
+-
+-        // TODO: Assert that we don't set the same resource multiple times to different values.
+-        // Could happen if you pass in stale data!
+-    }
+-
+-    public int getUnusedResourceCount() {
+-        return mUnused.size();
+-    }
+-
+-    @VisibleForTesting
+-    List<Resource> getAllResources() {
+-        return mResources;
+-    }
+-
+-    public static class Resource {
+-        /** Type of resource */
+-        public ResourceType type;
+-        /** Name of resource */
+-        public String name;
+-        /** Integer id location */
+-        public int value;
+-        /** Whether this resource can be reached from one of the roots (manifest, code) */
+-        public boolean reachable;
+-        /** Whether this resource has a default definition (e.g. present in a resource folder
+-         * with no qualifiers). For id references, an inline definition (@+id) does not count as
+-         * a default definition.*/
+-        public boolean hasDefault;
+-        /** Resources this resource references. For example, a layout can reference another via
+-         * an include; a style reference in a layout references that layout style, and so on. */
+-        public List<Resource> references;
+-        public final List<File> declarations = Lists.newArrayList();
+-
+-        private Resource(ResourceType type, String name, int value) {
+-            this.type = type;
+-            this.name = name;
+-            this.value = value;
+-        }
+-
+-        @Override
+-        public String toString() {
+-            return type + ":" + name + ":" + value;
+-        }
+-
+-        @SuppressWarnings("RedundantIfStatement") // Generated by IDE
+-        @Override
+-        public boolean equals(Object o) {
+-            if (this == o) {
+-                return true;
+-            }
+-            if (o == null || getClass() != o.getClass()) {
+-                return false;
+-            }
+-
+-            Resource resource = (Resource) o;
+-
+-            if (name != null ? !name.equals(resource.name) : resource.name != null) {
+-                return false;
+-            }
+-            if (type != resource.type) {
+-                return false;
+-            }
+-
+-            return true;
+-        }
+-
+-        @Override
+-        public int hashCode() {
+-            int result = type != null ? type.hashCode() : 0;
+-            result = 31 * result + (name != null ? name.hashCode() : 0);
+-            return result;
+-        }
+-
+-        public void addLocation(@NonNull File file) {
+-            declarations.add(file);
+-        }
+-
+-        public void addReference(@Nullable Resource resource) {
+-            if (resource != null) {
+-                if (references == null) {
+-                    references = Lists.newArrayList();
+-                } else if (references.contains(resource)) {
+-                    return;
+-                }
+-                references.add(resource);
+-            }
+-        }
+-
+-        public String getUrl() {
+-            return '@' + type.getName() + '/' + name;
+-        }
+-
+-        public boolean isRelevantType() {
+-            return type != ResourceType.ID; // && getFolderType() != ResourceFolderType.VALUES;
+-        }
+-    }
+-
+-    /**
+-     * Class visitor responsible for looking for resource references in code.
+-     * It looks for R.type.name references (as well as inlined constants for these,
+-     * in the case of non-library code), as well as looking both for Resources#getIdentifier
+-     * calls and recording string literals, used to handle dynamic lookup of resources.
+-     */
+-    private class UsageVisitor extends ClassVisitor {
+-        private final File mJarFile;
+-        private final String mCurrentClass;
+-
+-        public UsageVisitor(File jarFile, String name) {
+-            super(Opcodes.ASM5);
+-            mJarFile = jarFile;
+-            mCurrentClass = name;
+-        }
+-
+-        @Override
+-        public MethodVisitor visitMethod(int access, final String name,
+-                String desc, String signature, String[] exceptions) {
+-            return new MethodVisitor(Opcodes.ASM5) {
+-                @Override
+-                public void visitLdcInsn(Object cst) {
+-                    handleCodeConstant(cst, "ldc");
+-                }
+-
+-                @Override
+-                public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+-                    if (opcode == Opcodes.GETSTATIC) {
+-                        ResourceType type = mResourceClassOwners.get(owner);
+-                        if (type != null) {
+-                            Resource resource = getResource(type, name);
+-                            if (resource != null) {
+-                                markReachable(resource);
+-                            }
+-                        }
+-                    }
+-                }
+-
+-                @Override
+-                public void visitMethodInsn(int opcode, String owner, String name,
+-                        String desc, boolean itf) {
+-                    super.visitMethodInsn(opcode, owner, name, desc, itf);
+-                    if (owner.equals("android/content/res/Resources")
+-                            && name.equals("getIdentifier")
+-                            && desc.equals(
+-                            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I")) {
+-                        mFoundGetIdentifier = true;
+-                        // TODO: Check previous instruction and see if we can find a literal
+-                        // String; if so, we can more accurately dispatch the resource here
+-                        // rather than having to check the whole string pool!
+-                    }
+-                    if (owner.equals("android/webkit/WebView") && name.startsWith("load")) {
+-                        mFoundWebContent = true;
+-                    }
+-                }
+-
+-                @Override
+-                public AnnotationVisitor visitAnnotationDefault() {
+-                    return new AnnotationUsageVisitor();
+-                }
+-
+-                @Override
+-                public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+-                    return new AnnotationUsageVisitor();
+-                }
+-
+-                @Override
+-                public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
+-                        boolean visible) {
+-                    return new AnnotationUsageVisitor();
+-                }
+-            };
+-        }
+-
+-        @Override
+-        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+-            return new AnnotationUsageVisitor();
+-        }
+-
+-        @Override
+-        public FieldVisitor visitField(int access, String name, String desc, String signature,
+-                Object value) {
+-            handleCodeConstant(value, "field");
+-            return new FieldVisitor(Opcodes.ASM5) {
+-                @Override
+-                public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+-                    return new AnnotationUsageVisitor();
+-                }
+-            };
+-        }
+-
+-        private class AnnotationUsageVisitor extends AnnotationVisitor {
+-            public AnnotationUsageVisitor() {
+-                super(Opcodes.ASM5);
+-            }
+-
+-            @Override
+-            public AnnotationVisitor visitAnnotation(String name, String desc) {
+-                return new AnnotationUsageVisitor();
+-            }
+-
+-            @Override
+-            public AnnotationVisitor visitArray(String name) {
+-                return new AnnotationUsageVisitor();
+-            }
+-
+-            @Override
+-            public void visit(String name, Object value) {
+-                handleCodeConstant(value, "annotation");
+-                super.visit(name, value);
+-            }
+-        }
+-
+-        /** Invoked when an ASM visitor encounters a constant: record corresponding reference */
+-        private void handleCodeConstant(@Nullable Object cst, @NonNull String context) {
+-            if (cst instanceof Integer) {
+-                Integer value = (Integer) cst;
+-                Resource resource = mValueToResource.get(value);
+-                if (markReachable(resource) && mDebug) {
+-                    System.out.println("Marking " + resource + " reachable: referenced from " +
+-                            context + " in " + mJarFile + ":" + mCurrentClass);
+-                }
+-            } else if (cst instanceof int[]) {
+-                int[] values = (int[]) cst;
+-                for (int value : values) {
+-                    Resource resource = mValueToResource.get(value);
+-                    if (markReachable(resource) && mDebug) {
+-                        System.out.println("Marking " + resource + " reachable: referenced from " +
+-                                context + " in " + mJarFile + ":" + mCurrentClass);
+-                    }
+-                }
+-            } else if (cst instanceof String) {
+-                String string = (String) cst;
+-                referencedString(string);
+-            }
+-        }
+-    }
+-
+-    @VisibleForTesting
+-    String dumpResourceModel() {
+-        StringBuilder sb = new StringBuilder(1000);
+-        Collections.sort(mResources, new Comparator<Resource>() {
+-            @Override
+-            public int compare(Resource resource1,
+-                    Resource resource2) {
+-                int delta = resource1.type.compareTo(resource2.type);
+-                if (delta != 0) {
+-                    return delta;
+-                }
+-                return resource1.name.compareTo(resource2.name);
+-            }
+-        });
+-
+-        for (Resource resource : mResources) {
+-            sb.append(resource.getUrl()).append(" : reachable=").append(resource.reachable);
+-            sb.append("\n");
+-            if (resource.references != null) {
+-                for (Resource referenced : resource.references) {
+-                    sb.append("    ");
+-                    sb.append(referenced.getUrl());
+-                    sb.append("\n");
+-                }
+-            }
+-        }
+-
+-        return sb.toString();
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ShrinkResources.groovy b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ShrinkResources.groovy
+deleted file mode 100644
+index 4031e6c..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ShrinkResources.groovy
++++ /dev/null
+@@ -1,220 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks
+-
+-import com.android.build.gradle.internal.scope.ConventionMappingHelper
+-import com.android.build.gradle.internal.scope.TaskConfigAction
+-import com.android.build.gradle.internal.scope.VariantOutputScope
+-import com.android.build.gradle.internal.tasks.BaseTask
+-import com.android.build.gradle.internal.variant.BaseVariantData
+-import com.android.build.gradle.internal.variant.BaseVariantOutputData
+-import com.android.builder.core.AaptPackageProcessBuilder
+-import com.android.ide.common.process.LoggedProcessOutputHandler
+-import org.gradle.api.logging.LogLevel
+-import org.gradle.api.tasks.InputFile
+-import org.gradle.api.tasks.OutputFile
+-import org.gradle.api.tasks.ParallelizableTask
+-import org.gradle.api.tasks.TaskAction
+-
+-import java.util.concurrent.Callable
+-
+-/**
+- * Task which strips out unused resources
+- * <p>
+- * The process works as follows:
+- * <ul>
+- * <li> Collect R id <b>values</b> from the final merged R class, which incorporates
+- *      the final id's of all the libraries (if ProGuard hasn't inlined these,
+- *      we don't need to do this; we can look for actual R.id's instead!)
+- * <li> Collect <b>used<b> R values from all the .class files, and R.x.y references too!
+- * <li> Compute the set of remaining/used id’s
+- * <li> Add in any found in the manifest
+- * <li> Look through all resources and produce a graph of reachable resources
+- * <li> Compute unused resources by visiting all resources and ignoring those that
+- *      were reachable
+- * <li> In addition, if we find a call to Resources#getIdentifier(), we collect all
+- *      strings in the class files, and also mark as used any resources that match
+- *      potential string lookups
+- * </ul>
+- */
+- at ParallelizableTask
+-public class ShrinkResources extends BaseTask {
+-    /**
+-     * Associated variant data that the strip task will be run against. Used to locate
+-     * not only locations the task needs (e.g. for resources and generated R classes)
+-     * but also to obtain the resource merging task, since we will run it a second time
+-     * here to generate a new .ap_ file with fewer resources
+-     */
+-    public BaseVariantOutputData variantOutputData
+-
+-    @InputFile
+-    File uncompressedResources
+-
+-    @OutputFile
+-    File compressedResources
+-
+-    /** Whether we've already warned about how to turn off shrinking. Used to avoid
+-     * repeating the same multi-line message for every repeated abi split. */
+-    private static ourWarned;
+-
+-    @SuppressWarnings("GroovyUnusedDeclaration")
+-    @TaskAction
+-    void shrink() {
+-        def variantData = variantOutputData.variantData
+-        try {
+-            def processResourcesTask = variantData.generateRClassTask
+-            File sourceDir = processResourcesTask.sourceOutputDir
+-            File resourceDir = variantData.getScope().getFinalResourcesDir()
+-            File mergedManifest = variantOutputData.manifestProcessorTask.manifestOutputFile
+-
+-            // Analyze resources and usages and strip out unused
+-            def analyzer = new ResourceUsageAnalyzer(
+-                    sourceDir,
+-                    variantData.getScope().getProguardOutputFile(),
+-                    mergedManifest,
+-                    variantData.getMappingFile(),
+-                    resourceDir)
+-            analyzer.verbose = project.logger.isEnabled(LogLevel.INFO)
+-            analyzer.debug = project.logger.isEnabled(LogLevel.DEBUG)
+-            analyzer.analyze();
+-
+-            //noinspection GroovyConstantIfStatement
+-            if (ResourceUsageAnalyzer.TWO_PASS_AAPT) {
+-                // This is currently not working; we need support from aapt to be able
+-                // to assign a stable set of resources that it should use.
+-                def destination = new File(resourceDir.parentFile, resourceDir.name + "-stripped")
+-                analyzer.removeUnused(destination)
+-
+-                File sourceOutputs = processResourcesTask.getSourceOutputDir();
+-                sourceOutputs = new File(sourceOutputs.getParentFile(),
+-                        sourceOutputs.getName() + "-stripped")
+-                sourceOutputs.mkdirs()
+-
+-                // We don't need to emit R files again, but we can do this here such that
+-                // we can *verify* that the R classes generated in the second aapt pass
+-                // matches those we saw the first time around.
+-                //String sourceOutputPath = sourceOutputs?.getAbsolutePath();
+-                String sourceOutputPath = null
+-
+-                // Repackage the resources:
+-                AaptPackageProcessBuilder aaptPackageCommandBuilder =
+-                        new AaptPackageProcessBuilder(processResourcesTask.getManifestFile(),
+-                                processResourcesTask.getAaptOptions())
+-                                .setAssetsFolder(processResourcesTask.getAssetsDir())
+-                                .setResFolder(destination)
+-                                .setLibraries(processResourcesTask.getLibraries())
+-                                .setPackageForR(processResourcesTask.getPackageForR())
+-                                .setSourceOutputDir(sourceOutputPath)
+-                                .setResPackageOutput(getCompressedResources().absolutePath)
+-                                .setType(processResourcesTask.getType())
+-                                .setDebuggable(processResourcesTask.getDebuggable())
+-                                .setResourceConfigs(processResourcesTask.getResourceConfigs())
+-                                .setSplits(processResourcesTask.getSplits())
+-
+-                getBuilder().processResources(
+-                        aaptPackageCommandBuilder,
+-                        processResourcesTask.getEnforceUniquePackageName(),
+-                        new LoggedProcessOutputHandler(getBuilder().getLogger())
+-                )
+-            } else {
+-                // Just rewrite the .ap_ file to strip out the res/ files for unused resources
+-                analyzer.rewriteResourceZip(getUncompressedResources(), getCompressedResources())
+-            }
+-
+-            // Dump some stats
+-            int unused = analyzer.getUnusedResourceCount()
+-            if (unused > 0) {
+-                StringBuilder sb = new StringBuilder(200);
+-                sb.append("Removed unused resources")
+-
+-                // This is a bit misleading until we can strip out all resource types:
+-                //int total = analyzer.getTotalResourceCount()
+-                //sb.append("(" + unused + "/" + total + ")")
+-
+-                int before = getUncompressedResources().length()
+-                int after = getCompressedResources().length()
+-                int percent = (before - after) * 100 / before
+-                sb.append(": Binary resource data reduced from ").
+-                        append(toKbString(before)).
+-                        append("KB to ").
+-                        append(toKbString(after)).
+-                        append("KB: Removed " + percent + "%");
+-                if (!ourWarned) {
+-                    ourWarned = true;
+-                    sb.append(
+-                        "\nNote: If necessary, you can disable resource shrinking by adding\n" +
+-                        "android {\n" +
+-                        "    buildTypes {\n" +
+-                        "        " + variantData.variantConfiguration.buildType.name + " {\n" +
+-                        "            shrinkResources false\n" +
+-                        "        }\n" +
+-                        "    }\n" +
+-                        "}")
+-                }
+-
+-                println sb.toString();
+-            }
+-
+-        } catch (Exception e) {
+-            println 'Failed to shrink resources: ' + e.toString() + '; ignoring'
+-            logger.quiet("Failed to shrink resources: ignoring", e)
+-        }
+-    }
+-
+-    private static String toKbString(long size) {
+-        return Integer.toString((int)size/1024);
+-    }
+-
+-    public static class ConfigAction implements TaskConfigAction<ShrinkResources> {
+-
+-        private VariantOutputScope scope;
+-
+-        public ConfigAction(VariantOutputScope scope) {
+-            this.scope = scope;
+-        }
+-
+-        @Override
+-        String getName() {
+-            return scope.getTaskName("shrink", "Resources");
+-        }
+-
+-        @Override
+-        Class<ShrinkResources> getType() {
+-            return ShrinkResources.class
+-        }
+-
+-        @Override
+-        void execute(ShrinkResources task) {
+-            BaseVariantData<? extends BaseVariantOutputData> variantData =
+-                    scope.variantScope.variantData
+-            task.setAndroidBuilder(scope.getGlobalScope().getAndroidBuilder());
+-            task.setVariantName(scope.getVariantScope().getVariantConfiguration().getFullName());
+-            task.variantOutputData = scope.variantOutputData;
+-
+-            final String outputBaseName = scope.variantOutputData.getBaseName();
+-            task.setCompressedResources(scope.getCompressedResourceFile());
+-
+-            ConventionMappingHelper.map(task, "uncompressedResources", new Callable<File>() {
+-                @Override
+-                public File call() {
+-                    return scope.variantOutputData.processResourcesTask.getPackageOutputFile();
+-                }
+-            });
+-
+-        }
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ApiDatabase.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ApiDatabase.java
+deleted file mode 100644
+index 67d47e1..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ApiDatabase.java
++++ /dev/null
+@@ -1,356 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks.annotations;
+-
+-import com.android.annotations.NonNull;
+-import com.android.annotations.VisibleForTesting;
+-import com.google.common.base.Charsets;
+-import com.google.common.base.Splitter;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-import com.google.common.collect.Sets;
+-import com.google.common.io.Files;
+-
+-import java.io.File;
+-import java.io.IOException;
+-import java.util.List;
+-import java.util.Map;
+-import java.util.Set;
+-import java.util.regex.Matcher;
+-import java.util.regex.Pattern;
+-
+-/** Reads a signature file in the format of the new API files in frameworks/base/api */
+-public class ApiDatabase {
+-    @NonNull
+-    private final List<String> lines;
+-    /** Map from class name to set of field names */
+-    @NonNull private final  Map<String,Set<String>> fieldMap =
+-            Maps.newHashMapWithExpectedSize(1000);
+-    /** Map from class name to map of method names whose values are overloaded signatures */
+-    @NonNull private final  Map<String,Map<String,List<String>>> methodMap =
+-            Maps.newHashMapWithExpectedSize(1000);
+-    @NonNull private final Map<String, List<String>> inheritsFrom =
+-            Maps.newHashMapWithExpectedSize(1000);
+-    @NonNull private final  Map<String,Set<String>> intFieldMap =
+-            Maps.newHashMapWithExpectedSize(1000);
+-    @NonNull private final  Set<String> classSet =
+-            Sets.newHashSetWithExpectedSize(1000);
+-
+-    public ApiDatabase(@NonNull List<String> lines) {
+-        this.lines = lines;
+-        readApi();
+-    }
+-
+-    public ApiDatabase(@NonNull File api) throws IOException {
+-        this(Files.readLines(api, Charsets.UTF_8));
+-    }
+-
+-    public boolean hasMethod(String className, String methodName, String arguments) {
+-        // Perform raw lookup
+-        className = getRawClass(className);
+-        methodName = getRawMethod(methodName);
+-        arguments = getRawParameterList(arguments);
+-
+-        Map<String, List<String>> methods = methodMap.get(className);
+-        if (methods != null) {
+-            List<String> strings = methods.get(methodName);
+-            if (strings != null && strings.contains(arguments)) {
+-                return true;
+-            }
+-        }
+-
+-        List<String> inheritsFrom = this.inheritsFrom.get(className);
+-        if (inheritsFrom != null) {
+-            for (String clz : inheritsFrom) {
+-                if (hasMethod(clz, methodName, arguments)) {
+-                    return true;
+-                }
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    public boolean hasField(String className, String fieldName) {
+-        Set<String> fields = fieldMap.get(className);
+-        if (fields != null && fields.contains(fieldName)) {
+-            return true;
+-        }
+-
+-        List<String> inheritsFrom = this.inheritsFrom.get(className);
+-        if (inheritsFrom != null) {
+-            for (String clz : inheritsFrom) {
+-                if (hasField(clz, fieldName)) {
+-                    return true;
+-                }
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    public boolean hasClass(String className) {
+-        return classSet.contains(className);
+-    }
+-
+-    public Set<String> getDeclaredIntFields(String className) {
+-        return intFieldMap.get(className);
+-    }
+-
+-    private void readApi() {
+-        String MODIFIERS =
+-                "((deprecated|public|static|private|protected|final|abstract|\\s*)\\s+)*";
+-        Pattern PACKAGE = Pattern.compile("package (\\S+) \\{");
+-        Pattern CLASS =
+-                Pattern.compile(MODIFIERS
+-                        + "(class|interface|enum)\\s+(\\S+)\\s+(extends (.+))?(implements (.+))?(.*)\\{");
+-        Pattern METHOD = Pattern.compile("(method|ctor)\\s+" +
+-                MODIFIERS + "(.+)??\\s+(\\S+)\\s*\\((.*)\\)(.*);");
+-        Pattern CTOR = Pattern.compile("(method|ctor)\\s+.*\\((.*)\\)(.*);");
+-        Pattern FIELD = Pattern.compile("(enum_constant|field)\\s+" +
+-                MODIFIERS + "(.+)\\s+(\\S+)\\s*;");
+-
+-        String currentPackage = null;
+-        String currentClass = null;
+-
+-        for (String line : lines) {
+-            line = line.trim();
+-            if (line.isEmpty() || line.equals("}")) {
+-                continue;
+-            }
+-            if (line.startsWith("method ")) {
+-                Matcher matcher = METHOD.matcher(line);
+-                if (!matcher.matches()) {
+-                    Extractor.warning("Warning: Did not match as a member: " + line);
+-                } else {
+-                    assert currentClass != null;
+-                    Map<String,List<String>> memberMap = methodMap.get(currentClass);
+-                    if (memberMap == null) {
+-                        memberMap = Maps.newHashMap();
+-                        methodMap.put(currentClass, memberMap);
+-                        methodMap.put(getRawClass(currentClass), memberMap);
+-                    }
+-                    String methodName = matcher.group(5);
+-                    List<String> signatures = memberMap.get(methodName);
+-                    if (signatures == null) {
+-                        signatures = Lists.newArrayList();
+-                        memberMap.put(methodName, signatures);
+-                        memberMap.put(getRawMethod(methodName), signatures);
+-                    }
+-                    String signature = matcher.group(6);
+-                    signature = signature.trim().replace(" ", "").replace(" ", "");
+-                    // normalize varargs: allow lookup with both formats
+-                    signatures.add(signature);
+-                    if (signature.endsWith("...")) {
+-                        signatures.add(signature.substring(0, signature.length() - 3) + "[]");
+-                    } else if (signature.endsWith("[]") && !signature.endsWith("[][]")) {
+-                        signatures.add(signature.substring(0, signature.length() - 2) + "...");
+-                    }
+-                    String raw = getRawParameterList(signature);
+-                    if (!signatures.contains(raw)) {
+-                        signatures.add(raw);
+-                    }
+-                }
+-            } else if (line.startsWith("ctor ")) {
+-                Matcher matcher = CTOR.matcher(line);
+-                if (!matcher.matches()) {
+-                    Extractor.warning("Warning: Did not match as a member: " + line);
+-                } else {
+-                    assert currentClass != null;
+-                    Map<String,List<String>> memberMap = methodMap.get(currentClass);
+-                    if (memberMap == null) {
+-                        memberMap = Maps.newHashMap();
+-                        methodMap.put(currentClass, memberMap);
+-                        methodMap.put(getRawClass(currentClass), memberMap);
+-                    }
+-                    @SuppressWarnings("UnnecessaryLocalVariable")
+-                    String methodName = currentClass;
+-                    List<String> signatures = memberMap.get(methodName);
+-                    if (signatures == null) {
+-                        signatures = Lists.newArrayList();
+-                        memberMap.put(methodName, signatures);
+-                        String constructor = methodName.substring(methodName.lastIndexOf('.') + 1);
+-                        memberMap.put(constructor, signatures);
+-                        memberMap.put(getRawMethod(methodName), signatures);
+-                        memberMap.put(getRawMethod(constructor), signatures);
+-                    }
+-                    String signature = matcher.group(2);
+-                    signature = signature.trim().replace(" ", "").replace(" ", "");
+-                    if (signature.endsWith("...")) {
+-                        signatures.add(signature.substring(0, signature.length() - 3) + "[]");
+-                    } else if (signature.endsWith("[]") && !signature.endsWith("[][]")) {
+-                        signatures.add(signature.substring(0, signature.length() - 2) + "...");
+-                    }
+-                    signatures.add(signature);
+-                    String raw = getRawMethod(signature);
+-                    if (!signatures.contains(raw)) {
+-                        signatures.add(raw);
+-                    }
+-                }
+-            } else if (line.startsWith("enum_constant ") || line.startsWith("field ")) {
+-                int equals = line.indexOf('=');
+-                if (equals != -1) {
+-                    line = line.substring(0, equals).trim();
+-                    int semi = line.indexOf(';');
+-                    if (semi == -1) {
+-                        line = line + ';';
+-                    }
+-                } else if (!line.endsWith(";")) {
+-                    int semi = line.indexOf(';');
+-                    if (semi != -1) {
+-                        line = line.substring(0, semi + 1);
+-                    }
+-                }
+-                Matcher matcher = FIELD.matcher(line);
+-                if (!matcher.matches()) {
+-                    Extractor.warning("Warning: Did not match as a member: " + line);
+-                } else {
+-                    assert currentClass != null;
+-                    String fieldName = matcher.group(5);
+-                    Set<String> fieldSet = fieldMap.get(currentClass);
+-                    if (fieldSet == null) {
+-                        fieldSet = Sets.newHashSet();
+-                        fieldMap.put(currentClass, fieldSet);
+-                    }
+-                    fieldSet.add(fieldName);
+-                    String type = matcher.group(4);
+-                    if (type.equals("int")) {
+-                        fieldSet = intFieldMap.get(currentClass);
+-                        if (fieldSet == null) {
+-                            fieldSet = Sets.newHashSet();
+-                            intFieldMap.put(currentClass, fieldSet);
+-                        }
+-                        fieldSet.add(fieldName);
+-                    }
+-                }
+-            } else if (line.startsWith("package ")) {
+-                Matcher matcher = PACKAGE.matcher(line);
+-                if (!matcher.matches()) {
+-                    Extractor.warning("Warning: Did not match as a package: " + line);
+-                } else {
+-                    currentPackage = matcher.group(1);
+-                }
+-            } else {
+-                Matcher matcher = CLASS.matcher(line);
+-                if (!matcher.matches()) {
+-                    Extractor.warning("Warning: Did not match as a class/interface: " + line);
+-                } else {
+-                    currentClass = currentPackage + '.' + matcher.group(4);
+-                    classSet.add(currentClass);
+-
+-                    String superClass = matcher.group(6);
+-                    if (superClass != null) {
+-                        Splitter splitter = Splitter.on(' ').trimResults().omitEmptyStrings();
+-                        for (String from : splitter.split(superClass)) {
+-                            if (from.equals("implements")) {  // workaround for broken regexp
+-                                continue;
+-                            }
+-                            addInheritsFrom(currentClass, from);
+-                        }
+-                        addInheritsFrom(currentClass, superClass.trim());
+-                    }
+-                    String implementsList = matcher.group(8);
+-                    if (implementsList != null) {
+-                        Splitter splitter = Splitter.on(' ').trimResults().omitEmptyStrings();
+-                        for (String from : splitter.split(implementsList)) {
+-                            addInheritsFrom(currentClass, from);
+-                        }
+-                    }
+-                }
+-            }
+-        }
+-    }
+-
+-    private void addInheritsFrom(String cls, String inheritsFrom) {
+-        List<String> list = this.inheritsFrom.get(cls);
+-        if (list == null) {
+-            list = Lists.newArrayList();
+-            this.inheritsFrom.put(cls, list);
+-        }
+-        list.add(inheritsFrom);
+-    }
+-
+-    /** Drop generic type variables from a class name */
+-    @VisibleForTesting
+-    static String getRawClass(@NonNull String name) {
+-        int index = name.indexOf('<');
+-        if (index != -1) {
+-            int end = name.indexOf('>', index + 1);
+-            if (end == -1 || end == name.length() - 1) {
+-                return name.substring(0, index);
+-            } else {
+-                // e.g. test.pkg.ArrayAdapter<T>.Inner
+-                return name.substring(0, index) + name.substring(end + 1);
+-            }
+-        }
+-        return name;
+-    }
+-
+-    /** Drop generic type variables from a method or constructor name */
+-    @VisibleForTesting
+-    static String getRawMethod(@NonNull String name) {
+-        int index = name.indexOf('<');
+-        if (index != -1) {
+-            return name.substring(0, index);
+-        }
+-        return name;
+-    }
+-
+-    /** Drop generic type variables and varargs to produce a raw signature */
+-    @VisibleForTesting
+-    static String getRawParameterList(String signature) {
+-        if (signature.indexOf('<') == -1 && !signature.endsWith("...")) {
+-            return signature;
+-        }
+-
+-        int n = signature.length();
+-        StringBuilder sb = new StringBuilder(n);
+-        int start = 0;
+-        while (true) {
+-            int index = signature.indexOf('<', start);
+-            if (index == -1) {
+-                sb.append(signature.substring(start));
+-                break;
+-            }
+-            sb.append(signature.substring(start, index));
+-            int balance = 1;
+-            for (int i = index + 1; i < n; i++) {
+-                char c = signature.charAt(i);
+-                if (c == '<') {
+-                    balance++;
+-                } else if (c == '>') {
+-                    balance--;
+-                    if (balance == 0) {
+-                        start = i + 1;
+-                        break;
+-                    }
+-                }
+-            }
+-        }
+-
+-        // Normalize varargs... to []
+-        if (sb.length() > 3
+-                && sb.charAt(sb.length() - 1) == '.'
+-                && sb.charAt(sb.length() - 2) == '.'
+-                && sb.charAt(sb.length() - 3) == '.') {
+-            sb.setLength(sb.length() - 3);
+-            sb.append('[').append(']');
+-        }
+-
+-        return sb.toString();
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ExtractAnnotationsDriver.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ExtractAnnotationsDriver.java
+deleted file mode 100644
+index 78ec03d..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/ExtractAnnotationsDriver.java
++++ /dev/null
+@@ -1,400 +0,0 @@
+-/*
+- * Copyright (C) 2015 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.build.gradle.tasks.annotations;
+-
+-import static com.android.SdkConstants.DOT_JAVA;
+-import static java.io.File.pathSeparator;
+-import static java.io.File.pathSeparatorChar;
+-
+-import com.android.annotations.NonNull;
+-import com.android.tools.lint.EcjParser;
+-import com.android.utils.Pair;
+-import com.google.common.base.Charsets;
+-import com.google.common.base.Splitter;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-import com.google.common.io.Files;
+-
+-import org.eclipse.jdt.core.compiler.IProblem;
+-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+-import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
+-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+-import org.eclipse.jdt.internal.compiler.util.Util;
+-
+-import java.io.File;
+-import java.io.IOException;
+-import java.io.PrintStream;
+-import java.util.Collection;
+-import java.util.List;
+-import java.util.Map;
+-
+-/**
+- * The extract annotations driver is a command line interface to extracting annotations
+- * from a source tree. It's similar to the gradle
+- * {@link com.android.build.gradle.tasks.ExtractAnnotations} task,
+- * but usable from the command line and outside Gradle, for example
+- * to extract annotations from the Android framework itself (which is not built with
+- * Gradle). It also allows other options only interesting for extracting
+- * platform annotations, such as filtering all APIs and constants through an
+- * API white-list (such that we for example can pull annotations from the master
+- * branch which has the latest metadata, but only expose APIs that are actually in
+- * a released platform), as well as translating android.annotation annotations into
+- * android.support.annotations.
+- */
+-public class ExtractAnnotationsDriver {
+-    public static void main(String[] args) {
+-        new ExtractAnnotationsDriver().run(args);
+-    }
+-
+-    private static void usage(PrintStream output) {
+-        output.println("Usage: " + ExtractAnnotationsDriver.class.getSimpleName() + " <flags>");
+-        output.println(" --sources <paths>       : Source directories to extract annotations from. ");
+-        output.println("                           Separate paths with " + pathSeparator + ", and you can use @ ");
+-        output.println("                           as a filename prefix to have the filenames fed from a file");
+-        output.println("--classpath <paths>      : Directories and .jar files to resolve symbols from");
+-        output.println("--output <zip path>      : The .zip file to write the extracted annotations to, if any");
+-        output.println("--proguard <path>        : The proguard.cfg file to write the keep rules to, if any");
+-        output.println();
+-        output.println("Optional flags:");
+-        output.println("--merge-zips <paths>     : Existing external annotation files to merge in");
+-        output.println("--quiet                  : Don't print summary information");
+-        output.println("--rmtypedefs <folder>    : Remove typedef classes found in the given folder");
+-        output.println("--allow-missing-types    : Don't fail even if some types can't be resolved");
+-        output.println("--allow-errors           : Don't fail even if there are some compiler errors");
+-        output.println("--encoding <encoding>    : Encoding (defaults to utf-8)");
+-        output.println("--language-level <level> : Java source language level, typically 1.6 (default) or 1.7");
+-        output.println("--api-filter <api.txt>   : A framework API definition to restrict included APIs to");
+-        output.println("--hide-filtered          : If filtering out non-APIs, supply this flag to hide listing matches");
+-        output.println("--skip-class-retention   : Don't extract annotations that have class retention");
+-        System.exit(-1);
+-    }
+-
+-    @SuppressWarnings("MethodMayBeStatic")
+-    public void run(@NonNull String[] args) {
+-        List<String> classpath = Lists.newArrayList();
+-        List<File> sources = Lists.newArrayList();
+-        List<File> mergePaths = Lists.newArrayList();
+-        List<File> apiFilters = null;
+-        File rmTypeDefs = null;
+-        boolean verbose = true;
+-        boolean allowMissingTypes = false;
+-        boolean allowErrors = false;
+-        boolean listFiltered = true;
+-        boolean skipClassRetention = false;
+-
+-        String encoding = Charsets.UTF_8.name();
+-        File output = null;
+-        File proguard = null;
+-        long languageLevel = EcjParser.getLanguageLevel(1, 7);
+-        if (args.length == 1 && "--help".equals(args[0])) {
+-            usage(System.out);
+-        }
+-        if (args.length < 2) {
+-            usage(System.err);
+-        }
+-        for (int i = 0, n = args.length; i < n; i++) {
+-            String flag = args[i];
+-
+-            if (flag.equals("--quiet")) {
+-                verbose = false;
+-                continue;
+-            } else if (flag.equals("--allow-missing-types")) {
+-                allowMissingTypes = true;
+-                continue;
+-            } else if (flag.equals("--allow-errors")) {
+-                allowErrors = true;
+-                continue;
+-            } else if (flag.equals("--hide-filtered")) {
+-                listFiltered = false;
+-                continue;
+-            } else if (flag.equals("--skip-class-retention")) {
+-                skipClassRetention = true;
+-                continue;
+-            }
+-            if (i == n - 1) {
+-                usage(System.err);
+-            }
+-            String value = args[i + 1];
+-            i++;
+-
+-            if (flag.equals("--sources")) {
+-                sources = getFiles(value);
+-            } else if (flag.equals("--classpath")) {
+-                classpath = getPaths(value);
+-            } else if (flag.equals("--merge-zips")) {
+-                mergePaths = getFiles(value);
+-            } else if (flag.equals("--output")) {
+-                output = new File(value);
+-                if (output.exists()) {
+-                    if (output.isDirectory()) {
+-                        abort(output + " is a directory");
+-                    }
+-                    boolean deleted = output.delete();
+-                    if (!deleted) {
+-                        abort("Could not delete previous version of " + output);
+-                    }
+-                } else if (output.getParentFile() != null && !output.getParentFile().exists()) {
+-                    abort(output.getParentFile() + " does not exist");
+-                }
+-            } else if (flag.equals("--proguard")) {
+-                proguard = new File(value);
+-                if (proguard.exists()) {
+-                    if (proguard.isDirectory()) {
+-                        abort(proguard + " is a directory");
+-                    }
+-                    boolean deleted = proguard.delete();
+-                    if (!deleted) {
+-                        abort("Could not delete previous version of " + proguard);
+-                    }
+-                } else if (proguard.getParentFile() != null && !proguard.getParentFile().exists()) {
+-                    abort(proguard.getParentFile() + " does not exist");
+-                }
+-            } else if (flag.equals("--encoding")) {
+-                encoding = value;
+-            } else if (flag.equals("--api-filter")) {
+-                if (apiFilters == null) {
+-                    apiFilters = Lists.newArrayList();
+-                }
+-                for (String path : Splitter.on(",").omitEmptyStrings().split(value)) {
+-                    File apiFilter = new File(path);
+-                    if (!apiFilter.isFile()) {
+-                        String message = apiFilter + " does not exist or is not a file";
+-                        abort(message);
+-                    }
+-                    apiFilters.add(apiFilter);
+-                }
+-            } else if (flag.equals("--language-level")) {
+-                if ("1.6".equals(value)) {
+-                    languageLevel = EcjParser.getLanguageLevel(1, 6);
+-                } else if ("1.7".equals(value)) {
+-                    languageLevel = EcjParser.getLanguageLevel(1, 7);
+-                } else {
+-                    abort("Unsupported language level " + value);
+-                }
+-            } else if (flag.equals("--rmtypedefs")) {
+-                rmTypeDefs = new File(value);
+-                if (!rmTypeDefs.isDirectory()) {
+-                    abort(rmTypeDefs + " is not a directory");
+-                }
+-            } else {
+-                System.err.println("Unknown flag " + flag + ": Use --help for usage information");
+-            }
+-        }
+-
+-        if (sources.isEmpty()) {
+-            abort("Must specify at least one source path");
+-        }
+-        if (classpath.isEmpty()) {
+-            abort("Must specify classpath pointing to at least android.jar or the framework");
+-        }
+-        if (output == null && proguard == null) {
+-            abort("Must specify output path with --output or a proguard path with --proguard");
+-        }
+-
+-        // API definition files
+-        ApiDatabase database = null;
+-        if (apiFilters != null && !apiFilters.isEmpty()) {
+-            try {
+-                List<String> lines = Lists.newArrayList();
+-                for (File file : apiFilters) {
+-                    lines.addAll(Files.readLines(file, Charsets.UTF_8));
+-                }
+-                database = new ApiDatabase(lines);
+-            } catch (IOException e) {
+-                abort("Could not open API database " + apiFilters + ": " + e.getLocalizedMessage());
+-            }
+-        }
+-
+-        Extractor extractor = new Extractor(database, rmTypeDefs, verbose, !skipClassRetention,
+-                true);
+-        extractor.setListIgnored(listFiltered);
+-
+-        try {
+-            Pair<Collection<CompilationUnitDeclaration>, INameEnvironment>
+-                    pair = parseSources(sources, classpath, encoding, languageLevel);
+-            Collection<CompilationUnitDeclaration> units = pair.getFirst();
+-
+-            boolean abort = false;
+-            int errorCount = 0;
+-            for (CompilationUnitDeclaration unit : units) {
+-                // so maybe I don't need my map!!
+-                IProblem[] problems = unit.compilationResult().getAllProblems();
+-                if (problems != null) {
+-                    for (IProblem problem : problems) {
+-                        if (problem.isError()) {
+-                            errorCount++;
+-                            String message = problem.getMessage();
+-                            if (allowMissingTypes) {
+-                                if (message.contains("cannot be resolved")) {
+-                                    continue;
+-                                }
+-                            }
+-
+-                            System.out.println("Error: " +
+-                                    new String(problem.getOriginatingFileName()) + ":" +
+-                                    problem.getSourceLineNumber() + ": " + message);
+-                            abort = !allowErrors;
+-                        }
+-                    }
+-                }
+-            }
+-            if (errorCount > 0) {
+-                System.err.println("Found " + errorCount + " errors");
+-            }
+-            if (abort) {
+-                abort("Not extracting annotations (compilation problems encountered)");
+-            }
+-
+-            INameEnvironment environment = pair.getSecond();
+-            extractor.extractFromProjectSource(units);
+-
+-            if (mergePaths != null) {
+-                for (File jar : mergePaths) {
+-                    extractor.mergeExisting(jar);
+-                }
+-            }
+-
+-            extractor.export(output, proguard);
+-
+-            // Remove typedefs?
+-            //noinspection VariableNotUsedInsideIf
+-            if (rmTypeDefs != null) {
+-                extractor.removeTypedefClasses();
+-            }
+-
+-            environment.cleanup();
+-        } catch (IOException e) {
+-            e.printStackTrace();
+-        }
+-    }
+-
+-    private static void abort(@NonNull String message) {
+-        System.err.println(message);
+-        System.exit(-1);
+-    }
+-
+-    private static List<File> getFiles(String value) {
+-        List<File> files = Lists.newArrayList();
+-        Splitter splitter = Splitter.on(pathSeparatorChar).omitEmptyStrings().trimResults();
+-        for (String path : splitter.split(value)) {
+-            if (path.startsWith("@")) {
+-                // Special syntax for providing files in a list
+-                File sourcePath = new File(path.substring(1));
+-                if (!sourcePath.exists()) {
+-                    abort(sourcePath + " does not exist");
+-                }
+-                try {
+-                    for (String line : Files.readLines(sourcePath, Charsets.UTF_8)) {
+-                        line = line.trim();
+-                        if (!line.isEmpty()) {
+-                            File file = new File(line);
+-                            if (!file.exists()) {
+-                                System.err.println("Warning: Could not find file " + line +
+-                                        " listed in " + sourcePath);
+-                            }
+-                            files.add(file);
+-                        }
+-                    }
+-                    continue;
+-                } catch (IOException e) {
+-                    e.printStackTrace();
+-                    System.exit(-1);
+-                }
+-            }
+-            File file = new File(path);
+-            if (!file.exists()) {
+-                abort(file + " does not exist");
+-            }
+-            files.add(file);
+-        }
+-
+-        return files;
+-    }
+-
+-    private static List<String> getPaths(String value) {
+-        List<File> files = getFiles(value);
+-        List<String> paths = Lists.newArrayListWithExpectedSize(files.size());
+-        for (File file : files) {
+-            paths.add(file.getPath());
+-        }
+-        return paths;
+-    }
+-
+-    private static void addJavaSources(List<File> list, File file) {
+-        if (file.isDirectory()) {
+-            File[] files = file.listFiles();
+-            if (files != null) {
+-                for (File child : files) {
+-                    addJavaSources(list, child);
+-                }
+-            }
+-        } else {
+-            if (file.isFile() && file.getName().endsWith(DOT_JAVA)) {
+-                list.add(file);
+-            }
+-        }
+-    }
+-
+-    private static List<File> gatherJavaSources(List<File> sourcePath) {
+-        List<File> sources = Lists.newArrayList();
+-        for (File file : sourcePath) {
+-            addJavaSources(sources, file);
+-        }
+-        return sources;
+-    }
+-
+-    @NonNull
+-    private static Pair<Collection<CompilationUnitDeclaration>,INameEnvironment> parseSources(
+-            @NonNull List<File> sourcePaths,
+-            @NonNull List<String> classpath,
+-            @NonNull String encoding,
+-            long languageLevel)
+-            throws IOException {
+-        List<ICompilationUnit> sourceUnits = Lists.newArrayListWithExpectedSize(100);
+-
+-        for (File source : gatherJavaSources(sourcePaths)) {
+-            char[] contents = Util.getFileCharContent(source, encoding);
+-            ICompilationUnit unit = new CompilationUnit(contents, source.getPath(), encoding);
+-            sourceUnits.add(unit);
+-        }
+-
+-        Map<ICompilationUnit, CompilationUnitDeclaration> outputMap = Maps.newHashMapWithExpectedSize(
+-                sourceUnits.size());
+-
+-        CompilerOptions options = EcjParser.createCompilerOptions();
+-        options.docCommentSupport = true; // So I can find @hide
+-
+-        // Note: We can *not* set options.ignoreMethodBodies=true because it disables
+-        // type attribution!
+-
+-        options.sourceLevel = languageLevel;
+-        options.complianceLevel = options.sourceLevel;
+-        // We don't generate code, but just in case the parser consults this flag
+-        // and makes sure that it's not greater than the source level:
+-        options.targetJDK = options.sourceLevel;
+-        options.originalComplianceLevel = options.sourceLevel;
+-        options.originalSourceLevel = options.sourceLevel;
+-        options.inlineJsrBytecode = true; // >= 1.5
+-
+-        INameEnvironment environment = EcjParser.parse(options, sourceUnits, classpath,
+-                outputMap, null);
+-        Collection<CompilationUnitDeclaration> parsedUnits = outputMap.values();
+-        return Pair.of(parsedUnits, environment);
+-    }
+-}
+\ No newline at end of file
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/Extractor.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/Extractor.java
+deleted file mode 100644
+index 8cc6042..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/Extractor.java
++++ /dev/null
+@@ -1,2484 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks.annotations;
+-
+-import static com.android.SdkConstants.AMP_ENTITY;
+-import static com.android.SdkConstants.APOS_ENTITY;
+-import static com.android.SdkConstants.ATTR_NAME;
+-import static com.android.SdkConstants.ATTR_VALUE;
+-import static com.android.SdkConstants.DOT_CLASS;
+-import static com.android.SdkConstants.DOT_JAR;
+-import static com.android.SdkConstants.DOT_XML;
+-import static com.android.SdkConstants.GT_ENTITY;
+-import static com.android.SdkConstants.INT_DEF_ANNOTATION;
+-import static com.android.SdkConstants.LT_ENTITY;
+-import static com.android.SdkConstants.QUOT_ENTITY;
+-import static com.android.SdkConstants.STRING_DEF_ANNOTATION;
+-import static com.android.SdkConstants.SUPPORT_ANNOTATIONS_PREFIX;
+-import static com.android.SdkConstants.TYPE_DEF_FLAG_ATTRIBUTE;
+-import static com.android.SdkConstants.TYPE_DEF_VALUE_ATTRIBUTE;
+-import static com.android.SdkConstants.VALUE_TRUE;
+-import static com.android.tools.lint.checks.SupportAnnotationDetector.INT_RANGE_ANNOTATION;
+-import static com.android.tools.lint.detector.api.LintUtils.assertionsEnabled;
+-
+-import com.android.annotations.NonNull;
+-import com.android.annotations.Nullable;
+-import com.android.utils.XmlUtils;
+-import com.google.common.base.Charsets;
+-import com.google.common.base.Splitter;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-import com.google.common.collect.Sets;
+-import com.google.common.io.ByteStreams;
+-import com.google.common.io.Closeables;
+-import com.google.common.io.Files;
+-import com.google.common.xml.XmlEscapers;
+-
+-import org.eclipse.jdt.internal.compiler.ASTVisitor;
+-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+-import org.eclipse.jdt.internal.compiler.ast.Annotation;
+-import org.eclipse.jdt.internal.compiler.ast.Argument;
+-import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
+-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+-import org.eclipse.jdt.internal.compiler.ast.Expression;
+-import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
+-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+-import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+-import org.eclipse.jdt.internal.compiler.ast.NameReference;
+-import org.eclipse.jdt.internal.compiler.ast.NumberLiteral;
+-import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
+-import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+-import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
+-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+-import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
+-import org.eclipse.jdt.internal.compiler.impl.ByteConstant;
+-import org.eclipse.jdt.internal.compiler.impl.CharConstant;
+-import org.eclipse.jdt.internal.compiler.impl.Constant;
+-import org.eclipse.jdt.internal.compiler.impl.DoubleConstant;
+-import org.eclipse.jdt.internal.compiler.impl.FloatConstant;
+-import org.eclipse.jdt.internal.compiler.impl.IntConstant;
+-import org.eclipse.jdt.internal.compiler.impl.LongConstant;
+-import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+-import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
+-import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+-import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.Binding;
+-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+-import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+-import org.eclipse.jdt.internal.compiler.lookup.ElementValuePair;
+-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.MemberTypeBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+-import org.eclipse.jdt.internal.compiler.lookup.Scope;
+-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+-import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+-import org.w3c.dom.Document;
+-import org.w3c.dom.Element;
+-import org.w3c.dom.Node;
+-import org.w3c.dom.NodeList;
+-import org.xml.sax.SAXException;
+-import org.xml.sax.SAXParseException;
+-
+-import java.io.BufferedWriter;
+-import java.io.File;
+-import java.io.FileInputStream;
+-import java.io.FileOutputStream;
+-import java.io.FileWriter;
+-import java.io.IOException;
+-import java.io.PrintWriter;
+-import java.io.StringWriter;
+-import java.io.Writer;
+-import java.lang.reflect.Field;
+-import java.util.ArrayList;
+-import java.util.Arrays;
+-import java.util.Collection;
+-import java.util.Collections;
+-import java.util.Comparator;
+-import java.util.List;
+-import java.util.Map;
+-import java.util.Set;
+-import java.util.jar.JarEntry;
+-import java.util.jar.JarInputStream;
+-import java.util.jar.JarOutputStream;
+-import java.util.regex.Matcher;
+-import java.util.regex.Pattern;
+-import java.util.zip.ZipEntry;
+-
+-/**
+- * Annotation extractor which looks for annotations in parsed compilation units and writes
+- * the annotations into a format suitable for use by IntelliJ and Android Studio etc;
+- * it's basically an XML file, organized by package, which lists the signatures for
+- * fields and methods in classes in the given package, and identifiers method parameters
+- * by index, and lists the annotations annotated on that element.
+- * <p>
+- * This is primarily intended for use in Android libraries such as the support library,
+- * where you want to use the resource int ({@code StringRes}, {@code DrawableRes}, and so on)
+- * annotations to indicate what types of id's are expected, or the {@code IntDef} or
+- * {@code StringDef} annotations to record which specific constants are allowed in int and
+- * String parameters.
+- * <p>
+- * However, the code is also used to extract SDK annotations from the platform, where
+- * the package names of the annotations differ slightly (and where the nullness annotations
+- * do not have class retention for example). Therefore, this code contains some extra
+- * support not needed when extracting annotations in an Android library, such as code
+- * to skip annotations for any method/field not mentioned in the API database, and code
+- * to rewrite the android.jar file to insert annotations in the generated bytecode.
+- * <p>
+- * TODO:
+- * - Warn if the {@code @IntDef} annotation is used on a non-int, and similarly if
+- *   {@code @StringDef} is used on a non-string
+- * - Ignore annotations defined on @hide elements
+- */
+-public class Extractor {
+-    /** Whether we should include type args like <T*gt; in external annotations signatures */
+-    private static final boolean INCLUDE_TYPE_ARGS = false;
+-
+-    /** Whether to sort annotation attributes (otherwise their declaration order is used) */
+-    private final boolean sortAnnotations;
+-
+-    /**
+-     * Whether we should include class-retention annotations into the extracted file;
+-     * we don't need {@code android.support.annotation.Nullable} to be in the extracted XML
+-     * file since it has class retention and will appear in the compiled .jar version of
+-     * the library
+-     */
+-    private final boolean includeClassRetentionAnnotations;
+-
+-    /**
+-     * Whether we should skip nullable annotations in merged in annotations zip files
+-     * (these are typically from infer nullity, which sometimes is a bit aggressive
+-     * in assuming something should be marked as nullable; see for example issue #66999
+-     * or all the manual removals of findViewById @Nullable return value annotations
+-     */
+-    private static final boolean INCLUDE_INFERRED_NULLABLE = false;
+-
+-    public static final String ANDROID_ANNOTATIONS_PREFIX = "android.annotation.";
+-    public static final String ANDROID_NULLABLE = "android.annotation.Nullable";
+-    public static final String SUPPORT_NULLABLE = "android.support.annotation.Nullable";
+-    public static final String SUPPORT_KEEP = "android.support.annotation.Keep";
+-    public static final String RESOURCE_TYPE_ANNOTATIONS_SUFFIX = "Res";
+-    public static final String ANDROID_NOTNULL = "android.annotation.NonNull";
+-    public static final String SUPPORT_NOTNULL = "android.support.annotation.NonNull";
+-    public static final String ANDROID_INT_DEF = "android.annotation.IntDef";
+-    public static final String ANDROID_INT_RANGE = "android.annotation.IntRange";
+-    public static final String ANDROID_STRING_DEF = "android.annotation.StringDef";
+-    public static final String REQUIRES_PERMISSION = "android.support.annotation.RequiresPermission";
+-    public static final String ANDROID_REQUIRES_PERMISSION = "android.annotation.RequiresPermission";
+-    public static final String IDEA_NULLABLE = "org.jetbrains.annotations.Nullable";
+-    public static final String IDEA_NOTNULL = "org.jetbrains.annotations.NotNull";
+-    public static final String IDEA_MAGIC = "org.intellij.lang.annotations.MagicConstant";
+-    public static final String IDEA_CONTRACT = "org.jetbrains.annotations.Contract";
+-    public static final String IDEA_NON_NLS = "org.jetbrains.annotations.NonNls";
+-    public static final String ATTR_VAL = "val";
+-
+-    @NonNull
+-    private final Map<String, List<AnnotationData>> types = Maps.newHashMap();
+-
+-    @NonNull
+-    private final Set<String> irrelevantAnnotations = Sets.newHashSet();
+-
+-    private final File classDir;
+-
+-    @NonNull
+-    private final Map<String, Map<String, List<Item>>> itemMap = Maps.newHashMap();
+-
+-    @Nullable
+-    private final ApiDatabase apiFilter;
+-
+-    private final boolean displayInfo;
+-
+-    private final Map<String,Integer> stats = Maps.newHashMap();
+-    private int filteredCount;
+-    private int mergedCount;
+-    private final Set<CompilationUnitDeclaration> processedFiles = Sets.newHashSetWithExpectedSize(100);
+-    private final Set<String> ignoredAnnotations = Sets.newHashSet();
+-    private boolean listIgnored;
+-    private Map<String,List<Annotation>> typedefs;
+-    private List<String> typedefClasses;
+-    private Map<String,Boolean> sourceRetention;
+-    private final List<Item> keepItems = Lists.newArrayList();
+-
+-    public Extractor(@Nullable ApiDatabase apiFilter, @Nullable File classDir, boolean displayInfo,
+-            boolean includeClassRetentionAnnotations, boolean sortAnnotations) {
+-        this.apiFilter = apiFilter;
+-        this.listIgnored = apiFilter != null;
+-        this.classDir = classDir;
+-        this.displayInfo = displayInfo;
+-        this.includeClassRetentionAnnotations = includeClassRetentionAnnotations;
+-        this.sortAnnotations = sortAnnotations;
+-    }
+-
+-    public void extractFromProjectSource(Collection<CompilationUnitDeclaration> units) {
+-        TypedefCollector collector = new TypedefCollector(units, false /*requireHide*/,
+-                true /*requireSourceRetention*/);
+-        typedefs = collector.getTypedefs();
+-        typedefClasses = collector.getNonPublicTypedefClasses();
+-
+-        for (CompilationUnitDeclaration unit : units) {
+-            analyze(unit);
+-        }
+-    }
+-
+-    public void removeTypedefClasses() {
+-        if (classDir != null && typedefClasses != null && !typedefClasses.isEmpty()) {
+-            boolean quiet = false;
+-            boolean verbose = false;
+-            boolean dryRun = false;
+-            //noinspection ConstantConditions
+-            TypedefRemover remover = new TypedefRemover(this, quiet, verbose, dryRun);
+-            remover.remove(classDir, typedefClasses);
+-        }
+-    }
+-
+-    public void export(@Nullable File annotationsZip, @Nullable File proguardCfg) {
+-        if (proguardCfg != null) {
+-            if (keepItems.isEmpty()) {
+-                if (proguardCfg.exists()) {
+-                    //noinspection ResultOfMethodCallIgnored
+-                    proguardCfg.delete();
+-                }
+-            } else if (writeKeepRules(proguardCfg)) {
+-                info("ProGuard keep rules written to " + proguardCfg);
+-            }
+-        }
+-
+-        if (annotationsZip != null) {
+-            if (itemMap.isEmpty()) {
+-                if (annotationsZip.exists()) {
+-                    //noinspection ResultOfMethodCallIgnored
+-                    annotationsZip.delete();
+-                }
+-            } else if (writeExternalAnnotations(annotationsZip)) {
+-                writeStats();
+-                info("Annotations written to " + annotationsZip);
+-            }
+-        }
+-
+-    }
+-
+-    public void writeStats() {
+-        if (!displayInfo) {
+-            return;
+-        }
+-
+-        if (!stats.isEmpty()) {
+-            List<String> annotations = Lists.newArrayList(stats.keySet());
+-            Collections.sort(annotations, new Comparator<String>() {
+-                @Override
+-                public int compare(String s1, String s2) {
+-                    int frequency1 = stats.get(s1);
+-                    int frequency2 = stats.get(s2);
+-                    int delta = frequency2 - frequency1;
+-                    if (delta != 0) {
+-                        return delta;
+-                    }
+-                    return s1.compareTo(s2);
+-                }
+-            });
+-            Map<String,String> fqnToName = Maps.newHashMap();
+-            int max = 0;
+-            int count = 0;
+-            for (String fqn : annotations) {
+-                String name = fqn.substring(fqn.lastIndexOf('.') + 1);
+-                fqnToName.put(fqn, name);
+-                max = Math.max(max, name.length());
+-                count += stats.get(fqn);
+-            }
+-
+-            StringBuilder sb = new StringBuilder(200);
+-            sb.append("Extracted ").append(count).append(" Annotations:");
+-            for (String fqn : annotations) {
+-                sb.append('\n');
+-                String name = fqnToName.get(fqn);
+-                for (int i = 0, n = max - name.length() + 1; i < n; i++) {
+-                    sb.append(' ');
+-                }
+-                sb.append('@');
+-                sb.append(name);
+-                sb.append(':').append(' ');
+-                sb.append(Integer.toString(stats.get(fqn)));
+-            }
+-            if (sb.length() > 0) {
+-                info(sb.toString());
+-            }
+-        }
+-
+-        if (filteredCount > 0) {
+-            info(filteredCount + " of these were filtered out (not in API database file)");
+-        }
+-        if (mergedCount > 0) {
+-            info(mergedCount + " additional annotations were merged in");
+-        }
+-    }
+-
+-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+-    void info(final String message) {
+-        if (displayInfo) {
+-            System.out.println(message);
+-        }
+-    }
+-
+-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+-    static void error(String message) {
+-        System.err.println("Error: " + message);
+-    }
+-
+-    @SuppressWarnings("UseOfSystemOutOrSystemErr")
+-    static void warning(String message) {
+-        System.out.println("Warning: " + message);
+-    }
+-
+-    private void analyze(CompilationUnitDeclaration unit) {
+-        if (processedFiles.contains(unit)) {
+-            // The code to process all roots seems to hit some of the same classes
+-            // repeatedly... so filter these out manually
+-            return;
+-        }
+-        processedFiles.add(unit);
+-
+-        AnnotationVisitor visitor = new AnnotationVisitor();
+-        unit.traverse(visitor, unit.scope);
+-    }
+-
+-    @Nullable
+-    private static ClassScope findClassScope(Scope scope) {
+-        while (scope != null) {
+-            if (scope instanceof ClassScope) {
+-                return (ClassScope)scope;
+-            }
+-            scope = scope.parent;
+-        }
+-
+-        return null;
+-    }
+-
+-    @Nullable
+-    static String getFqn(@NonNull Annotation annotation) {
+-        if (annotation.resolvedType != null) {
+-            return new String(annotation.resolvedType.readableName());
+-        }
+-        return null;
+-    }
+-
+-    @Nullable
+-    private static String getFqn(@NonNull ClassScope scope) {
+-        TypeDeclaration typeDeclaration = scope.referenceType();
+-        if (typeDeclaration != null && typeDeclaration.binding != null) {
+-            return new String(typeDeclaration.binding.readableName());
+-        }
+-        return null;
+-    }
+-
+-    @Nullable
+-    private static String getFqn(@NonNull MethodScope scope) {
+-        ClassScope classScope = findClassScope(scope);
+-        if (classScope != null) {
+-            return getFqn(classScope);
+-        }
+-
+-        return null;
+-    }
+-
+-    @Nullable
+-    private static String getFqn(@NonNull BlockScope scope) {
+-        ClassScope classScope = findClassScope(scope);
+-        if (classScope != null) {
+-            return getFqn(classScope);
+-        }
+-
+-        return null;
+-    }
+-
+-    boolean hasSourceRetention(@NonNull String fqn, @Nullable Annotation annotation) {
+-        if (sourceRetention == null) {
+-            sourceRetention = Maps.newHashMapWithExpectedSize(20);
+-            // The @IntDef and @String annotations have always had source retention,
+-            // and always must (because we can't express fully qualified field references
+-            // in a .class file.)
+-            sourceRetention.put(INT_DEF_ANNOTATION, true);
+-            sourceRetention.put(STRING_DEF_ANNOTATION, true);
+-            // The @Nullable and @NonNull annotations have always had class retention
+-            sourceRetention.put(SUPPORT_NOTNULL, false);
+-            sourceRetention.put(SUPPORT_NULLABLE, false);
+-
+-            // TODO: Look at support library statistics and put the other most
+-            // frequently referenced annotations in here statically
+-
+-            // The resource annotations vary: up until 22.0.1 they had source
+-            // retention but then switched to class retention.
+-        }
+-
+-        Boolean source = sourceRetention.get(fqn);
+-
+-        if (source != null) {
+-            return source;
+-        }
+-
+-        if (annotation == null || annotation.type == null
+-                || annotation.type.resolvedType == null) {
+-            // Assume it's class retention: that's what nearly all annotations
+-            // currently are. (We do dynamic lookup of unknown ones to allow for
+-            // this version of the Gradle plugin to be able to work on future
+-            // versions of the support library with new annotations, where it's
+-            // possible some annotations need to use source retention.
+-            sourceRetention.put(fqn, false);
+-            return false;
+-        } else if (annotation.type.resolvedType.getAnnotations() != null) {
+-            for (AnnotationBinding binding : annotation.type.resolvedType.getAnnotations()) {
+-                if (hasSourceRetention(binding)) {
+-                    sourceRetention.put(fqn, true);
+-                    return true;
+-                }
+-            }
+-        }
+-
+-        sourceRetention.put(fqn, false);
+-        return false;
+-    }
+-
+-    @SuppressWarnings("unused")
+-    static boolean hasSourceRetention(@NonNull AnnotationBinding a) {
+-        if (new String(a.getAnnotationType().readableName()).equals("java.lang.annotation.Retention")) {
+-            ElementValuePair[] pairs = a.getElementValuePairs();
+-            if (pairs == null || pairs.length != 1) {
+-                warning("Expected exactly one parameter passed to @Retention");
+-                return false;
+-            }
+-            ElementValuePair pair = pairs[0];
+-            Object value = pair.getValue();
+-            if (value instanceof FieldBinding) {
+-                FieldBinding field = (FieldBinding) value;
+-                if ("SOURCE".equals(new String(field.readableName()))) {
+-                    return true;
+-                }
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    @SuppressWarnings("unused")
+-    static boolean hasSourceRetention(@NonNull Annotation[] annotations) {
+-        for (Annotation annotation : annotations) {
+-            String typeName = Extractor.getFqn(annotation);
+-            if ("java.lang.annotation.Retention".equals(typeName)) {
+-                MemberValuePair[] pairs = annotation.memberValuePairs();
+-                if (pairs == null || pairs.length != 1) {
+-                    warning("Expected exactly one parameter passed to @Retention");
+-                    return false;
+-                }
+-                MemberValuePair pair = pairs[0];
+-                Expression value = pair.value;
+-                if (value instanceof NameReference) {
+-                    NameReference reference = (NameReference) value;
+-                    Binding binding = reference.binding;
+-                    if (binding != null) {
+-                        if (binding instanceof FieldBinding) {
+-                            FieldBinding fb = (FieldBinding) binding;
+-                            if ("SOURCE".equals(new String(fb.name)) &&
+-                                    "java.lang.annotation.RetentionPolicy".equals(
+-                                            new String(fb.declaringClass.readableName()))) {
+-                                return true;
+-                            }
+-                        }
+-                    }
+-                }
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    private void addAnnotations(@Nullable Annotation[] annotations, @NonNull Item item) {
+-        if (annotations != null) {
+-            for (Annotation annotation : annotations) {
+-                if (isRelevantAnnotation(annotation)) {
+-                    String fqn = getFqn(annotation);
+-                    if (SUPPORT_KEEP.equals(fqn)) {
+-                        // Put keep rules in a different place; we don't want to write
+-                        // these out into the external annotations database, they go
+-                        // into a special proguard file
+-                        keepItems.add(item);
+-                    } else {
+-                        addAnnotation(annotation, fqn, item.annotations);
+-                    }
+-                }
+-            }
+-        }
+-    }
+-
+-    private void addAnnotation(@NonNull Annotation annotation, @Nullable String fqn,
+-            @NonNull List<AnnotationData> list) {
+-        if (fqn == null) {
+-            return;
+-        }
+-
+-        if (fqn.equals(ANDROID_NULLABLE) || fqn.equals(SUPPORT_NULLABLE)) {
+-            recordStats(fqn);
+-            list.add(new AnnotationData(SUPPORT_NULLABLE));
+-            return;
+-        }
+-
+-        if (fqn.equals(ANDROID_NOTNULL) || fqn.equals(SUPPORT_NOTNULL)) {
+-            recordStats(fqn);
+-            list.add(new AnnotationData(SUPPORT_NOTNULL));
+-            return;
+-        }
+-
+-        if (fqn.startsWith(SUPPORT_ANNOTATIONS_PREFIX)
+-                && fqn.endsWith(RESOURCE_TYPE_ANNOTATIONS_SUFFIX)) {
+-            recordStats(fqn);
+-            list.add(new AnnotationData(fqn));
+-            return;
+-        }
+-
+-        if (fqn.startsWith(ANDROID_ANNOTATIONS_PREFIX)) {
+-            // System annotations: translate to support library annotations
+-            if (fqn.endsWith(RESOURCE_TYPE_ANNOTATIONS_SUFFIX)) {
+-                // Translate e.g. android.annotation.DrawableRes to
+-                //    android.support.annotation.DrawableRes
+-                String resAnnotation = SUPPORT_ANNOTATIONS_PREFIX +
+-                        fqn.substring(ANDROID_ANNOTATIONS_PREFIX.length());
+-                if (!includeClassRetentionAnnotations
+-                        && !hasSourceRetention(resAnnotation, null)) {
+-                    return;
+-                }
+-                recordStats(resAnnotation);
+-                list.add(new AnnotationData(resAnnotation));
+-                return;
+-            } else if (isRelevantFrameworkAnnotation(fqn)) {
+-                // Translate other android.annotation annotations into corresponding
+-                // support annotations
+-                String supportAnnotation = SUPPORT_ANNOTATIONS_PREFIX +
+-                        fqn.substring(ANDROID_ANNOTATIONS_PREFIX.length());
+-                if (!includeClassRetentionAnnotations
+-                        && !hasSourceRetention(supportAnnotation, null)) {
+-                    return;
+-                }
+-                recordStats(supportAnnotation);
+-                list.add(createData(supportAnnotation, annotation));
+-            }
+-        }
+-
+-        if (fqn.startsWith(SUPPORT_ANNOTATIONS_PREFIX)) {
+-            recordStats(fqn);
+-            list.add(createData(fqn, annotation));
+-            return;
+-        }
+-
+-        if (isMagicConstant(fqn)) {
+-            List<AnnotationData> indirect = types.get(fqn);
+-            if (indirect != null) {
+-                list.addAll(indirect);
+-            }
+-        }
+-    }
+-
+-    private void recordStats(String fqn) {
+-        Integer count = stats.get(fqn);
+-        if (count == null) {
+-            count = 0;
+-        }
+-        stats.put(fqn, count + 1);
+-    }
+-
+-    private boolean hasRelevantAnnotations(@Nullable Annotation[] annotations) {
+-        if (annotations == null) {
+-            return false;
+-        }
+-
+-        for (Annotation annotation : annotations) {
+-            if (isRelevantAnnotation(annotation)) {
+-                return true;
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    private boolean isRelevantAnnotation(@NonNull Annotation annotation) {
+-        String fqn = getFqn(annotation);
+-        if (fqn == null || fqn.startsWith("java.lang.")) {
+-            return false;
+-        }
+-        if (fqn.startsWith(SUPPORT_ANNOTATIONS_PREFIX)) {
+-            if (fqn.equals(SUPPORT_KEEP)) {
+-                return true; // even with class file retention we want to process these
+-            }
+-
+-            //noinspection PointlessBooleanExpression,ConstantConditions,RedundantIfStatement
+-            if (!includeClassRetentionAnnotations && !hasSourceRetention(fqn, annotation)) {
+-                return false;
+-            }
+-
+-            return true;
+-        } else if (fqn.startsWith(ANDROID_ANNOTATIONS_PREFIX)) {
+-            return isRelevantFrameworkAnnotation(fqn);
+-        }
+-        if (fqn.equals(ANDROID_NULLABLE) || fqn.equals(ANDROID_NOTNULL)
+-                || isMagicConstant(fqn)) {
+-            return true;
+-        } else if (fqn.equals(IDEA_CONTRACT)) {
+-            return true;
+-        }
+-
+-        return false;
+-    }
+-
+-    private static boolean isRelevantFrameworkAnnotation(@NonNull String fqn) {
+-        return fqn.startsWith(ANDROID_ANNOTATIONS_PREFIX)
+-                && !fqn.endsWith(".Widget")
+-                && !fqn.endsWith(".TargetApi")
+-                && !fqn.endsWith(".SystemApi")
+-                && !fqn.endsWith(".SuppressLint")
+-                && !fqn.endsWith(".SdkConstant");
+-    }
+-
+-    boolean isMagicConstant(String typeName) {
+-        if (irrelevantAnnotations.contains(typeName)
+-                || typeName.startsWith("java.lang.")) { // @Override, @SuppressWarnings, etc.
+-            return false;
+-        }
+-        if (types.containsKey(typeName) ||
+-                typeName.equals(INT_DEF_ANNOTATION) ||
+-                typeName.equals(STRING_DEF_ANNOTATION) ||
+-                typeName.equals(INT_RANGE_ANNOTATION) ||
+-                typeName.equals(ANDROID_INT_RANGE) ||
+-                typeName.equals(ANDROID_INT_DEF) ||
+-                typeName.equals(ANDROID_STRING_DEF)) {
+-            return true;
+-        }
+-
+-        List<Annotation> typeDefs = typedefs.get(typeName);
+-        // We only support a single level of IntDef type annotations, not arbitrary nesting
+-        if (typeDefs != null) {
+-            boolean match = false;
+-            for (Annotation typeDef : typeDefs) {
+-                String fqn = getFqn(typeDef);
+-                if (isNestedAnnotation(fqn)) {
+-                    List<AnnotationData> list = types.get(typeName);
+-                    if (list == null) {
+-                        list = new ArrayList<AnnotationData>(2);
+-                        types.put(typeName, list);
+-                    }
+-                    addAnnotation(typeDef, fqn, list);
+-                    match = true;
+-                }
+-            }
+-
+-            return match;
+-        }
+-
+-        irrelevantAnnotations.add(typeName);
+-
+-        return false;
+-    }
+-
+-    static boolean isNestedAnnotation(@Nullable String fqn) {
+-        return (fqn != null &&
+-                (fqn.equals(INT_DEF_ANNOTATION) ||
+-                        fqn.equals(STRING_DEF_ANNOTATION) ||
+-                        fqn.equals(REQUIRES_PERMISSION) ||
+-                        fqn.equals(ANDROID_REQUIRES_PERMISSION) ||
+-                        fqn.equals(INT_RANGE_ANNOTATION) ||
+-                        fqn.equals(ANDROID_INT_RANGE) ||
+-                        fqn.equals(ANDROID_INT_DEF) ||
+-                        fqn.equals(ANDROID_STRING_DEF)));
+-    }
+-
+-    private boolean writeKeepRules(@NonNull File proguardCfg) {
+-        if (!keepItems.isEmpty()) {
+-            try {
+-                Writer writer = new BufferedWriter(new FileWriter(proguardCfg));
+-                try {
+-                    Collections.sort(keepItems);
+-                    for (Item item : keepItems) {
+-                        writer.write(item.getKeepRule());
+-                        writer.write('\n');
+-                    }
+-                } finally {
+-                    writer.close();
+-                }
+-            } catch (IOException ioe) {
+-                error(ioe.toString());
+-                return true;
+-            }
+-
+-            // Now that we've handled these items, remove them from the list
+-            // such that we don't accidentally also emit them into the annotations.zip
+-            // file, where they are not needed
+-            for (Item item : keepItems) {
+-                removeItem(item.getQualifiedClassName(), item);
+-            }
+-        } else if (proguardCfg.exists()) {
+-            //noinspection ResultOfMethodCallIgnored
+-            proguardCfg.delete();
+-        }
+-        return false;
+-    }
+-
+-    private boolean writeExternalAnnotations(@NonNull File annotationsZip) {
+-        try {
+-            FileOutputStream fileOutputStream = new FileOutputStream(annotationsZip);
+-            JarOutputStream zos = new JarOutputStream(fileOutputStream);
+-
+-            try {
+-                // TODO: Extract to share with keep rules
+-                List<String> sortedPackages = new ArrayList<String>(itemMap.keySet());
+-                Collections.sort(sortedPackages);
+-                for (String pkg : sortedPackages) {
+-                    // Note: Using / rather than File.separator: jar lib requires it
+-                    String name = pkg.replace('.', '/') + "/annotations.xml";
+-
+-                    JarEntry outEntry = new JarEntry(name);
+-                    zos.putNextEntry(outEntry);
+-
+-                    StringWriter stringWriter = new StringWriter(1000);
+-                    PrintWriter writer = new PrintWriter(stringWriter);
+-                    try {
+-                        writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
+-                                "<root>");
+-
+-                        Map<String, List<Item>> classMap = itemMap.get(pkg);
+-                        List<String> classes = new ArrayList<String>(classMap.keySet());
+-                        Collections.sort(classes);
+-                        for (String cls : classes) {
+-                            List<Item> items = classMap.get(cls);
+-                            Collections.sort(items);
+-                            for (Item item : items) {
+-                                item.write(writer);
+-                            }
+-                        }
+-
+-                        writer.println("</root>\n");
+-                        writer.close();
+-                        String xml = stringWriter.toString();
+-
+-                        // Validate
+-                        if (assertionsEnabled()) {
+-                            Document document = checkDocument(pkg, xml, false);
+-                            if (document == null) {
+-                                error("Could not parse XML document back in for entry " + name
+-                                        + ": invalid XML?\n\"\"\"\n" + xml + "\n\"\"\"\n");
+-                                return false;
+-                            }
+-                        }
+-                        byte[] bytes = xml.getBytes(Charsets.UTF_8);
+-                        zos.write(bytes);
+-                        zos.closeEntry();
+-                    } finally {
+-                        writer.close();
+-                    }
+-                }
+-            } finally {
+-                zos.flush();
+-                zos.close();
+-            }
+-        } catch (IOException ioe) {
+-            error(ioe.toString());
+-            return false;
+-        }
+-
+-        return true;
+-    }
+-
+-    private void addItem(@NonNull String fqn, @NonNull Item item) {
+-        // Not part of the API?
+-        if (apiFilter != null && item.isFiltered(apiFilter)) {
+-            if (isListIgnored()) {
+-                info("Skipping API because it is not part of the API file: " + item);
+-            }
+-
+-            filteredCount++;
+-            return;
+-        }
+-
+-        String pkg = getPackage(fqn);
+-        Map<String, List<Item>> classMap = itemMap.get(pkg);
+-        if (classMap == null) {
+-            classMap = Maps.newHashMapWithExpectedSize(100);
+-            itemMap.put(pkg, classMap);
+-        }
+-        List<Item> items = classMap.get(fqn);
+-        if (items == null) {
+-            items = Lists.newArrayList();
+-            classMap.put(fqn, items);
+-        }
+-
+-        items.add(item);
+-    }
+-
+-    private void removeItem(@NonNull String classFqn, @NonNull Item item) {
+-        String pkg = getPackage(classFqn);
+-        Map<String, List<Item>> classMap = itemMap.get(pkg);
+-        if (classMap != null) {
+-            List<Item> items = classMap.get(classFqn);
+-            if (items != null) {
+-                items.remove(item);
+-                if (items.isEmpty()) {
+-                    classMap.remove(classFqn);
+-                    if (classMap.isEmpty()) {
+-                        itemMap.remove(pkg);
+-                    }
+-                }
+-            }
+-        }
+-    }
+-
+-    @Nullable
+-    private Item findItem(@NonNull String fqn, @NonNull Item item) {
+-        String pkg = getPackage(fqn);
+-        Map<String, List<Item>> classMap = itemMap.get(pkg);
+-        if (classMap == null) {
+-            return null;
+-        }
+-        List<Item> items = classMap.get(fqn);
+-        if (items == null) {
+-            return null;
+-        }
+-        for (Item existing : items) {
+-            if (existing.equals(item)) {
+-                return existing;
+-            }
+-        }
+-
+-        return null;
+-    }
+-
+-    @Nullable
+-    private static Document checkDocument(@NonNull String pkg, @NonNull String xml,
+-            boolean namespaceAware) {
+-        try {
+-            return XmlUtils.parseDocument(xml, namespaceAware);
+-        } catch (SAXException sax) {
+-            warning("Failed to parse document for package " + pkg + ": " + sax.toString());
+-        } catch (Exception e) {
+-            // pass
+-            // This method is deliberately silent; will return null
+-        }
+-
+-        return null;
+-    }
+-
+-    public void mergeExisting(@NonNull File file) {
+-        if (file.isDirectory()) {
+-            File[] files = file.listFiles();
+-            if (files != null) {
+-                for (File child : files) {
+-                    mergeExisting(child);
+-                }
+-            }
+-        } else if (file.isFile()) {
+-            if (file.getPath().endsWith(DOT_JAR)) {
+-                mergeFromJar(file);
+-            } else if (file.getPath().endsWith(DOT_XML)) {
+-                try {
+-                    String xml = Files.toString(file, Charsets.UTF_8);
+-                    mergeAnnotationsXml(file.getPath(), xml);
+-                } catch (IOException e) {
+-                    error("Aborting: I/O problem during transform: " + e.toString());
+-                }
+-            }
+-        }
+-    }
+-
+-    private void mergeFromJar(@NonNull File jar) {
+-        // Reads in an existing annotations jar and merges in entries found there
+-        // with the annotations analyzed from source.
+-        JarInputStream zis = null;
+-        try {
+-            @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+-            FileInputStream fis = new FileInputStream(jar);
+-            zis = new JarInputStream(fis);
+-            ZipEntry entry = zis.getNextEntry();
+-            while (entry != null) {
+-                if (entry.getName().endsWith(".xml")) {
+-                    byte[] bytes = ByteStreams.toByteArray(zis);
+-                    String xml = new String(bytes, Charsets.UTF_8);
+-                    mergeAnnotationsXml(jar.getPath() + ": " + entry, xml);
+-                }
+-                entry = zis.getNextEntry();
+-            }
+-        } catch (IOException e) {
+-            error("Aborting: I/O problem during transform: " + e.toString());
+-        } finally {
+-            //noinspection deprecation
+-            try {
+-                Closeables.close(zis, true /* swallowIOException */);
+-            } catch (IOException e) {
+-                // cannot happen
+-            }
+-        }
+-    }
+-
+-    private void mergeAnnotationsXml(@NonNull String path, @NonNull String xml) {
+-        try {
+-            Document document = XmlUtils.parseDocument(xml, false);
+-            mergeDocument(document);
+-        } catch (Exception e) {
+-            String message = "Failed to merge " + path + ": " + e.toString();
+-            if (e instanceof SAXParseException) {
+-                SAXParseException spe = (SAXParseException)e;
+-                message = "Line " + spe.getLineNumber() + ":" + spe.getColumnNumber() + ": " + message;
+-            }
+-            error(message);
+-            if (!(e instanceof IOException)) {
+-                e.printStackTrace();
+-            }
+-        }
+-    }
+-
+-    private void mergeDocument(@NonNull Document document) {
+-        @SuppressWarnings("SpellCheckingInspection")
+-        final Pattern XML_SIGNATURE = Pattern.compile(
+-                // Class (FieldName | Type? Name(ArgList) Argnum?)
+-                //"(\\S+) (\\S+|(.*)\\s+(\\S+)\\((.*)\\)( \\d+)?)");
+-                "(\\S+) (\\S+|((.*)\\s+)?(\\S+)\\((.*)\\)( \\d+)?)");
+-
+-        Element root = document.getDocumentElement();
+-        String rootTag = root.getTagName();
+-        assert rootTag.equals("root") : rootTag;
+-
+-        for (Element item : getChildren(root)) {
+-            String signature = item.getAttribute(ATTR_NAME);
+-            if (signature == null || signature.equals("null")) {
+-                continue; // malformed item
+-            }
+-
+-            if (!hasRelevantAnnotations(item)) {
+-                continue;
+-            }
+-
+-            signature = unescapeXml(signature);
+-            if (signature.equals("java.util.Arrays void sort(T[], java.util.Comparator<?) 0")) {
+-                // Incorrect metadata (unbalanced <>'s)
+-                // See IDEA-137385
+-                signature = "java.util.Arrays void sort(T[], java.util.Comparator<?>) 0";
+-            }
+-
+-            Matcher matcher = XML_SIGNATURE.matcher(signature);
+-            if (matcher.matches()) {
+-                String containingClass = matcher.group(1);
+-                if (containingClass == null) {
+-                    warning("Could not find class for " + signature);
+-                }
+-                String methodName = matcher.group(5);
+-                if (methodName != null) {
+-                    String type = matcher.group(4);
+-                    boolean isConstructor = type == null;
+-                    String parameters = matcher.group(6);
+-                    mergeMethodOrParameter(item, matcher, containingClass, methodName, type,
+-                            isConstructor, parameters);
+-                } else {
+-                    String fieldName = matcher.group(2);
+-                    mergeField(item, containingClass, fieldName);
+-                }
+-            } else {
+-                if (signature.indexOf(' ') != -1 || signature.indexOf('.') == -1) {
+-                    warning("No merge match for signature " + signature);
+-                } // else: probably just a class signature, e.g. for @NonNls
+-            }
+-        }
+-    }
+-
+-    @NonNull
+-    private static String unescapeXml(@NonNull String escaped) {
+-        String workingString = escaped.replace(QUOT_ENTITY, "\"");
+-        workingString = workingString.replace(LT_ENTITY, "<");
+-        workingString = workingString.replace(GT_ENTITY, ">");
+-        workingString = workingString.replace(APOS_ENTITY, "'");
+-        workingString = workingString.replace(AMP_ENTITY, "&");
+-
+-        return workingString;
+-    }
+-
+-    @NonNull
+-    private static String escapeXml(@NonNull String unescaped) {
+-        return XmlEscapers.xmlAttributeEscaper().escape(unescaped);
+-    }
+-
+-    private void mergeField(Element item, String containingClass, String fieldName) {
+-        if (apiFilter != null &&
+-                !apiFilter.hasField(containingClass, fieldName)) {
+-            if (isListIgnored()) {
+-                info("Skipping imported element because it is not part of the API file: "
+-                        + containingClass + "#" + fieldName);
+-            }
+-            filteredCount++;
+-        } else {
+-            FieldItem fieldItem = new FieldItem(containingClass, ClassKind.CLASS, fieldName, null);
+-            Item existing = findItem(containingClass, fieldItem);
+-            if (existing != null) {
+-                mergedCount += mergeAnnotations(item, existing);
+-            } else {
+-                addItem(containingClass, fieldItem);
+-                mergedCount += addAnnotations(item, fieldItem);
+-            }
+-        }
+-    }
+-
+-    private void mergeMethodOrParameter(Element item, Matcher matcher, String containingClass,
+-            String methodName, String type, boolean constructor, String parameters) {
+-        parameters = fixParameterString(parameters);
+-
+-        if (apiFilter != null &&
+-                !apiFilter.hasMethod(containingClass, methodName, parameters)) {
+-            if (isListIgnored()) {
+-                info("Skipping imported element because it is not part of the API file: "
+-                        + containingClass + "#" + methodName + "(" + parameters + ")");
+-            }
+-            filteredCount++;
+-            return;
+-        }
+-
+-        String argNum = matcher.group(7);
+-        if (argNum != null) {
+-            argNum = argNum.trim();
+-            ParameterItem parameterItem = new ParameterItem(containingClass, ClassKind.CLASS, type,
+-                    methodName, parameters, constructor, argNum);
+-            Item existing = findItem(containingClass, parameterItem);
+-
+-            if ("java.util.Calendar".equals(containingClass) && "set".equals(methodName)
+-                    && Integer.parseInt(argNum) > 0) {
+-                // Skip the metadata for Calendar.set(int, int, int+); see
+-                // https://code.google.com/p/android/issues/detail?id=73982
+-                return;
+-            }
+-
+-            if (existing != null) {
+-                mergedCount += mergeAnnotations(item, existing);
+-            } else {
+-                addItem(containingClass, parameterItem);
+-                mergedCount += addAnnotations(item, parameterItem);
+-            }
+-        } else {
+-            MethodItem methodItem = new MethodItem(containingClass, ClassKind.CLASS, type,
+-                    methodName, parameters, constructor);
+-            Item existing = findItem(containingClass, methodItem);
+-            if (existing != null) {
+-                mergedCount += mergeAnnotations(item, existing);
+-            } else {
+-                addItem(containingClass, methodItem);
+-                mergedCount += addAnnotations(item, methodItem);
+-            }
+-        }
+-    }
+-
+-    // The parameter declaration used in XML files should not have duplicated spaces,
+-    // and there should be no space after commas (we can't however strip out all spaces,
+-    // since for example the spaces around the "extends" keyword needs to be there in
+-    // types like Map<String,? extends Number>
+-    private static String fixParameterString(String parameters) {
+-        return parameters.replace("  ", " ").replace(", ", ",");
+-    }
+-
+-    private boolean hasRelevantAnnotations(Element item) {
+-        for (Element annotationElement : getChildren(item)) {
+-            if (isRelevantAnnotation(annotationElement)) {
+-                return true;
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    private boolean isRelevantAnnotation(Element annotationElement) {
+-        AnnotationData annotation = createAnnotation(annotationElement);
+-        if (annotation == null) {
+-            // Unsupported annotation in import
+-            return false;
+-        }
+-        if (isNullable(annotation.name) || isNonNull(annotation.name)
+-                || annotation.name.startsWith(ANDROID_ANNOTATIONS_PREFIX)
+-                || annotation.name.startsWith(SUPPORT_ANNOTATIONS_PREFIX)) {
+-            return true;
+-        } else if (annotation.name.equals(IDEA_CONTRACT)) {
+-            return true;
+-        } else if (annotation.name.equals(IDEA_NON_NLS)) {
+-            return false;
+-        } else {
+-            if (!ignoredAnnotations.contains(annotation.name)) {
+-                ignoredAnnotations.add(annotation.name);
+-                if (isListIgnored()) {
+-                    info("(Ignoring merge annotation " + annotation.name + ")");
+-                }
+-            }
+-        }
+-
+-        return false;
+-    }
+-
+-    @NonNull
+-    private static List<Element> getChildren(@NonNull Element element) {
+-        NodeList itemList = element.getChildNodes();
+-        int length = itemList.getLength();
+-        List<Element> result = new ArrayList<Element>(Math.max(5, length / 2 + 1));
+-        for (int i = 0; i < length; i++) {
+-            Node node = itemList.item(i);
+-            if (node.getNodeType() != Node.ELEMENT_NODE) {
+-                continue;
+-            }
+-
+-            result.add((Element) node);
+-        }
+-
+-        return result;
+-    }
+-
+-    private int addAnnotations(Element itemElement, Item item) {
+-        int count = 0;
+-        for (Element annotationElement : getChildren(itemElement)) {
+-            if (!isRelevantAnnotation(annotationElement)) {
+-                continue;
+-            }
+-            AnnotationData annotation = createAnnotation(annotationElement);
+-            item.annotations.add(annotation);
+-            count++;
+-        }
+-        return count;
+-    }
+-
+-    private int mergeAnnotations(Element itemElement, Item item) {
+-        int count = 0;
+-        loop:
+-        for (Element annotationElement : getChildren(itemElement)) {
+-            if (!isRelevantAnnotation(annotationElement)) {
+-                continue;
+-            }
+-            AnnotationData annotation = createAnnotation(annotationElement);
+-            if (annotation == null) {
+-                continue;
+-            }
+-            boolean haveNullable = false;
+-            boolean haveNotNull = false;
+-            for (AnnotationData existing : item.annotations) {
+-                if (isNonNull(existing.name)) {
+-                    haveNotNull = true;
+-                }
+-                if (isNullable(existing.name)) {
+-                    haveNullable = true;
+-                }
+-                if (existing.equals(annotation)) {
+-                    continue loop;
+-                }
+-            }
+-
+-            // Make sure we don't have a conflict between nullable and not nullable
+-            if (isNonNull(annotation.name) && haveNullable ||
+-                    isNullable(annotation.name) && haveNotNull) {
+-                warning("Found both @Nullable and @NonNull after import for " + item);
+-                continue;
+-            }
+-
+-            item.annotations.add(annotation);
+-            count++;
+-        }
+-
+-        return count;
+-    }
+-
+-    private static boolean isNonNull(String name) {
+-        return name.equals(IDEA_NOTNULL)
+-                || name.equals(ANDROID_NOTNULL)
+-                || name.equals(SUPPORT_NOTNULL);
+-    }
+-
+-    private static boolean isNullable(String name) {
+-        return name.equals(IDEA_NULLABLE)
+-                || name.equals(ANDROID_NULLABLE)
+-                || name.equals(SUPPORT_NULLABLE);
+-    }
+-
+-    private AnnotationData createAnnotation(Element annotationElement) {
+-        String tagName = annotationElement.getTagName();
+-        assert tagName.equals("annotation") : tagName;
+-        String name = annotationElement.getAttribute(ATTR_NAME);
+-        assert name != null && !name.isEmpty();
+-        AnnotationData annotation;
+-        if (IDEA_MAGIC.equals(name)) {
+-            List<Element> children = getChildren(annotationElement);
+-            assert children.size() == 1 : children.size();
+-            Element valueElement = children.get(0);
+-            String valName = valueElement.getAttribute(ATTR_NAME);
+-            String value = valueElement.getAttribute(ATTR_VAL);
+-            boolean flagsFromClass = valName.equals("flagsFromClass");
+-            boolean flag = valName.equals("flags") || flagsFromClass;
+-            if (valName.equals("valuesFromClass") || flagsFromClass) {
+-                // Not supported
+-                boolean found = false;
+-                if (value.endsWith(DOT_CLASS)) {
+-                    String clsName = value.substring(0, value.length() - DOT_CLASS.length());
+-                    StringBuilder sb = new StringBuilder();
+-                    sb.append('{');
+-
+-
+-                    Field[] reflectionFields = null;
+-                    try {
+-                        Class<?> cls = Class.forName(clsName);
+-                        reflectionFields = cls.getDeclaredFields();
+-                    } catch (Exception ignore) {
+-                        // Class not available: not a problem. We'll rely on API filter.
+-                        // It's mainly used for sorting anyway.
+-                    }
+-                    if (apiFilter != null) {
+-                        // Search in API database
+-                        Set<String> fields = apiFilter.getDeclaredIntFields(clsName);
+-                        if ("java.util.zip.ZipEntry".equals(clsName)) {
+-                            // The metadata says valuesFromClass ZipEntry, and unfortunately
+-                            // that class implements ZipConstants and therefore imports a large
+-                            // number of irrelevant constants that aren't valid here. Instead,
+-                            // only allow these two:
+-                            fields = Sets.newHashSet("STORED", "DEFLATED");
+-                        }
+-
+-                        if (fields != null) {
+-                            List<String> sorted = Lists.newArrayList(fields);
+-                            Collections.sort(sorted);
+-                            if (reflectionFields != null) {
+-                                final Map<String,Integer> rank = Maps.newHashMap();
+-                                for (int i = 0, n = sorted.size(); i < n; i++) {
+-                                    rank.put(sorted.get(i), reflectionFields.length + i);
+-
+-                                }
+-                                for (int i = 0, n = reflectionFields.length; i < n; i++) {
+-                                    rank.put(reflectionFields[i].getName(), i);
+-                                }
+-                                Collections.sort(sorted, new Comparator<String>() {
+-                                    @Override
+-                                    public int compare(String o1, String o2) {
+-                                        int rank1 = rank.get(o1);
+-                                        int rank2 = rank.get(o2);
+-                                        int delta = rank1 - rank2;
+-                                        if (delta != 0) {
+-                                            return delta;
+-                                        }
+-                                        return o1.compareTo(o2);
+-                                    }
+-                                });
+-                            }
+-                            boolean first = true;
+-                            for (String field : sorted) {
+-                                if (first) {
+-                                    first = false;
+-                                } else {
+-                                    sb.append(',').append(' ');
+-                                }
+-                                sb.append(clsName).append('.').append(field);
+-                            }
+-                            found = true;
+-                        }
+-                    }
+-                    // Attempt to sort in reflection order
+-                    if (!found && reflectionFields != null && (apiFilter == null || apiFilter.hasClass(clsName))) {
+-                        // Attempt with reflection
+-                        boolean first = true;
+-                        for (Field field : reflectionFields) {
+-                            if (field.getType() == Integer.TYPE ||
+-                                    field.getType() == int.class) {
+-                                if (first) {
+-                                    first = false;
+-                                } else {
+-                                    sb.append(',').append(' ');
+-                                }
+-                                sb.append(clsName).append('.').append(field.getName());
+-                            }
+-                        }
+-                    }
+-                    sb.append('}');
+-                    value = sb.toString();
+-                    if (sb.length() > 2) { // 2: { }
+-                        found = true;
+-                    }
+-                }
+-
+-                if (!found) {
+-                    return null;
+-                }
+-            }
+-
+-            //noinspection VariableNotUsedInsideIf
+-            if (apiFilter != null) {
+-                value = removeFiltered(value);
+-                while (value.contains(", ,")) {
+-                    value = value.replace(", ,",",");
+-                }
+-                if (value.startsWith(", ")) {
+-                    value = value.substring(2);
+-                }
+-            }
+-
+-            annotation = new AnnotationData(
+-                    valName.equals("stringValues") ? STRING_DEF_ANNOTATION : INT_DEF_ANNOTATION,
+-                    new String[] {
+-                            TYPE_DEF_VALUE_ATTRIBUTE, value,
+-                            flag ? TYPE_DEF_FLAG_ATTRIBUTE : null, flag ? VALUE_TRUE : null });
+-        } else if (STRING_DEF_ANNOTATION.equals(name) || ANDROID_STRING_DEF.equals(name) ||
+-                INT_DEF_ANNOTATION.equals(name) || ANDROID_INT_DEF.equals(name)) {
+-            List<Element> children = getChildren(annotationElement);
+-            Element valueElement = children.get(0);
+-            String valName = valueElement.getAttribute(ATTR_NAME);
+-            assert TYPE_DEF_VALUE_ATTRIBUTE.equals(valName);
+-            String value = valueElement.getAttribute(ATTR_VAL);
+-            boolean flag = false;
+-            if (children.size() == 2) {
+-                valueElement = children.get(1);
+-                assert TYPE_DEF_FLAG_ATTRIBUTE.equals(valueElement.getAttribute(ATTR_NAME));
+-                flag = VALUE_TRUE.equals(valueElement.getAttribute(ATTR_VAL));
+-            }
+-            boolean intDef = INT_DEF_ANNOTATION.equals(name) || ANDROID_INT_DEF.equals(name);
+-            annotation = new AnnotationData(
+-                    intDef ? INT_DEF_ANNOTATION : STRING_DEF_ANNOTATION,
+-                    new String[] { TYPE_DEF_VALUE_ATTRIBUTE, value,
+-                    flag ? TYPE_DEF_FLAG_ATTRIBUTE : null, flag ? VALUE_TRUE : null});
+-        } else if (IDEA_CONTRACT.equals(name)) {
+-            List<Element> children = getChildren(annotationElement);
+-            assert children.size() == 1 : children.size();
+-            Element valueElement = children.get(0);
+-            String value = valueElement.getAttribute(ATTR_VAL);
+-            annotation = new AnnotationData(name, new String[] { TYPE_DEF_VALUE_ATTRIBUTE, value });
+-        } else if (isNonNull(name)) {
+-            annotation = new AnnotationData(SUPPORT_NOTNULL);
+-        } else if (isNullable(name)) {
+-            //noinspection PointlessBooleanExpression,ConstantConditions
+-            if (!INCLUDE_INFERRED_NULLABLE && IDEA_NULLABLE.equals(name)) {
+-                return null;
+-            }
+-            annotation = new AnnotationData(SUPPORT_NULLABLE);
+-        } else {
+-            List<Element> children = getChildren(annotationElement);
+-            if (children.isEmpty()) {
+-                return new AnnotationData(name);
+-            }
+-            List<String> attributeStrings = Lists.newArrayList();
+-            for (Element valueElement : children) {
+-                attributeStrings.add(valueElement.getAttribute(ATTR_NAME));
+-                attributeStrings.add(valueElement.getAttribute(ATTR_VAL));
+-            }
+-            annotation = new AnnotationData(name, attributeStrings.toArray(
+-                    new String[attributeStrings.size()]));
+-        }
+-        return annotation;
+-    }
+-
+-    private String removeFiltered(String value) {
+-        assert apiFilter != null;
+-        if (value.startsWith("{")) {
+-            value = value.substring(1);
+-        }
+-        if (value.endsWith("}")) {
+-            value = value.substring(0, value.length() - 1);
+-        }
+-        value = value.trim();
+-        StringBuilder sb = new StringBuilder(value.length());
+-        sb.append('{');
+-        for (String fqn : Splitter.on(',').omitEmptyStrings().trimResults().split(value)) {
+-            fqn = unescapeXml(fqn);
+-            if (fqn.startsWith("\"")) {
+-                continue;
+-            }
+-            int index = fqn.lastIndexOf('.');
+-            String cls = fqn.substring(0, index);
+-            String field = fqn.substring(index + 1);
+-            if (apiFilter.hasField(cls, field)) {
+-                if (sb.length() > 1) { // 0: '{'
+-                    sb.append(", ");
+-                }
+-                sb.append(fqn);
+-            } else if (isListIgnored()) {
+-                info("Skipping constant from typedef because it is not part of the SDK: " + fqn);
+-            }
+-        }
+-        sb.append('}');
+-        return escapeXml(sb.toString());
+-    }
+-
+-
+-    private static String getPackage(String fqn) {
+-        // Extract package from the given fqn. Attempts to handle inner classes;
+-        // e.g.  "foo.bar.Foo.Bar will return "foo.bar".
+-        int index = 0;
+-        int last = 0;
+-        while (true) {
+-            index = fqn.indexOf('.', index);
+-            if (index == -1) {
+-                break;
+-            }
+-            last = index;
+-            if (index < fqn.length() - 1) {
+-                char next = fqn.charAt(index + 1);
+-                if (Character.isUpperCase(next)) {
+-                    break;
+-                }
+-            }
+-            index++;
+-        }
+-
+-        return fqn.substring(0, last);
+-    }
+-
+-    @SuppressWarnings("UnusedDeclaration")
+-    public void setListIgnored(boolean listIgnored) {
+-        this.listIgnored = listIgnored;
+-    }
+-
+-    public boolean isListIgnored() {
+-        return listIgnored;
+-    }
+-
+-    public AnnotationData createData(@NonNull String name, @NonNull Annotation annotation) {
+-        MemberValuePair[] pairs = annotation.memberValuePairs();
+-        if (pairs == null || pairs.length == 0) {
+-            return new AnnotationData(name);
+-        }
+-        return new AnnotationData(name, pairs);
+-    }
+-
+-    private class AnnotationData {
+-        @NonNull
+-        public final String name;
+-
+-        @Nullable
+-        public String[] attributeStrings;
+-
+-        @Nullable
+-        public MemberValuePair[] attributes;
+-
+-        private AnnotationData(@NonNull String name) {
+-            this.name = name;
+-        }
+-
+-        private AnnotationData(@NonNull String name, @Nullable MemberValuePair[] pairs) {
+-            this(name);
+-            attributes = pairs;
+-            assert attributes == null || attributes.length > 0;
+-        }
+-
+-        private AnnotationData(@NonNull String name, @Nullable String[] attributeStrings) {
+-            this(name);
+-            this.attributeStrings = attributeStrings;
+-            assert attributeStrings != null && attributeStrings.length > 0;
+-        }
+-
+-        void write(PrintWriter writer) {
+-            writer.print("    <annotation name=\"");
+-            writer.print(name);
+-
+-            if (attributes != null) {
+-                writer.print("\">");
+-                writer.println();
+-                //noinspection PointlessBooleanExpression,ConstantConditions
+-                if (attributes.length > 1 && sortAnnotations) {
+-                    // Ensure that the value attribute is written first
+-                    Arrays.sort(attributes, new Comparator<MemberValuePair>() {
+-                        private String getName(MemberValuePair pair) {
+-                            if (pair.name == null) {
+-                                return ATTR_VALUE;
+-                            } else {
+-                                return new String(pair.name);
+-                            }
+-                        }
+-
+-                        private int rank(MemberValuePair pair) {
+-                            return ATTR_VALUE.equals(getName(pair)) ? -1 : 0;
+-                        }
+-
+-                        @Override
+-                        public int compare(MemberValuePair o1, MemberValuePair o2) {
+-                            int r1 = rank(o1);
+-                            int r2 = rank(o2);
+-                            int delta = r1 - r2;
+-                            if (delta != 0) {
+-                                return delta;
+-                            }
+-                            return getName(o1).compareTo(getName(o2));
+-                        }
+-                    });
+-                }
+-
+-                MemberValuePair[] attributes = this.attributes;
+-
+-                if (attributes.length == 1
+-                        && name.startsWith(REQUIRES_PERMISSION)
+-                        && name.length() > REQUIRES_PERMISSION.length()
+-                        && attributes[0].value instanceof SingleMemberAnnotation) {
+-                    // The external annotations format does not allow for nested/complex annotations.
+-                    // However, these special annotations (@RequiresPermission.Read,
+-                    // @RequiresPermission.Write, etc) are known to only be simple containers with a
+-                    // single permission child, so instead we "inline" the content:
+-                    //  @Read(@RequiresPermission(allOf={P1,P2},conditional=true)
+-                    //     =>
+-                    //      @RequiresPermission.Read(allOf({P1,P2},conditional=true)
+-                    // That's setting attributes that don't actually exist on the container permission,
+-                    // but we'll counteract that on the read-annotations side.
+-                    SingleMemberAnnotation annotation = (SingleMemberAnnotation)attributes[0].value;
+-                    attributes = annotation.memberValuePairs();
+-                }
+-
+-                for (MemberValuePair pair : attributes) {
+-                    writer.print("      <val name=\"");
+-                    if (pair.name != null) {
+-                        writer.print(pair.name);
+-                    } else {
+-                        writer.print(ATTR_VALUE); // default name
+-                    }
+-                    writer.print("\" val=\"");
+-                    writer.print(escapeXml(attributeString(pair.value)));
+-                    writer.println("\" />");
+-                }
+-                writer.println("    </annotation>");
+-
+-            } else if (attributeStrings != null) {
+-                writer.print("\">");
+-                writer.println();
+-                for (int i = 0; i < attributeStrings.length; i += 2) {
+-                    String name = attributeStrings[i];
+-                    String value = attributeStrings[i + 1];
+-                    if (name == null) {
+-                        continue;
+-                    }
+-                    writer.print("      <val name=\"");
+-                    writer.print(name);
+-                    writer.print("\" val=\"");
+-                    writer.print(escapeXml(value));
+-                    writer.println("\" />");
+-                }
+-                writer.println("    </annotation>");
+-            } else {
+-                writer.println("\" />");
+-            }
+-        }
+-
+-        @Override
+-        public boolean equals(Object o) {
+-            if (this == o) {
+-                return true;
+-            }
+-            if (o == null || getClass() != o.getClass()) {
+-                return false;
+-            }
+-
+-            AnnotationData that = (AnnotationData) o;
+-
+-            return name.equals(that.name);
+-        }
+-
+-        @Override
+-        public int hashCode() {
+-            return name.hashCode();
+-        }
+-
+-        private String attributeString(@NonNull Expression value) {
+-            StringBuilder sb = new StringBuilder();
+-            appendExpression(sb, value);
+-            return sb.toString();
+-        }
+-
+-        private boolean appendExpression(@NonNull StringBuilder sb,
+-                @NonNull Expression expression) {
+-            if (expression instanceof ArrayInitializer) {
+-                sb.append('{');
+-                ArrayInitializer initializer = (ArrayInitializer) expression;
+-                boolean first = true;
+-                int initialLength = sb.length();
+-                for (Expression e : initializer.expressions) {
+-                    int length = sb.length();
+-                    if (first) {
+-                        first = false;
+-                    } else {
+-                        sb.append(", ");
+-                    }
+-                    boolean appended = appendExpression(sb, e);
+-                    if (!appended) {
+-                        // trunk off comma if it bailed for some reason (e.g. constant
+-                        // filtered out by API etc)
+-                        sb.setLength(length);
+-                        if (length == initialLength) {
+-                            first = true;
+-                        }
+-                    }
+-                }
+-                sb.append('}');
+-                return true;
+-            } else if (expression instanceof NameReference) {
+-                NameReference reference = (NameReference) expression;
+-                if (reference.binding != null) {
+-                    if (reference.binding instanceof FieldBinding) {
+-                        FieldBinding fb = (FieldBinding)reference.binding;
+-                        Constant constant = fb.constant();
+-                        if (constant != null && constant != Constant.NotAConstant &&
+-                                !(name.equals(INT_DEF_ANNOTATION)) &&
+-                                !(name.equals(STRING_DEF_ANNOTATION))) {
+-                            if (constant instanceof StringConstant) {
+-                                sb.append('"').append(constant.stringValue()).append('"');
+-                                return true;
+-                            } else if (constant instanceof IntConstant) {
+-                                sb.append(Integer.toString(constant.intValue()));
+-                                return true;
+-                            } else if (constant instanceof BooleanConstant) {
+-                                sb.append(Boolean.toString(constant.booleanValue()));
+-                                return true;
+-                            } else if (constant instanceof LongConstant) {
+-                                sb.append(Long.toString(constant.longValue()));
+-                                return true;
+-                            } else if (constant instanceof DoubleConstant) {
+-                                sb.append(Double.toString(constant.doubleValue()));
+-                                return true;
+-                            } else if (constant instanceof CharConstant) {
+-                                sb.append('\'').append(Character.toString(constant.charValue())).append('\'');
+-                                return true;
+-                            } else if (constant instanceof FloatConstant) {
+-                                sb.append(Float.toString(constant.floatValue()));
+-                                return true;
+-                            } else if (constant instanceof ShortConstant) {
+-                                sb.append(Short.toString(constant.shortValue()));
+-                                return true;
+-                            } else if (constant instanceof ByteConstant) {
+-                                sb.append(Byte.toString(constant.byteValue()));
+-                                return true;
+-                            }
+-                        }
+-                        if (fb.declaringClass != null) {
+-                            if (apiFilter != null &&
+-                                    !apiFilter.hasField(
+-                                            new String(fb.declaringClass.readableName()),
+-                                            new String(fb.name))) {
+-                                if (isListIgnored()) {
+-                                    info("Filtering out typedef constant "
+-                                            + new String(fb.declaringClass.readableName()) + "."
+-                                            + new String(fb.name) + "");
+-                                }
+-                                return false;
+-                            }
+-                            sb.append(fb.declaringClass.readableName());
+-                            sb.append('.');
+-                            sb.append(fb.name);
+-                        } else {
+-                            sb.append(reference.binding.readableName());
+-                        }
+-                    } else {
+-                        sb.append(reference.binding.readableName());
+-                    }
+-                    return true;
+-                } else {
+-                    warning("No binding for reference " + reference);
+-                }
+-                return false;
+-            } else if (expression instanceof StringLiteral) {
+-                StringLiteral s = (StringLiteral) expression;
+-                sb.append('"');
+-                sb.append(s.source());
+-                sb.append('"');
+-                return true;
+-            } else if (expression instanceof NumberLiteral) {
+-                NumberLiteral number = (NumberLiteral) expression;
+-                sb.append(number.source());
+-                return true;
+-            } else if (expression instanceof TrueLiteral) {
+-                sb.append(true);
+-                return true;
+-            } else if (expression instanceof FalseLiteral) {
+-                sb.append(false);
+-                return true;
+-            } else if (expression instanceof org.eclipse.jdt.internal.compiler.ast.NullLiteral) {
+-                sb.append("null");
+-                return true;
+-            } else {
+-                // BinaryExpression etc can happen if you put "3 + 4" in as an integer!
+-                if (expression.constant != null) {
+-                    if (expression.constant.typeID() == TypeIds.T_int) {
+-                        sb.append(expression.constant.intValue());
+-                        return true;
+-                    } else if (expression.constant.typeID() == TypeIds.T_JavaLangString) {
+-                        sb.append('"');
+-                        sb.append(expression.constant.stringValue());
+-                        sb.append('"');
+-                        return true;
+-                    } else {
+-                        warning("Unexpected type for constant " + expression.constant.toString());
+-                    }
+-                } else {
+-                    warning("Unexpected annotation expression of type " + expression.getClass() + " and is "
+-                            + expression);
+-                }
+-            }
+-
+-            return false;
+-        }
+-    }
+-
+-    public enum ClassKind {
+-        CLASS,
+-        INTERFACE,
+-        ENUM,
+-        ANNOTATION;
+-
+-        @NonNull
+-        public static ClassKind forType(@Nullable TypeDeclaration declaration) {
+-            if (declaration == null) {
+-                return CLASS;
+-            }
+-            switch (TypeDeclaration.kind(declaration.modifiers)) {
+-                case TypeDeclaration.INTERFACE_DECL:
+-                    return INTERFACE;
+-                case TypeDeclaration.ANNOTATION_TYPE_DECL:
+-                    return ANNOTATION;
+-                case TypeDeclaration.ENUM_DECL:
+-                    return ENUM;
+-                default:
+-                    return CLASS;
+-            }
+-        }
+-
+-        public String getKeepType() {
+-            // See http://proguard.sourceforge.net/manual/usage.html#classspecification
+-            switch (this) {
+-                case INTERFACE:
+-                    return "interface";
+-                case ENUM:
+-                    return "enum";
+-
+-                case ANNOTATION:
+-                case CLASS:
+-                default:
+-                    return "class";
+-            }
+-        }
+-    }
+-
+-    /**
+-     * An item in the XML file: this corresponds to a method, a field, or a method parameter, and
+-     * has an associated set of annotations
+-     */
+-    private abstract static class Item implements Comparable<Item> {
+-        @NonNull public final String containingClass;
+-        @NonNull public final ClassKind classKind;
+-
+-        public Item(@NonNull String containingClass, @NonNull ClassKind classKind) {
+-            this.containingClass = containingClass;
+-            this.classKind = classKind;
+-        }
+-
+-        public final List<AnnotationData> annotations = Lists.newArrayList();
+-
+-        void write(PrintWriter writer) {
+-            if (annotations.isEmpty()) {
+-                return;
+-            }
+-            writer.print("  <item name=\"");
+-            writer.print(getSignature());
+-            writer.println("\">");
+-
+-            for (AnnotationData annotation : annotations) {
+-                annotation.write(writer);
+-            }
+-            writer.print("  </item>");
+-            writer.println();
+-        }
+-
+-        abstract boolean isFiltered(@NonNull ApiDatabase database);
+-
+-        @NonNull
+-        abstract String getSignature();
+-
+-        @Override
+-        public int compareTo(@SuppressWarnings("NullableProblems") @NonNull Item item) {
+-            String signature1 = getSignature();
+-            String signature2 = item.getSignature();
+-
+-            // IntelliJ's sorting order is not on the escaped HTML but the original
+-            // signatures, which means android.os.AsyncTask<Params,Progress,Result>
+-            // should appear *after* android.os.AsyncTask.Status, which when the <'s are
+-            // escaped it does not
+-            signature1 = signature1.replace('&', '.');
+-            signature2 = signature2.replace('&', '.');
+-
+-            return signature1.compareTo(signature2);
+-        }
+-
+-        @NonNull
+-        public abstract String getKeepRule();
+-
+-        @NonNull
+-        public abstract String getQualifiedClassName();
+-    }
+-
+-    private static class ClassItem extends Item {
+-        private ClassItem(@NonNull String containingClass, @NonNull ClassKind classKind) {
+-            super(containingClass, classKind);
+-        }
+-
+-        @NonNull
+-        static ClassItem create(@NonNull String classFqn, @NonNull ClassKind kind) {
+-            classFqn = ApiDatabase.getRawClass(classFqn);
+-            return new ClassItem(classFqn, kind);
+-        }
+-
+-        @Override
+-        boolean isFiltered(@NonNull ApiDatabase database) {
+-            return !database.hasClass(containingClass);
+-        }
+-
+-        @NonNull
+-        @Override
+-        String getSignature() {
+-            return escapeXml(containingClass);
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getKeepRule() {
+-            // See http://proguard.sourceforge.net/manual/usage.html#classspecification
+-            return "-keep " + classKind.getKeepType() + " " + containingClass + "\n";
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getQualifiedClassName() {
+-            return containingClass;
+-        }
+-
+-        @Override
+-        public String toString() {
+-            return "Class " + containingClass;
+-        }
+-
+-        @Override
+-        public boolean equals(Object o) {
+-            if (this == o) {
+-                return true;
+-            }
+-            if (o == null || getClass() != o.getClass()) {
+-                return false;
+-            }
+-
+-            ClassItem that = (ClassItem) o;
+-
+-            return containingClass.equals(that.containingClass);
+-        }
+-
+-        @Override
+-        public int hashCode() {
+-            return containingClass.hashCode();
+-        }
+-    }
+-
+-    private static class FieldItem extends Item {
+-
+-        @NonNull
+-        public final String fieldName;
+-
+-        @Nullable
+-        public final String fieldType;
+-
+-        private FieldItem(@NonNull String containingClass, @NonNull ClassKind classKind,
+-                @NonNull String fieldName, @Nullable String fieldType) {
+-            super(containingClass, classKind);
+-            this.fieldName = fieldName;
+-            this.fieldType = fieldType;
+-        }
+-
+-        @Nullable
+-        static FieldItem create(String classFqn, @NonNull ClassKind classKind, FieldBinding field) {
+-            String name = new String(field.name);
+-            String type = getFieldType(field);
+-            return classFqn != null ? new FieldItem(classFqn, classKind, name, type) : null;
+-        }
+-
+-        @Nullable
+-        private static String getFieldType(FieldBinding binding) {
+-            if (binding.type != null) {
+-                return new String(binding.type.readableName());
+-            }
+-
+-            return null;
+-        }
+-
+-        @Override
+-        boolean isFiltered(@NonNull ApiDatabase database) {
+-            return !database.hasField(containingClass, fieldName);
+-        }
+-
+-        @NonNull
+-        @Override
+-        String getSignature() {
+-            return escapeXml(containingClass) + ' ' + fieldName;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getKeepRule() {
+-            if (fieldType == null) {
+-                return ""; // imported item; these can't have keep rules
+-            }
+-            // See http://proguard.sourceforge.net/manual/usage.html#classspecification
+-            return "-keep " + classKind.getKeepType() + " " + containingClass +
+-                    " {\n    " + fieldType + " " + fieldName + "\n}\n";
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getQualifiedClassName() {
+-            return containingClass;
+-        }
+-
+-        @Override
+-        public String toString() {
+-            return "Field " + containingClass + "#" + fieldName;
+-        }
+-
+-        @Override
+-        public boolean equals(Object o) {
+-            if (this == o) {
+-                return true;
+-            }
+-            if (o == null || getClass() != o.getClass()) {
+-                return false;
+-            }
+-
+-            FieldItem that = (FieldItem) o;
+-
+-            return containingClass.equals(that.containingClass) &&
+-                    fieldName.equals(that.fieldName);
+-        }
+-
+-        @Override
+-        public int hashCode() {
+-            int result = fieldName.hashCode();
+-            result = 31 * result + containingClass.hashCode();
+-            return result;
+-        }
+-    }
+-
+-    private static class MethodItem extends Item {
+-
+-        @NonNull
+-        public final String methodName;
+-
+-        @NonNull
+-        public final String parameterList;
+-
+-        @Nullable
+-        public final String returnType;
+-
+-        public final boolean isConstructor;
+-
+-        private MethodItem(
+-                @NonNull String containingClass,
+-                @NonNull ClassKind classKind,
+-                @Nullable String returnType,
+-                @NonNull String methodName,
+-                @NonNull String parameterList,
+-                boolean isConstructor) {
+-            super(containingClass, classKind);
+-            this.returnType = returnType;
+-            this.methodName = methodName;
+-            this.parameterList = parameterList;
+-            this.isConstructor = isConstructor;
+-        }
+-
+-        @NonNull
+-        public String getName() {
+-            return methodName;
+-        }
+-
+-        @Nullable
+-        static MethodItem create(@Nullable String classFqn,
+-                @NonNull ClassKind classKind,
+-                @NonNull AbstractMethodDeclaration declaration,
+-                @Nullable MethodBinding binding) {
+-            if (classFqn == null || binding == null) {
+-                return null;
+-            }
+-            String returnType = getReturnType(binding);
+-            String methodName = getMethodName(binding);
+-            Argument[] arguments = declaration.arguments;
+-            boolean isVarargs = arguments != null && arguments.length > 0 &&
+-                    arguments[arguments.length - 1].isVarArgs();
+-            String parameterList = getParameterList(binding, isVarargs);
+-            if (returnType == null || methodName == null) {
+-                return null;
+-            }
+-            //noinspection PointlessBooleanExpression,ConstantConditions
+-            if (!INCLUDE_TYPE_ARGS) {
+-                classFqn = ApiDatabase.getRawClass(classFqn);
+-                methodName = ApiDatabase.getRawMethod(methodName);
+-            }
+-            return new MethodItem(classFqn, classKind, returnType,
+-                    methodName, parameterList,
+-                    binding.isConstructor());
+-        }
+-
+-        @NonNull
+-        @Override
+-        String getSignature() {
+-            StringBuilder sb = new StringBuilder(100);
+-            sb.append(escapeXml(containingClass));
+-            sb.append(' ');
+-
+-            if (isConstructor) {
+-                sb.append(escapeXml(methodName));
+-            } else {
+-                assert returnType != null;
+-                sb.append(escapeXml(returnType));
+-                sb.append(' ');
+-                sb.append(escapeXml(methodName));
+-            }
+-
+-            sb.append('(');
+-
+-            // The signature must match *exactly* the formatting used by IDEA,
+-            // since it looks up external annotations in a map by this key.
+-            // Therefore, it is vital that the parameter list uses exactly one
+-            // space after each comma between parameters, and *no* spaces between
+-            // generics variables, e.g. foo(Map<A,B>, int)
+-
+-            // Insert spaces between commas, but not in generics signatures
+-            int balance = 0;
+-            for (int i = 0, n = parameterList.length(); i < n; i++) {
+-                char c = parameterList.charAt(i);
+-                if (c == '<') {
+-                    balance++;
+-                    sb.append("<");
+-                } else if (c == '>') {
+-                    balance--;
+-                    sb.append(">");
+-                } else if (c == ',') {
+-                    sb.append(',');
+-                    if (balance == 0) {
+-                        sb.append(' ');
+-                    }
+-                } else {
+-                    sb.append(c);
+-                }
+-            }
+-            sb.append(')');
+-            return sb.toString();
+-        }
+-
+-        @Override
+-        boolean isFiltered(@NonNull ApiDatabase database) {
+-            return !database.hasMethod(containingClass, methodName, parameterList);
+-        }
+-
+-        @Override
+-        public boolean equals(Object o) {
+-            if (this == o) {
+-                return true;
+-            }
+-            if (o == null || getClass() != o.getClass()) {
+-                return false;
+-            }
+-
+-            MethodItem that = (MethodItem) o;
+-
+-            return isConstructor == that.isConstructor && containingClass
+-                    .equals(that.containingClass) && methodName.equals(that.methodName)
+-                    && parameterList.equals(that.parameterList);
+-
+-        }
+-
+-        @Override
+-        public int hashCode() {
+-            int result = methodName.hashCode();
+-            result = 31 * result + containingClass.hashCode();
+-            result = 31 * result + parameterList.hashCode();
+-            result = 31 * result + (returnType != null ? returnType.hashCode() : 0);
+-            result = 31 * result + (isConstructor ? 1 : 0);
+-            return result;
+-        }
+-
+-        @Override
+-        public String toString() {
+-            return "Method " + containingClass + "#" + methodName;
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getKeepRule() {
+-            // See http://proguard.sourceforge.net/manual/usage.html#classspecification
+-            StringBuilder sb = new StringBuilder();
+-            sb.append("-keep ");
+-            sb.append(classKind.getKeepType());
+-            sb.append(" ");
+-            sb.append(containingClass);
+-            sb.append(" {\n");
+-            sb.append("    ");
+-            if (isConstructor) {
+-                sb.append("<init>");
+-            } else {
+-                sb.append(returnType);
+-                sb.append(" ");
+-                sb.append(methodName);
+-            }
+-            sb.append("(");
+-            sb.append(parameterList); // TODO: Strip generics?
+-            sb.append(")\n");
+-            sb.append("}\n");
+-
+-            return sb.toString();
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getQualifiedClassName() {
+-            return containingClass;
+-        }
+-    }
+-
+-    @Nullable
+-    private static String getReturnType(MethodBinding binding) {
+-        if (binding.returnType != null) {
+-            return new String(binding.returnType.readableName());
+-        } else if (binding.declaringClass != null) {
+-            assert binding.isConstructor();
+-            return new String(binding.declaringClass.readableName());
+-        }
+-
+-        return null;
+-    }
+-
+-    @Nullable
+-    private static String getMethodName(@NonNull MethodBinding binding) {
+-        if (binding.isConstructor()) {
+-            if (binding.declaringClass != null) {
+-                String classFqn = new String(binding.declaringClass.readableName());
+-                return classFqn.substring(classFqn.lastIndexOf('.') + 1);
+-            }
+-
+-        }
+-        if (binding.selector != null) {
+-            return new String(binding.selector);
+-        }
+-
+-        assert binding.isConstructor();
+-
+-        return null;
+-    }
+-
+-    @NonNull
+-    private static String getParameterList(@NonNull MethodBinding binding, boolean isVarargs) {
+-        // Create compact type signature (no spaces around commas or generics arguments)
+-        StringBuilder sb = new StringBuilder();
+-        TypeBinding[] typeParameters = binding.parameters;
+-        if (typeParameters != null) {
+-            for (int i = 0, n = typeParameters.length; i < n; i++) {
+-                TypeBinding parameter = typeParameters[i];
+-                if (i > 0) {
+-                    sb.append(',');
+-                }
+-                String str = fixParameterString(new String(parameter.readableName()));
+-                if (isVarargs && i == n - 1 && str.endsWith("[]")) {
+-                    str = str.substring(0, str.length() - 2) + "...";
+-                }
+-                sb.append(str);
+-            }
+-        }
+-        return sb.toString();
+-    }
+-
+-    private static class ParameterItem extends MethodItem {
+-        @NonNull
+-        public final String argIndex;
+-
+-        private ParameterItem(
+-                @NonNull String containingClass,
+-                @NonNull ClassKind classKind,
+-                @Nullable String returnType,
+-                @NonNull String methodName,
+-                @NonNull String parameterList,
+-                boolean isConstructor,
+-                @NonNull String argIndex) {
+-            super(containingClass, classKind, returnType, methodName, parameterList, isConstructor);
+-            this.argIndex = argIndex;
+-        }
+-
+-        @Nullable
+-        static ParameterItem create(
+-                AbstractMethodDeclaration methodDeclaration,
+-                Argument argument,
+-                String classFqn,
+-                ClassKind classKind,
+-                MethodBinding methodBinding,
+-                LocalVariableBinding parameterBinding) {
+-            if (classFqn == null || methodBinding == null || parameterBinding == null) {
+-                return null;
+-            }
+-
+-            String methodName = getMethodName(methodBinding);
+-            Argument[] arguments = methodDeclaration.arguments;
+-            boolean isVarargs = arguments != null && arguments.length > 0 &&
+-                    arguments[arguments.length - 1].isVarArgs();
+-            String parameterList = getParameterList(methodBinding, isVarargs);
+-            String returnType = getReturnType(methodBinding);
+-            if (methodName == null || returnType == null) {
+-                return null;
+-            }
+-
+-            int index = 0;
+-            boolean found = false;
+-            if (methodDeclaration.arguments != null) {
+-                for (Argument a : methodDeclaration.arguments) {
+-                    if (a == argument) {
+-                        found = true;
+-                        break;
+-                    }
+-                    index++;
+-                }
+-            }
+-            if (!found) {
+-                return null;
+-            }
+-            String argNum = Integer.toString(index);
+-
+-            //noinspection PointlessBooleanExpression,ConstantConditions
+-            if (!INCLUDE_TYPE_ARGS) {
+-                classFqn = ApiDatabase.getRawClass(classFqn);
+-                methodName = ApiDatabase.getRawMethod(methodName);
+-            }
+-            return new ParameterItem(classFqn, classKind, returnType, methodName, parameterList,
+-                    methodBinding.isConstructor(), argNum);
+-        }
+-
+-
+-        @NonNull
+-        @Override
+-        String getSignature() {
+-            return super.getSignature() + ' ' + argIndex;
+-        }
+-
+-        @Override
+-        public boolean equals(Object o) {
+-            if (this == o) {
+-                return true;
+-            }
+-            if (o == null || getClass() != o.getClass()) {
+-                return false;
+-            }
+-            if (!super.equals(o)) {
+-                return false;
+-            }
+-
+-            ParameterItem that = (ParameterItem) o;
+-
+-            return argIndex.equals(that.argIndex);
+-
+-        }
+-
+-        @Override
+-        public int hashCode() {
+-            int result = super.hashCode();
+-            result = 31 * result + argIndex.hashCode();
+-            return result;
+-        }
+-
+-        @Override
+-        public String toString() {
+-            return "Parameter #" + argIndex + " in " + super.toString();
+-        }
+-
+-        @NonNull
+-        @Override
+-        public String getKeepRule() {
+-            return "";
+-        }
+-    }
+-
+-    private class AnnotationVisitor extends ASTVisitor {
+-        @Override
+-        public boolean visit(Argument argument, BlockScope scope) {
+-            Annotation[] annotations = argument.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                ReferenceContext referenceContext = scope.referenceContext();
+-                if (referenceContext instanceof AbstractMethodDeclaration) {
+-                    MethodBinding binding = ((AbstractMethodDeclaration) referenceContext).binding;
+-                    ClassScope classScope = findClassScope(scope);
+-                    if (classScope == null) {
+-                        return false;
+-                    }
+-                    String fqn = getFqn(classScope);
+-                    ClassKind kind = ClassKind.forType(classScope.referenceContext);
+-                    Item item = ParameterItem.create(
+-                            (AbstractMethodDeclaration) referenceContext, argument, fqn, kind,
+-                            binding, argument.binding);
+-                    if (item != null) {
+-                        addItem(fqn, item);
+-                        addAnnotations(annotations, item);
+-                    }
+-                }
+-            }
+-            return false;
+-        }
+-
+-        @Override
+-        public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+-            Annotation[] annotations = constructorDeclaration.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                MethodBinding constructorBinding = constructorDeclaration.binding;
+-                if (constructorBinding == null) {
+-                    return false;
+-                }
+-
+-                String fqn = getFqn(scope);
+-                ClassKind kind = ClassKind.forType(scope.referenceContext);
+-                Item item = MethodItem.create(fqn, kind, constructorDeclaration, constructorBinding);
+-                if (item != null) {
+-                    addItem(fqn, item);
+-                    addAnnotations(annotations, item);
+-                }
+-            }
+-
+-            Argument[] arguments = constructorDeclaration.arguments;
+-            if (arguments != null) {
+-                for (Argument argument : arguments) {
+-                    argument.traverse(this, constructorDeclaration.scope);
+-                }
+-            }
+-            return false;
+-        }
+-
+-        @Override
+-        public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+-            Annotation[] annotations = fieldDeclaration.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                FieldBinding fieldBinding = fieldDeclaration.binding;
+-                if (fieldBinding == null) {
+-                    return false;
+-                }
+-
+-                String fqn = getFqn(scope);
+-                ClassKind kind = scope.referenceContext instanceof TypeDeclaration ?
+-                        ClassKind.forType((TypeDeclaration)scope.referenceContext) :
+-                        ClassKind.CLASS;
+-                Item item = FieldItem.create(fqn, kind, fieldBinding);
+-                if (item != null && fqn != null) {
+-                    addItem(fqn, item);
+-                    addAnnotations(annotations, item);
+-                }
+-            }
+-            return false;
+-        }
+-
+-        @Override
+-        public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+-            Annotation[] annotations = methodDeclaration.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                MethodBinding methodBinding = methodDeclaration.binding;
+-                if (methodBinding == null) {
+-                    return false;
+-                }
+-                String fqn = getFqn(scope);
+-                ClassKind kind = ClassKind.forType(scope.referenceContext);
+-                MethodItem item = MethodItem.create(fqn, kind, methodDeclaration,
+-                        methodDeclaration.binding);
+-                if (item != null) {
+-                    addItem(fqn, item);
+-
+-                    // Deliberately skip findViewById()'s return nullability
+-                    // for now; it's true that findViewById can return null,
+-                    // but that means all code which does findViewById(R.id.foo).something()
+-                    // will be flagged as potentially throwing an NPE, and many developers
+-                    // will do this when they *know* that the id exists (in which case
+-                    // the method won't return null.)
+-                    boolean skipReturnAnnotations = false;
+-                    if ("findViewById".equals(item.getName())) {
+-                        skipReturnAnnotations = true;
+-                        if (item.annotations.isEmpty()) {
+-                            // No other annotations so far: just remove it
+-                            removeItem(fqn, item);
+-                        }
+-                    }
+-
+-                    if (!skipReturnAnnotations) {
+-                        addAnnotations(annotations, item);
+-                    }
+-                }
+-            }
+-
+-            Argument[] arguments = methodDeclaration.arguments;
+-            if (arguments != null) {
+-                for (Argument argument : arguments) {
+-                    argument.traverse(this, methodDeclaration.scope);
+-                }
+-            }
+-            return false;
+-        }
+-
+-        @Override
+-        public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+-            Annotation[] annotations = localTypeDeclaration.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                SourceTypeBinding binding = localTypeDeclaration.binding;
+-                if (binding == null) {
+-                    return true;
+-                }
+-
+-                String fqn = getFqn(scope);
+-                if (fqn == null) {
+-                    fqn = new String(localTypeDeclaration.binding.readableName());
+-                }
+-                Item item = ClassItem.create(fqn, ClassKind.forType(localTypeDeclaration));
+-                addItem(fqn, item);
+-                addAnnotations(annotations, item);
+-
+-            }
+-            return true;
+-        }
+-
+-        @Override
+-        public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+-            Annotation[] annotations = memberTypeDeclaration.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                SourceTypeBinding binding = memberTypeDeclaration.binding;
+-                if (!(binding instanceof MemberTypeBinding)) {
+-                    return true;
+-                }
+-                if (binding.isAnnotationType() || binding.isAnonymousType()) {
+-                    return false;
+-                }
+-
+-                String fqn = new String(memberTypeDeclaration.binding.readableName());
+-                Item item = ClassItem.create(fqn, ClassKind.forType(memberTypeDeclaration));
+-                addItem(fqn, item);
+-                addAnnotations(annotations, item);
+-            }
+-            return true;
+-        }
+-
+-        @Override
+-        public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+-            Annotation[] annotations = typeDeclaration.annotations;
+-            if (hasRelevantAnnotations(annotations)) {
+-                SourceTypeBinding binding = typeDeclaration.binding;
+-                if (binding == null) {
+-                    return true;
+-                }
+-                String fqn = new String(typeDeclaration.binding.readableName());
+-                Item item = ClassItem.create(fqn, ClassKind.forType(typeDeclaration));
+-                addItem(fqn, item);
+-                addAnnotations(annotations, item);
+-
+-            }
+-            return true;
+-        }
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefCollector.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefCollector.java
+deleted file mode 100644
+index 5924f4c..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefCollector.java
++++ /dev/null
+@@ -1,154 +0,0 @@
+-/*
+- * Copyright (C) 2014 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.build.gradle.tasks.annotations;
+-
+-import com.android.annotations.NonNull;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Maps;
+-
+-import org.eclipse.jdt.internal.compiler.ASTVisitor;
+-import org.eclipse.jdt.internal.compiler.ast.Annotation;
+-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+-import org.eclipse.jdt.internal.compiler.ast.Javadoc;
+-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+-import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+-
+-import java.io.File;
+-import java.util.ArrayList;
+-import java.util.Collection;
+-import java.util.List;
+-import java.util.Map;
+-
+-/** Gathers information about typedefs (@IntDef and @StringDef */
+-public class TypedefCollector extends ASTVisitor {
+-    private Map<String,List<Annotation>> mMap = Maps.newHashMap();
+-
+-    private final boolean mRequireHide;
+-    private final boolean mRequireSourceRetention;
+-    private CompilationUnitDeclaration mCurrentUnit;
+-    private List<String> mTypedefClasses = Lists.newArrayList();
+-
+-    public TypedefCollector(
+-            @NonNull Collection<CompilationUnitDeclaration> units,
+-            boolean requireHide,
+-            boolean requireSourceRetention) {
+-        mRequireHide = requireHide;
+-        mRequireSourceRetention = requireSourceRetention;
+-
+-        for (CompilationUnitDeclaration unit : units) {
+-            mCurrentUnit = unit;
+-            unit.traverse(this, unit.scope);
+-            mCurrentUnit = null;
+-        }
+-    }
+-
+-    public List<String> getNonPublicTypedefClasses() {
+-        return mTypedefClasses;
+-    }
+-
+-    public Map<String,List<Annotation>> getTypedefs() {
+-        return mMap;
+-    }
+-
+-    @Override
+-    public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+-        return recordTypedefs(memberTypeDeclaration);
+-
+-    }
+-
+-    @Override
+-    public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+-        return recordTypedefs(typeDeclaration);
+-    }
+-
+-    private boolean recordTypedefs(TypeDeclaration declaration) {
+-        SourceTypeBinding binding = declaration.binding;
+-        if (binding == null) {
+-            return false;
+-        }
+-        Annotation[] annotations = declaration.annotations;
+-        if (annotations != null) {
+-            if (declaration.binding.isAnnotationType()) {
+-                for (Annotation annotation : annotations) {
+-                    String typeName = Extractor.getFqn(annotation);
+-                    if (typeName == null) {
+-                        continue;
+-                    }
+-
+-                    if (Extractor.isNestedAnnotation(typeName)) {
+-                        String fqn = new String(binding.readableName());
+-
+-                        List<Annotation> list = mMap.get(fqn);
+-                        if (list == null) {
+-                            list = new ArrayList<Annotation>(2);
+-                            mMap.put(fqn, list);
+-                        }
+-                        list.add(annotation);
+-
+-                        if (mRequireHide) {
+-                            Javadoc javadoc = declaration.javadoc;
+-                            if (javadoc != null) {
+-                                StringBuffer stringBuffer = new StringBuffer(200);
+-                                javadoc.print(0, stringBuffer);
+-                                String documentation = stringBuffer.toString();
+-                                if (!documentation.contains("@hide")) {
+-                                    Extractor.warning(getFileName()
+-                                            + ": The typedef annotation " + fqn
+-                                            + " should specify @hide in a doc comment");
+-                                }
+-                            }
+-                        }
+-                        if (mRequireSourceRetention
+-                                && !Extractor.hasSourceRetention(annotations)) {
+-                            Extractor.warning(getFileName()
+-                                    + ": The typedef annotation " + fqn
+-                                    + " should have @Retention(RetentionPolicy.SOURCE)");
+-                        }
+-                        if (declaration.binding != null
+-                                && (declaration.modifiers & ClassFileConstants.AccPublic) == 0) {
+-                            StringBuilder sb = new StringBuilder(100);
+-                            for (char c : declaration.binding.qualifiedPackageName()) {
+-                                if (c == '.') {
+-                                    sb.append('/');
+-                                } else {
+-                                    sb.append(c);
+-                                }
+-                            }
+-                            sb.append(File.separatorChar);
+-                            for (char c : declaration.binding.qualifiedSourceName()) {
+-                                if (c == '.') {
+-                                    sb.append('$');
+-                                } else {
+-                                    sb.append(c);
+-                                }
+-                            }
+-                            mTypedefClasses.add(sb.toString());
+-                        }
+-                    }
+-                }
+-            }
+-        }
+-        return true;
+-    }
+-
+-    private String getFileName() {
+-        return new String(mCurrentUnit.getFileName());
+-    }
+-}
+diff --git a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefRemover.java b/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefRemover.java
+deleted file mode 100644
+index 758f125..0000000
+--- a/base/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/annotations/TypedefRemover.java
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- * Copyright (C) 2015 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.build.gradle.tasks.annotations;
+-
+-import static com.android.SdkConstants.DOT_CLASS;
+-import static org.objectweb.asm.Opcodes.ASM5;
+-
+-import com.android.annotations.NonNull;
+-import com.google.common.collect.Lists;
+-import com.google.common.collect.Sets;
+-import com.google.common.io.Files;
+-
+-import org.objectweb.asm.ClassReader;
+-import org.objectweb.asm.ClassVisitor;
+-import org.objectweb.asm.ClassWriter;
+-
+-import java.io.File;
+-import java.io.IOException;
+-import java.util.List;
+-import java.util.Set;
+-
+-/**
+- * Finds and deletes typedef annotation classes (and also warns if their
+- * retention is wrong, such that usages of the annotation embeds data
+- * into the .class file.)
+- * <p>
+- * (Based on the similar class in {@code development/tools/rmtypedefs/})
+- */
+- at SuppressWarnings("SpellCheckingInspection")
+-public class TypedefRemover {
+-    private final Extractor mExtractor;
+-    private final boolean mQuiet;
+-    private final boolean mVerbose;
+-    private final boolean mDryRun;
+-
+-    public TypedefRemover(
+-            @NonNull Extractor extractor,
+-            boolean quiet,
+-            boolean verbose,
+-            boolean dryRun) {
+-        mExtractor = extractor;
+-        mQuiet = quiet;
+-        mVerbose = verbose;
+-        mDryRun = dryRun;
+-    }
+-
+-    private Set<String> mAnnotationNames = Sets.newHashSet();
+-    private List<File> mAnnotationClassFiles = Lists.newArrayList();
+-    private Set<File> mAnnotationOuterClassFiles = Sets.newHashSet();
+-
+-    public void remove(@NonNull File classDir, @NonNull List<String> owners) {
+-        if (!mQuiet) {
+-            mExtractor.info("Deleting @IntDef and @StringDef annotation class files");
+-        }
+-
+-        // Record typedef annotation names and files
+-        for (String owner : owners) {
+-            File file = new File(classDir, owner.replace('/', File.separatorChar) + DOT_CLASS);
+-            addTypeDef(owner, file);
+-        }
+-
+-        // Rewrite the .class files for any classes that *contain* typedefs as innerclasses
+-        rewriteOuterClasses();
+-
+-        // Removes the actual .class files for the typedef annotations
+-        deleteAnnotationClasses();
+-    }
+-
+-    /**
+-     * Records the given class name (internal name) and class file path as corresponding to a
+-     * typedef annotation
+-     * */
+-    private void addTypeDef(String name, File file) {
+-        mAnnotationClassFiles.add(file);
+-        mAnnotationNames.add(name);
+-
+-        String fileName = file.getName();
+-        int index = fileName.lastIndexOf('$');
+-        if (index != -1) {
+-            File parentFile = file.getParentFile();
+-            assert parentFile != null : file;
+-            File container = new File(parentFile, fileName.substring(0, index) + ".class");
+-            if (container.exists()) {
+-                mAnnotationOuterClassFiles.add(container);
+-            } else {
+-                Extractor.error("Warning: Could not find outer class " + container
+-                        + " for typedef " + file);
+-            }
+-        }
+-    }
+-
+-    /**
+-     * Rewrites the outer classes containing the typedefs such that they no longer refer to
+-     * the (now removed) typedef annotation inner classes
+-     */
+-    private void rewriteOuterClasses() {
+-        for (File file : mAnnotationOuterClassFiles) {
+-            byte[] bytes;
+-            try {
+-                bytes = Files.toByteArray(file);
+-            } catch (IOException e) {
+-                Extractor.error("Could not read " + file + ": " + e.getLocalizedMessage());
+-                continue;
+-            }
+-
+-            ClassWriter classWriter = new ClassWriter(ASM5);
+-            ClassVisitor classVisitor = new ClassVisitor(ASM5, classWriter) {
+-                @Override
+-                public void visitInnerClass(String name, String outerName, String innerName,
+-                        int access) {
+-                    if (!mAnnotationNames.contains(name)) {
+-                        super.visitInnerClass(name, outerName, innerName, access);
+-                    }
+-                }
+-            };
+-            ClassReader reader = new ClassReader(bytes);
+-            reader.accept(classVisitor, 0);
+-            byte[] rewritten = classWriter.toByteArray();
+-            try {
+-                Files.write(rewritten, file);
+-            } catch (IOException e) {
+-                Extractor.error("Could not write " + file + ": " + e.getLocalizedMessage());
+-                //noinspection UnnecessaryContinue
+-                continue;
+-            }
+-        }
+-    }
+-
+-    /**
+-     * Performs the actual deletion (or display, if in dry-run mode) of the typedef annotation
+-     * files
+-     */
+-    private void deleteAnnotationClasses() {
+-        for (File mFile : mAnnotationClassFiles) {
+-            if (mVerbose) {
+-                if (mDryRun) {
+-                    mExtractor.info("Would delete " + mFile);
+-                } else {
+-                    mExtractor.info("Deleting " + mFile);
+-                }
+-            }
+-            if (!mDryRun) {
+-                boolean deleted = mFile.delete();
+-                if (!deleted) {
+-                    Extractor.warning("Could not delete " + mFile);
+-                }
+-            }
+-        }
+-    }
+-}
+\ No newline at end of file
+diff --git a/base/build-system/gradle/src/main/groovy/com/android/build/gradle/BaseExtension.java b/base/build-system/gradle/src/main/groovy/com/android/build/gradle/BaseExtension.java
+index b4f4bb0..b91a3dd 100644
+--- a/base/build-system/gradle/src/main/groovy/com/android/build/gradle/BaseExtension.java
++++ b/base/build-system/gradle/src/main/groovy/com/android/build/gradle/BaseExtension.java
+@@ -34,7 +34,6 @@ import com.android.build.gradle.internal.dsl.BuildType;
+ import com.android.build.gradle.internal.dsl.CoreBuildType;
+ import com.android.build.gradle.internal.dsl.CoreProductFlavor;
+ import com.android.build.gradle.internal.dsl.DexOptions;
+-import com.android.build.gradle.internal.dsl.LintOptions;
+ import com.android.build.gradle.internal.dsl.PackagingOptions;
+ import com.android.build.gradle.internal.dsl.PreprocessingOptions;
+ import com.android.build.gradle.internal.dsl.ProductFlavor;
+@@ -92,9 +91,6 @@ public abstract class BaseExtension implements AndroidConfig {
+     /** Options for aapt, tool for packaging resources. */
+     final AaptOptions aaptOptions;
+ 
+-    /** Lint options. */
+-    final LintOptions lintOptions;
+-
+     /** Dex options. */
+     final DexOptions dexOptions;
+ 
+@@ -188,7 +184,6 @@ public abstract class BaseExtension implements AndroidConfig {
+ 
+         aaptOptions = instantiator.newInstance(AaptOptions.class);
+         dexOptions = instantiator.newInstance(DexOptions.class);
+-        lintOptions = instantiator.newInstance(LintOptions.class);
+         testOptions = instantiator.newInstance(TestOptions.class);
+         compileOptions = instantiator.newInstance(CompileOptions.class);
+         packagingOptions = instantiator.newInstance(PackagingOptions.class);
+@@ -405,14 +400,6 @@ public abstract class BaseExtension implements AndroidConfig {
+         action.execute(dexOptions);
+     }
+ 
+-    /**
+-     * Configure lint options.
+-     */
+-    public void lintOptions(Action<LintOptions> action) {
+-        checkWritability();
+-        action.execute(lintOptions);
+-    }
+-
+     /** Configures the test options. */
+     public void testOptions(Action<TestOptions> action) {
+         checkWritability();
+@@ -757,12 +744,6 @@ public abstract class BaseExtension implements AndroidConfig {
+ 
+     /** {@inheritDoc} */
+     @Override
+-    public LintOptions getLintOptions() {
+-        return lintOptions;
+-    }
+-
+-    /** {@inheritDoc} */
+-    @Override
+     public PackagingOptions getPackagingOptions() {
+         return packagingOptions;
+     }
diff --git a/debian/patches/gradle-experimental.patch b/debian/patches/gradle-experimental.patch
new file mode 100644
index 0000000..6a1d793
--- /dev/null
+++ b/debian/patches/gradle-experimental.patch
@@ -0,0 +1,62 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sat, 6 Feb 2016 21:14:41 +0100
+Subject: gradle experimental
+
+---
+ base/build-system/gradle-experimental/build.gradle | 24 +++++++++++-----------
+ build.gradle                                       |  2 +-
+ 2 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/base/build-system/gradle-experimental/build.gradle b/base/build-system/gradle-experimental/build.gradle
+index ce579e0..c224332 100644
+--- a/base/build-system/gradle-experimental/build.gradle
++++ b/base/build-system/gradle-experimental/build.gradle
+@@ -1,23 +1,23 @@
+ apply plugin: 'groovy'
+ 
+ // Extract gradle libraries to ensure gradle-core is compatible with older version.
+-String gradleVersion = "2.5"
+-File gradleBinary = file("$rootProject.projectDir/external/gradle/gradle-$gradleVersion-all.zip")
+-File gradleLib = file("$rootProject.ext.androidHostOut/alternate-gradle/gradle-$gradleVersion/lib")
++//String gradleVersion = "2.5"
++//File gradleBinary = file("$rootProject.projectDir/external/gradle/gradle-$gradleVersion-all.zip")
++//File gradleLib = file("$rootProject.ext.androidHostOut/alternate-gradle/gradle-$gradleVersion/lib")
+ 
+-task extractGradleLibs(type: Copy) {
+-    from zipTree(gradleBinary)
+-    into gradleLib.parentFile.parentFile
+-}
++//task extractGradleLibs(type: Copy) {
++//    from zipTree(gradleBinary)
++//    into gradleLib.parentFile.parentFile
++//}
+ 
+-compileJava.dependsOn extractGradleLibs
++//compileJava.dependsOn extractGradleLibs
+ 
+-task setupGradleInIde {
+-    dependsOn extractGradleLibs
+-}
++//task setupGradleInIde {
++//    dependsOn extractGradleLibs
++//}
+ 
+ dependencies {
+-    compile fileTree(dir:gradleLib)
++    //compile fileTree(dir:gradleLib)
+     compile project(':base:gradle-core')
+ 
+     testCompile 'junit:junit:4.12'
+diff --git a/build.gradle b/build.gradle
+index bf35058..6674c9a 100644
+--- a/build.gradle
++++ b/build.gradle
+@@ -118,7 +118,7 @@ task init {
+   dependsOn prepareRepo
+   dependsOn setupGradleInIde
+   dependsOn copyGradleProperty
+-  dependsOn tasks.findByPath(':base:gradle-experimental:setupGradleInIde')
++//dependsOn tasks.findByPath(':base:gradle-experimental:setupGradleInIde')
+   dependsOn tasks.findByPath(':base:builder:generateVersionConstantsJava')
+ }
+ 
diff --git a/debian/patches/project-test-lib.patch b/debian/patches/project-test-lib.patch
new file mode 100644
index 0000000..d61bd7b
--- /dev/null
+++ b/debian/patches/project-test-lib.patch
@@ -0,0 +1,35 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sun, 7 Feb 2016 20:24:29 +0100
+Subject: project-test-lib
+
+---
+ base/build-system/gradle-core/build.gradle | 2 +-
+ base/build-system/gradle/build.gradle      | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/base/build-system/gradle-core/build.gradle b/base/build-system/gradle-core/build.gradle
+index 7e3a673..e36483b 100644
+--- a/base/build-system/gradle-core/build.gradle
++++ b/base/build-system/gradle-core/build.gradle
+@@ -26,7 +26,7 @@ dependencies {
+ 
+     testCompile 'junit:junit:4.12'
+     testCompile 'org.mockito:mockito-all:1.9.5'
+-    testCompile project(':base:project-test-lib')
++    //testCompile project(':base:project-test-lib')
+     testCompile project(':base:testutils')
+ }
+ 
+diff --git a/base/build-system/gradle/build.gradle b/base/build-system/gradle/build.gradle
+index b36e23e..affa879 100644
+--- a/base/build-system/gradle/build.gradle
++++ b/base/build-system/gradle/build.gradle
+@@ -5,7 +5,7 @@ dependencies {
+     compile gradleApi()
+ 
+     testCompile 'junit:junit:4.12'
+-    testCompile project(':base:project-test-lib')
++    //testCompile project(':base:project-test-lib')
+ }
+ 
+ group = 'com.android.tools.build'
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..63b7123
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1,7 @@
+build.gradle.patch
+settings.gradle.patch
+gradle-experimental.patch
+SdkTestCase.patch
+project-test-lib.patch
+trove3.patch
+disable-lint.patch
diff --git a/debian/patches/settings.gradle.patch b/debian/patches/settings.gradle.patch
new file mode 100644
index 0000000..f721034
--- /dev/null
+++ b/debian/patches/settings.gradle.patch
@@ -0,0 +1,87 @@
+From: Markus Koschany <apo at debian.org>
+Date: Fri, 22 Jan 2016 00:51:17 +0100
+Subject: settings.gradle
+
+---
+ settings.gradle | 38 +++++++++++++++++++-------------------
+ 1 file changed, 19 insertions(+), 19 deletions(-)
+
+diff --git a/settings.gradle b/settings.gradle
+index eb684bb..9ccf1b2 100644
+--- a/settings.gradle
++++ b/settings.gradle
+@@ -4,18 +4,18 @@ include ':base:ant-tasks'
+ include ':base:archquery'
+ include ':base:asset-studio'
+ include ':base:common'
+-include ':base:docs'
++//include ':base:docs'
+ include ':base:ddmlib'
+ include ':base:perflib'
+ include ':base:chartlib'
+ include ':base:draw9patch'
+ include ':base:dvlib'
+-include ':base:jobb'
++//include ':base:jobb'
+ include ':base:layoutlib-api'
+-include ':base:lint'
+-include ':base:lint-api'
+-include ':base:lint-checks'
+-include ':base:lint-tests'
++//include ':base:lint'
++//include ':base:lint-api'
++//include ':base:lint-checks'
++//include ':base:lint-tests'
+ include ':base:manifest-merger'
+ include ':base:ninepatch'
+ include ':base:rule-api'
+@@ -35,10 +35,10 @@ include ':base:builder'
+ include ':base:gradle-model'
+ include ':base:gradle-core'
+ include ':base:gradle'
+-include ':base:gradle-experimental'
+-include ':base:integration-test'
+-include ':base:project-test-lib'
+-include ':base:project-test'
++//include ':base:gradle-experimental'
++//include ':base:integration-test'
++//include ':base:project-test-lib'
++//include ':base:project-test'
+ include ':base:google-services'
+ 
+ include ':base:templates'
+@@ -50,10 +50,10 @@ project(':base:api-generator'      ).projectDir = new File(rootDir, 'base/misc/a
+ project(':base:ant-tasks'          ).projectDir = new File(rootDir, 'base/legacy/ant-tasks')
+ project(':base:archquery'          ).projectDir = new File(rootDir, 'base/legacy/archquery')
+ project(':base:dvlib'              ).projectDir = new File(rootDir, 'base/device_validator/dvlib')
+-project(':base:lint'               ).projectDir = new File(rootDir, 'base/lint/cli')
+-project(':base:lint-api'           ).projectDir = new File(rootDir, 'base/lint/libs/lint-api')
+-project(':base:lint-checks'        ).projectDir = new File(rootDir, 'base/lint/libs/lint-checks')
+-project(':base:lint-tests'         ).projectDir = new File(rootDir, 'base/lint/libs/lint-tests')
++//project(':base:lint'               ).projectDir = new File(rootDir, 'base/lint/cli')
++//project(':base:lint-api'           ).projectDir = new File(rootDir, 'base/lint/libs/lint-api')
++//project(':base:lint-checks'        ).projectDir = new File(rootDir, 'base/lint/libs/lint-checks')
++//project(':base:lint-tests'         ).projectDir = new File(rootDir, 'base/lint/libs/lint-tests')
+ project(':base:screenshot2'        ).projectDir = new File(rootDir, 'base/misc/screenshot2')
+ project(':base:sdklib-test'        ).projectDir = new File(rootDir, 'base/sdklib')
+ project(':base:sdklib-test'        ).buildFileName = 'test.gradle'
+@@ -63,14 +63,14 @@ project(':base:builder-model'      ).projectDir = new File(rootDir, 'base/build-
+ project(':base:builder-test-api'   ).projectDir = new File(rootDir, 'base/build-system/builder-test-api')
+ project(':base:transform-api'      ).projectDir = new File(rootDir, 'base/build-system/transform-api')
+ project(':base:builder'            ).projectDir = new File(rootDir, 'base/build-system/builder')
+-project(':base:docs'               ).projectDir = new File(rootDir, 'base/build-system/docs')
++//project(':base:docs'               ).projectDir = new File(rootDir, 'base/build-system/docs')
+ project(':base:manifest-merger'    ).projectDir = new File(rootDir, 'base/build-system/manifest-merger')
+ project(':base:gradle-core'        ).projectDir = new File(rootDir, 'base/build-system/gradle-core')
+ project(':base:gradle'             ).projectDir = new File(rootDir, 'base/build-system/gradle')
+-project(':base:gradle-experimental').projectDir = new File(rootDir, 'base/build-system/gradle-experimental')
+-project(':base:integration-test'   ).projectDir = new File(rootDir, 'base/build-system/integration-test')
+-project(':base:project-test-lib'   ).projectDir = new File(rootDir, 'base/build-system/project-test-lib')
+-project(':base:project-test'       ).projectDir = new File(rootDir, 'base/build-system/project-test')
++//project(':base:gradle-experimental').projectDir = new File(rootDir, 'base/build-system/gradle-experimental')
++//project(':base:integration-test'   ).projectDir = new File(rootDir, 'base/build-system/integration-test')
++//project(':base:project-test-lib'   ).projectDir = new File(rootDir, 'base/build-system/project-test-lib')
++//project(':base:project-test'       ).projectDir = new File(rootDir, 'base/build-system/project-test')
+ project(':base:google-services'    ).projectDir = new File(rootDir, 'base/build-system/google-services')
+ 
+ include ':swt:chimpchat'
diff --git a/debian/patches/trove3.patch b/debian/patches/trove3.patch
new file mode 100644
index 0000000..bc6ec92
--- /dev/null
+++ b/debian/patches/trove3.patch
@@ -0,0 +1,154 @@
+From: Markus Koschany <apo at debian.org>
+Date: Sun, 7 Feb 2016 20:46:50 +0100
+Subject: trove3
+
+---
+ .../java/com/android/tools/chartlib/TimelineComponent.java   |  2 +-
+ .../main/java/com/android/tools/perflib/heap/ClassObj.java   |  6 +++---
+ .../src/main/java/com/android/tools/perflib/heap/Heap.java   | 12 ++++++------
+ .../java/com/android/tools/perflib/heap/HprofParser.java     |  2 +-
+ .../com/android/tools/perflib/heap/NonRecursiveVisitor.java  |  2 +-
+ .../main/java/com/android/tools/perflib/heap/Snapshot.java   |  2 +-
+ .../android/tools/perflib/heap/analysis/TopologicalSort.java |  2 +-
+ 7 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/base/chartlib/src/main/java/com/android/tools/chartlib/TimelineComponent.java b/base/chartlib/src/main/java/com/android/tools/chartlib/TimelineComponent.java
+index d90b1b8..8138478 100644
+--- a/base/chartlib/src/main/java/com/android/tools/chartlib/TimelineComponent.java
++++ b/base/chartlib/src/main/java/com/android/tools/chartlib/TimelineComponent.java
+@@ -36,7 +36,7 @@ import java.util.Map;
+ 
+ import javax.swing.Icon;
+ 
+-import gnu.trove.TIntObjectHashMap;
++import gnu.trove.map.hash.TIntObjectHashMap;
+ 
+ /**
+  * A component to display a TimelineData object. It locks the timeline object to prevent
+diff --git a/base/perflib/src/main/java/com/android/tools/perflib/heap/ClassObj.java b/base/perflib/src/main/java/com/android/tools/perflib/heap/ClassObj.java
+index 121c27c..213deae 100644
+--- a/base/perflib/src/main/java/com/android/tools/perflib/heap/ClassObj.java
++++ b/base/perflib/src/main/java/com/android/tools/perflib/heap/ClassObj.java
+@@ -19,7 +19,7 @@ package com.android.tools.perflib.heap;
+ import com.android.annotations.NonNull;
+ import com.android.annotations.Nullable;
+ import com.android.annotations.VisibleForTesting;
+-import gnu.trove.TIntObjectHashMap;
++import gnu.trove.map.hash.TIntObjectHashMap;
+ 
+ import java.util.*;
+ 
+@@ -267,7 +267,7 @@ public class ClassObj extends Instance implements Comparable<ClassObj> {
+ 
+     public int getInstanceCount() {
+         int count = 0;
+-        for (Object heapStat : mHeapData.getValues()) {
++        for (Object heapStat : mHeapData.values()) {
+             count += ((HeapData)heapStat).mInstances.size();
+         }
+         return count;
+@@ -275,7 +275,7 @@ public class ClassObj extends Instance implements Comparable<ClassObj> {
+ 
+     public int getShallowSize() {
+         int size = 0;
+-        for (Object heapStat : mHeapData.getValues()) {
++        for (Object heapStat : mHeapData.values()) {
+             size += ((HeapData)heapStat).mShallowSize;
+         }
+         return size;
+diff --git a/base/perflib/src/main/java/com/android/tools/perflib/heap/Heap.java b/base/perflib/src/main/java/com/android/tools/perflib/heap/Heap.java
+index 3d617e6..95d45dc 100644
+--- a/base/perflib/src/main/java/com/android/tools/perflib/heap/Heap.java
++++ b/base/perflib/src/main/java/com/android/tools/perflib/heap/Heap.java
+@@ -22,9 +22,9 @@ import java.util.ArrayList;
+ import java.util.Collection;
+ 
+ import com.google.common.collect.*;
+-import gnu.trove.TIntObjectHashMap;
+-import gnu.trove.TLongObjectHashMap;
+-import gnu.trove.TObjectProcedure;
++import gnu.trove.map.hash.TIntObjectHashMap;
++import gnu.trove.map.hash.TLongObjectHashMap;
++import gnu.trove.procedure.TObjectProcedure;
+ 
+ public class Heap {
+ 
+@@ -145,7 +145,7 @@ public class Heap {
+     }
+ 
+     public final void dumpInstanceCounts() {
+-        for (Object value : mClassesById.getValues()) {
++        for (Object value : mClassesById.values()) {
+             ClassObj theClass = (ClassObj) value;
+             int count = theClass.getInstanceCount();
+ 
+@@ -156,7 +156,7 @@ public class Heap {
+     }
+ 
+     public final void dumpSubclasses() {
+-        for (Object value : mClassesById.getValues()) {
++        for (Object value : mClassesById.values()) {
+             ClassObj theClass = (ClassObj) value;
+             int count = theClass.mSubclasses.size();
+ 
+@@ -168,7 +168,7 @@ public class Heap {
+     }
+ 
+     public final void dumpSizes() {
+-        for (Object value : mClassesById.getValues()) {
++        for (Object value : mClassesById.values()) {
+             ClassObj theClass = (ClassObj) value;
+ 
+             int size = 0;
+diff --git a/base/perflib/src/main/java/com/android/tools/perflib/heap/HprofParser.java b/base/perflib/src/main/java/com/android/tools/perflib/heap/HprofParser.java
+index 80271ab..e4d9767 100644
+--- a/base/perflib/src/main/java/com/android/tools/perflib/heap/HprofParser.java
++++ b/base/perflib/src/main/java/com/android/tools/perflib/heap/HprofParser.java
+@@ -24,7 +24,7 @@ import com.google.common.primitives.UnsignedInts;
+ import java.io.EOFException;
+ import java.io.IOException;
+ 
+-import gnu.trove.TLongObjectHashMap;
++import gnu.trove.map.hash.TLongObjectHashMap;
+ 
+ public class HprofParser {
+ 
+diff --git a/base/perflib/src/main/java/com/android/tools/perflib/heap/NonRecursiveVisitor.java b/base/perflib/src/main/java/com/android/tools/perflib/heap/NonRecursiveVisitor.java
+index c481321..b94f1e9 100644
+--- a/base/perflib/src/main/java/com/android/tools/perflib/heap/NonRecursiveVisitor.java
++++ b/base/perflib/src/main/java/com/android/tools/perflib/heap/NonRecursiveVisitor.java
+@@ -21,7 +21,7 @@ import com.android.annotations.NonNull;
+ import java.util.ArrayDeque;
+ import java.util.Deque;
+ 
+-import gnu.trove.TLongHashSet;
++import gnu.trove.set.hash.TLongHashSet;
+ 
+ /**
+  * Non-recursive depth-first visitor, managing its own stack.
+diff --git a/base/perflib/src/main/java/com/android/tools/perflib/heap/Snapshot.java b/base/perflib/src/main/java/com/android/tools/perflib/heap/Snapshot.java
+index 0b074bf..b216001 100644
+--- a/base/perflib/src/main/java/com/android/tools/perflib/heap/Snapshot.java
++++ b/base/perflib/src/main/java/com/android/tools/perflib/heap/Snapshot.java
+@@ -23,7 +23,7 @@ import com.android.tools.perflib.heap.analysis.ShortestDistanceVisitor;
+ import com.android.tools.perflib.heap.analysis.TopologicalSort;
+ import com.android.tools.perflib.heap.io.HprofBuffer;
+ import com.google.common.collect.ImmutableList;
+-import gnu.trove.THashSet;
++import gnu.trove.set.hash.THashSet;
+ 
+ import java.util.*;
+ 
+diff --git a/base/perflib/src/main/java/com/android/tools/perflib/heap/analysis/TopologicalSort.java b/base/perflib/src/main/java/com/android/tools/perflib/heap/analysis/TopologicalSort.java
+index 3bcc704..02b08cc 100644
+--- a/base/perflib/src/main/java/com/android/tools/perflib/heap/analysis/TopologicalSort.java
++++ b/base/perflib/src/main/java/com/android/tools/perflib/heap/analysis/TopologicalSort.java
+@@ -26,7 +26,7 @@ import com.google.common.collect.Lists;
+ 
+ import java.util.List;
+ 
+-import gnu.trove.TLongHashSet;
++import gnu.trove.set.hash.TLongHashSet;
+ 
+ public class TopologicalSort {
+ 
diff --git a/debian/poms/android-tools-annotations-pom.xml b/debian/poms/android-tools-annotations-pom.xml
new file mode 100644
index 0000000..a5b131a
--- /dev/null
+++ b/debian/poms/android-tools-annotations-pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.android.tools</groupId>
+  <artifactId>annotations</artifactId>
+  <version>24.5.0</version>
+  <description>annotations used throughout the Android tools libraries.</description>
+  <url>http://tools.android.com/</url>
+  <name>com.android.tools.annotations</name>
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <developers>
+    <developer>
+      <name>The Android Open Source Project</name>
+    </developer>
+  </developers>
+  <scm>
+    <connection>git://android.googlesource.com/platform/tools/base.git</connection>
+    <url>https://android.googlesource.com/platform/tools/base</url>
+  </scm>
+</project>
\ No newline at end of file
diff --git a/debian/poms/android-tools-common-pom.xml b/debian/poms/android-tools-common-pom.xml
new file mode 100644
index 0000000..e3e6b9e
--- /dev/null
+++ b/debian/poms/android-tools-common-pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.android.tools</groupId>
+  <artifactId>common</artifactId>
+  <version>24.5.0</version>
+  <dependencies>
+    <dependency>
+      <groupId>com.android.tools</groupId>
+      <artifactId>annotations</artifactId>
+      <version>24.5.0</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>17.0</version>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+  <description>common library used by other Android tools libraries.</description>
+  <url>http://tools.android.com/</url>
+  <name>com.android.tools.common</name>
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <developers>
+    <developer>
+      <name>The Android Open Source Project</name>
+    </developer>
+  </developers>
+  <scm>
+    <connection>git://android.googlesource.com/platform/tools/base.git</connection>
+    <url>https://android.googlesource.com/platform/tools/base</url>
+  </scm>
+</project>
\ No newline at end of file
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..2521765
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,11 @@
+#!/usr/bin/make -f
+
+export JAVA_HOME=/usr/lib/jvm/default-java
+
+%:
+	dh $@ --parallel --with javahelper,maven_repo_helper --buildsystem=gradle
+
+override_dh_auto_build:
+	dh_auto_build -- -x test assemble
+	mv out/build/base/common/build/libs/common-24.5.0.jar com.android.tools.common.jar
+	mv out/build/base/annotations/build/libs/annotations-24.5.0.jar com.android.tools.annotations.jar
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..4bcdd22
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+# This watch file does currently nothing until there is a way to track new
+# upstream releases

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/android-platform-tools-base.git



More information about the pkg-java-commits mailing list