diff --git a/build.gradle b/build.gradle
index 1fb56b1b6507ea6b2384e4893c5240c44b04ade8..ad5e88029928872ad5b64e5718e7e519d90df19f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -109,7 +109,7 @@ configurations {
 }
 
 dependencies {
-    ktlint "com.github.shyiko:ktlint:0.29.0"
+    ktlint "com.github.shyiko:ktlint:0.30.0"
 }
 
 task ktlint(type: JavaExec, group: "verification") {
diff --git a/src/main/java/com/android/tools/metalava/DocAnalyzer.kt b/src/main/java/com/android/tools/metalava/DocAnalyzer.kt
index b831a5b39dccb1e9c8117f4f7ac00ed08ae60f0c..13f02a9382344b571bea27785be99c818f7265e8 100644
--- a/src/main/java/com/android/tools/metalava/DocAnalyzer.kt
+++ b/src/main/java/com/android/tools/metalava/DocAnalyzer.kt
@@ -701,7 +701,7 @@ class DocAnalyzer(
         if (level > 1) {
             // TODO: *pre*pend instead!
             val description =
-                "<p class=\"caution\"><strong>This class was deprecated in API level 21.</strong></p>"
+                "<p class=\"caution\"><strong>This class was deprecated in API level $level.</strong></p>"
             item.appendDocumentation(description, "@deprecated", append = false)
         }
     }
diff --git a/src/main/java/com/android/tools/metalava/Driver.kt b/src/main/java/com/android/tools/metalava/Driver.kt
index a1c3bf27aa42a79a5c4d5ec6af8aa9e270b4674e..19d6749c035e37a7ab9d52ce535bf36430d7ec4b 100644
--- a/src/main/java/com/android/tools/metalava/Driver.kt
+++ b/src/main/java/com/android/tools/metalava/Driver.kt
@@ -17,9 +17,10 @@
 
 package com.android.tools.metalava
 
-import com.android.SdkConstants
+import com.android.SdkConstants.DOT_JAR
 import com.android.SdkConstants.DOT_JAVA
 import com.android.SdkConstants.DOT_KT
+import com.android.SdkConstants.DOT_TXT
 import com.android.ide.common.process.CachedProcessOutputHandler
 import com.android.ide.common.process.DefaultProcessExecutor
 import com.android.ide.common.process.ProcessInfoBuilder
@@ -37,6 +38,7 @@ import com.android.tools.metalava.doclava1.ApiPredicate
 import com.android.tools.metalava.doclava1.Errors
 import com.android.tools.metalava.doclava1.FilterPredicate
 import com.android.tools.metalava.doclava1.TextCodebase
+import com.android.tools.metalava.model.ClassItem
 import com.android.tools.metalava.model.Codebase
 import com.android.tools.metalava.model.Item
 import com.android.tools.metalava.model.PackageDocs
@@ -207,14 +209,14 @@ private fun processFlags() {
     processNonCodebaseFlags()
 
     val codebase =
-        if (options.sources.size == 1 && options.sources[0].path.endsWith(SdkConstants.DOT_TXT)) {
+        if (options.sources.size == 1 && options.sources[0].path.endsWith(DOT_TXT)) {
             SignatureFileLoader.load(
                 file = options.sources[0],
                 kotlinStyleNulls = options.inputKotlinStyleNulls
             )
         } else if (options.apiJar != null) {
             loadFromJarFile(options.apiJar!!)
-        } else if (options.sources.size == 1 && options.sources[0].path.endsWith(SdkConstants.DOT_JAR)) {
+        } else if (options.sources.size == 1 && options.sources[0].path.endsWith(DOT_JAR)) {
             loadFromJarFile(options.sources[0])
         } else if (options.sources.isNotEmpty() || options.sourcePath.isNotEmpty()) {
             loadFromSources()
@@ -227,6 +229,10 @@ private fun processFlags() {
         options.stdout.println("\n$PROGRAM_NAME analyzed API in ${stopwatch.elapsed(TimeUnit.SECONDS)} seconds")
     }
 
+    options.subtractApi?.let {
+        subtractApi(codebase, it)
+    }
+
     val androidApiLevelXml = options.generateApiLevelXml
     val apiLevelJars = options.apiLevelJars
     if (androidApiLevelXml != null && apiLevelJars != null) {
@@ -372,7 +378,7 @@ private fun processFlags() {
     val previousApiFile = options.migrateNullsFrom
     if (previousApiFile != null) {
         val previous =
-            if (previousApiFile.path.endsWith(SdkConstants.DOT_JAR)) {
+            if (previousApiFile.path.endsWith(DOT_JAR)) {
                 loadFromJarFile(previousApiFile)
             } else {
                 SignatureFileLoader.load(
@@ -450,6 +456,23 @@ private fun processFlags() {
     invokeDocumentationTool()
 }
 
+fun subtractApi(codebase: Codebase, subtractApiFile: File) {
+    val path = subtractApiFile.path
+    val oldCodebase =
+        when {
+            path.endsWith(DOT_TXT) -> SignatureFileLoader.load(subtractApiFile)
+            path.endsWith(DOT_JAR) -> loadFromJarFile(subtractApiFile)
+            else -> throw DriverException("Unsupported $ARG_SUBTRACT_API format, expected .txt or .jar: ${subtractApiFile.name}")
+        }
+
+    CodebaseComparator().compare(object : ComparisonVisitor() {
+        override fun compare(old: ClassItem, new: ClassItem) {
+            new.included = false
+            new.emit = false
+        }
+    }, oldCodebase, codebase, ApiType.ALL.getReferenceFilter())
+}
+
 fun processNonCodebaseFlags() {
     // --copy-annotations?
     val privateAnnotationsSource = options.privateAnnotationsSource
@@ -554,7 +577,7 @@ fun checkCompatibility(
     val signatureFile = check.file
 
     val current =
-        if (signatureFile.path.endsWith(SdkConstants.DOT_JAR)) {
+        if (signatureFile.path.endsWith(DOT_JAR)) {
             loadFromJarFile(signatureFile)
         } else {
             SignatureFileLoader.load(
@@ -801,7 +824,7 @@ private fun loadFromSources(): Codebase {
         val previous =
             when {
                 previousApiFile == null -> null
-                previousApiFile.path.endsWith(SdkConstants.DOT_JAR) -> loadFromJarFile(previousApiFile)
+                previousApiFile.path.endsWith(DOT_JAR) -> loadFromJarFile(previousApiFile)
                 else -> SignatureFileLoader.load(
                     file = previousApiFile,
                     kotlinStyleNulls = options.inputKotlinStyleNulls
@@ -863,7 +886,7 @@ internal fun parseSources(
     // Create project environment with those paths
     projectEnvironment.registerPaths(joined)
 
-    val kotlinFiles = sources.filter { it.path.endsWith(SdkConstants.DOT_KT) }
+    val kotlinFiles = sources.filter { it.path.endsWith(DOT_KT) }
     val trace = KotlinLintAnalyzerFacade().analyze(kotlinFiles, joined, project)
 
     val rootDir = sourceRoots.firstOrNull() ?: sourcePath.firstOrNull() ?: File("").canonicalFile
diff --git a/src/main/java/com/android/tools/metalava/Options.kt b/src/main/java/com/android/tools/metalava/Options.kt
index 8afb8cb5fd51ca34fb911a6fab223f35851b8f6f..c2c354b720c71bf50b557c2b65154f298f43ca92 100644
--- a/src/main/java/com/android/tools/metalava/Options.kt
+++ b/src/main/java/com/android/tools/metalava/Options.kt
@@ -136,7 +136,8 @@ const val ARG_INCLUDE_ANNOTATION_CLASSES = "--include-annotation-classes"
 const val ARG_REWRITE_ANNOTATIONS = "--rewrite-annotations"
 const val ARG_INCLUDE_SOURCE_RETENTION = "--include-source-retention"
 const val ARG_INCLUDE_SIG_VERSION = "--include-signature-version"
-const val ARG_UPDATE_API = "--update-api"
+const val ARG_UPDATE_API = "--only-update-api"
+const val ARG_CHECK_API = "--only-check-api"
 const val ARG_PASS_BASELINE_UPDATES = "--pass-baseline-updates"
 const val ARG_DEX_API_MAPPING = "--dex-api-mapping"
 const val ARG_GENERATE_DOCUMENTATION = "--generate-documentation"
@@ -146,6 +147,7 @@ const val ARG_MERGE_BASELINE = "--merge-baseline"
 const val ARG_STUB_PACKAGES = "--stub-packages"
 const val ARG_STUB_IMPORT_PACKAGES = "--stub-import-packages"
 const val ARG_DELETE_EMPTY_BASELINES = "--delete-empty-baselines"
+const val ARG_SUBTRACT_API = "--subtract-api"
 
 class Options(
     private val args: Array<String>,
@@ -197,6 +199,9 @@ class Options(
      */
     var noDocs = false
 
+    /** API to subtract from signature and stub generation. Corresponds to [ARG_SUBTRACT_API]. */
+    var subtractApi: File? = null
+
     /**
      * Validator for nullability annotations, if validation is enabled.
      */
@@ -241,7 +246,20 @@ class Options(
      * signature files. This avoids having duplicate metalava invocation logic where potentially newly
      * added flags are missing in one of the invocations etc.
      */
-    var updateApi = false
+    var onlyUpdateApi = false
+
+    /**
+     * Whether metalava is invoked as part of running the checkapi target. When this is true, metalava
+     * should *cancel* various other flags that are also being passed in, such as updating signature
+     * files.
+     *
+     * This is there to ease integration in the build system: for a given target, the build system will
+     * pass all the applicable flags (--stubs, --api, --check-compatibility, --generate-documentation, etc),
+     * and this integration is re-used for the checkapi facility where we *only* want to run compatibility
+     * checks. This avoids having duplicate metalava invocation logic where potentially newly
+     * added flags are missing in one of the invocations etc.
+     */
+    var onlyCheckApi = false
 
     /**
      * Whether signature files should emit in "compat" mode, preserving the various
@@ -406,7 +424,7 @@ class Options(
     var removedDexApiFile: File? = null
 
     /** Whether output should be colorized */
-    var color = System.getenv("TERM")?.startsWith("xterm") ?: false
+    var color = System.getenv("TERM")?.startsWith("xterm") ?: System.getenv("COLORTERM") != null ?: false
 
     /** Whether to omit Java and Kotlin runtime library packages from annotation coverage stats */
     var omitRuntimePackageStats = false
@@ -420,7 +438,7 @@ class Options(
     var migrateNullsFrom: File? = null
 
     /** Private backing list for [compatibilityChecks]] */
-    private var mutableCompatibilityChecks: MutableList<CheckRequest> = mutableListOf()
+    private val mutableCompatibilityChecks: MutableList<CheckRequest> = mutableListOf()
 
     /** The list of compatibility checks to run */
     val compatibilityChecks: List<CheckRequest> = mutableCompatibilityChecks
@@ -631,6 +649,13 @@ class Options(
                     }
                 }
 
+                ARG_SUBTRACT_API -> {
+                    if (subtractApi != null) {
+                        throw DriverException(stderr = "Only one $ARG_SUBTRACT_API can be supplied")
+                    }
+                    subtractApi = stringToExistingFile(getValue(args, ++index))
+                }
+
                 // TODO: Remove the legacy --merge-annotations flag once it's no longer used to update P docs
                 ARG_MERGE_QUALIFIER_ANNOTATIONS, "--merge-zips", "--merge-annotations" -> mutableMergeQualifierAnnotations.addAll(
                     stringToExistingDirsOrFiles(
@@ -986,7 +1011,8 @@ class Options(
 
                 ARG_NO_DOCS, "-nodocs" -> noDocs = true
 
-                ARG_UPDATE_API -> updateApi = true
+                ARG_UPDATE_API, "--update-api" -> onlyUpdateApi = true
+                ARG_CHECK_API -> onlyCheckApi = true
 
                 ARG_GENERATE_DOCUMENTATION -> {
                     // Digest all the remaining arguments.
@@ -1350,7 +1376,10 @@ class Options(
             generateAnnotations = false
         }
 
-        if (updateApi) {
+        if (onlyUpdateApi) {
+            if (onlyCheckApi) {
+                throw DriverException(stderr = "Cannot supply both $ARG_UPDATE_API and $ARG_CHECK_API at the same time")
+            }
             // We're running in update API mode: cancel other "action" flags; only signature file generation
             // flags count
             annotationCoverageClassReport = null
@@ -1373,6 +1402,46 @@ class Options(
             mutableCompatibilityChecks.clear()
             mutableAnnotationCoverageOf.clear()
             artifactRegistrations.clear()
+            mutableConvertToXmlFiles.clear()
+            nullabilityAnnotationsValidator = null
+            nullabilityWarningsTxt = null
+            validateNullabilityFromMergedStubs = false
+            validateNullabilityFromMergedStubs = false
+            validateNullabilityFromList = null
+        } else if (onlyCheckApi) {
+            annotationCoverageClassReport = null
+            annotationCoverageMemberReport = null
+            dumpAnnotationStatistics = false
+            apiLevelJars = null
+            generateApiLevelXml = null
+            applyApiLevelsXml = null
+            androidJarSignatureFiles = null
+            stubsDir = null
+            docStubsDir = null
+            stubsSourceList = null
+            docStubsSourceList = null
+            sdkValueDir = null
+            externalAnnotations = null
+            proguard = null
+            noDocs = true
+            invokeDocumentationToolArguments = emptyArray()
+            checkKotlinInterop = false
+            mutableAnnotationCoverageOf.clear()
+            artifactRegistrations.clear()
+            mutableConvertToXmlFiles.clear()
+            nullabilityAnnotationsValidator = null
+            nullabilityWarningsTxt = null
+            validateNullabilityFromMergedStubs = false
+            validateNullabilityFromMergedStubs = false
+            validateNullabilityFromList = null
+            apiFile = null
+            apiXmlFile = null
+            privateApiFile = null
+            dexApiFile = null
+            dexApiMappingFile = null
+            privateDexApiFile = null
+            removedApiFile = null
+            removedDexApiFile = null
         }
 
         if (baselineFile == null) {
@@ -1790,6 +1859,8 @@ class Options(
                 "to make it easier customize build system tasks.",
             ARG_UPDATE_API, "Cancel any other \"action\" flags other than generating signature files. This is here " +
                 "to make it easier customize build system tasks, particularly for the \"make update-api\" task.",
+            ARG_CHECK_API, "Cancel any other \"action\" flags other than checking signature files. This is here " +
+                "to make it easier customize build system tasks, particularly for the \"make checkapi\" task.",
 
             "", "\nAPI sources:",
             "$ARG_SOURCE_FILES <files>", "A comma separated list of source files to be parsed. Can also be " +
@@ -1841,11 +1912,14 @@ class Options(
                 "as hidden",
             ARG_SHOW_UNANNOTATED, "Include un-annotated public APIs in the signature file as well",
             "$ARG_JAVA_SOURCE <level>", "Sets the source level for Java source files; default is 1.8.",
-            "$ARG_STUB_PACKAGES <path>", "List of packages (separated by ${File.pathSeparator} which will be " +
-                "used to filter out irrelevant code. If specified, only code in these packages will be " +
+            "$ARG_STUB_PACKAGES <package-list>", "List of packages (separated by ${File.pathSeparator}) which will " +
+                "be used to filter out irrelevant code. If specified, only code in these packages will be " +
                 "included in signature files, stubs, etc. (This is not limited to just the stubs; the name " +
                 "is historical.) You can also use \".*\" at the end to match subpackages, so `foo.*` will " +
                 "match both `foo` and `foo.bar`.",
+            "$ARG_SUBTRACT_API <api file>", "Subtracts the API in the given signature or jar file from the " +
+                "current API being emitted via $ARG_API, $ARG_STUBS, $ARG_DOC_STUBS, etc. " +
+                "Note that the subtraction only applies to classes; it does not subtract members.",
 
             "", "\nDocumentation:",
             ARG_PUBLIC, "Only include elements that are public",
diff --git a/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt b/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt
index 205e133d87271d08bc70aab0eb901a3bba660183..99d76a338ad2a98b5740251f05d73cc5c30e9dd3 100644
--- a/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt
+++ b/src/test/java/com/android/tools/metalava/DocAnalyzerTest.kt
@@ -1163,7 +1163,7 @@ class DocAnalyzerTest : DriverTest() {
                             <method name="&lt;init>()V"/>
                             <method name="addCallbackBuffer([B)V" since="8"/>
                             <method name="getLogo()Landroid/graphics/drawable/Drawable;"/>
-                            <field name="ACTION_NEW_VIDEO" since="14" deprecated="25"/>
+                            <field name="ACTION_NEW_VIDEO" since="14" deprecated="19"/>
                         </class>
                     </api>
                     """,
@@ -1186,7 +1186,7 @@ class DocAnalyzerTest : DriverTest() {
                 public Camera() { throw new RuntimeException("Stub!"); }
                 /**
                  * @deprecated
-                 * <p class="caution"><strong>This class was deprecated in API level 21.</strong></p>
+                 * <p class="caution"><strong>This class was deprecated in API level 19.</strong></p>
                  *  Use something else.
                  * @since 14
                  */
diff --git a/src/test/java/com/android/tools/metalava/DriverTest.kt b/src/test/java/com/android/tools/metalava/DriverTest.kt
index 2e790eaa07129141628fb4757f806adacd99809e..9c27ca41e0b8a2d8992f1f2b349857ba0d723e68 100644
--- a/src/test/java/com/android/tools/metalava/DriverTest.kt
+++ b/src/test/java/com/android/tools/metalava/DriverTest.kt
@@ -226,6 +226,9 @@ abstract class DriverTest {
         dexApi: String? = null,
         /** The DEX mapping API (corresponds to --dex-api-mapping) */
         dexApiMapping: String? = null,
+        /** The subtract api signature content (corresponds to --subtract-api) */
+        @Language("TEXT")
+        subtractApi: String? = null,
         /** Expected stubs (corresponds to --stubs) */
         @Language("JAVA") stubs: Array<String> = emptyArray(),
         /** Stub source file list generated */
@@ -773,6 +776,15 @@ abstract class DriverTest {
             emptyArray()
         }
 
+        var subtractApiFile: File? = null
+        val subtractApiArgs = if (subtractApi != null) {
+            subtractApiFile = temporaryFolder.newFile("subtract-api.txt")
+            subtractApiFile.writeText(subtractApi.trimIndent())
+            arrayOf(ARG_SUBTRACT_API, subtractApiFile.path)
+        } else {
+            emptyArray()
+        }
+
         val convertFiles = mutableListOf<Options.ConvertFile>()
         val convertArgs = if (convertToJDiff.isNotEmpty()) {
             val args = mutableListOf<String>()
@@ -998,6 +1010,7 @@ abstract class DriverTest {
             *dexApiArgs,
             *privateDexApiArgs,
             *dexApiMappingArgs,
+            *subtractApiArgs,
             *stubsArgs,
             *stubsSourceListArgs,
             "$ARG_COMPAT_OUTPUT=${if (compatibilityMode) "yes" else "no"}",
@@ -1276,7 +1289,10 @@ abstract class DriverTest {
                 "${stubsSourceListFile.path} does not exist even though --write-stubs-source-list was used",
                 stubsSourceListFile.exists()
             )
-            val actualText = readFile(stubsSourceListFile, stripBlankLines, trim)
+            val actualText = cleanupString(readFile(stubsSourceListFile, stripBlankLines, trim), project)
+                // To make golden files look better put one entry per line instead of a single
+                // space separated line
+                .replace(' ', '\n')
             assertEquals(stripComments(stubsSourceList, stripLineComments = false).trimIndent(), actualText)
         }
 
diff --git a/src/test/java/com/android/tools/metalava/OptionsTest.kt b/src/test/java/com/android/tools/metalava/OptionsTest.kt
index 36d02bf03f2735ac1277cb4e3293ab13f91f6a2f..d625725a9be67f692a8e360a1fa0e1ee76f89f53 100644
--- a/src/test/java/com/android/tools/metalava/OptionsTest.kt
+++ b/src/test/java/com/android/tools/metalava/OptionsTest.kt
@@ -42,10 +42,14 @@ General:
 --no-docs                                 Cancel any other documentation flags supplied to
                                           metalava. This is here to make it easier
                                           customize build system tasks.
---update-api                              Cancel any other "action" flags other than
+--only-update-api                         Cancel any other "action" flags other than
                                           generating signature files. This is here to make
                                           it easier customize build system tasks,
                                           particularly for the "make update-api" task.
+--only-check-api                          Cancel any other "action" flags other than
+                                          checking signature files. This is here to make
+                                          it easier customize build system tasks,
+                                          particularly for the "make checkapi" task.
 
 API sources:
 --source-files <files>                    A comma separated list of source files to be
@@ -104,7 +108,7 @@ API sources:
                                           signature file as well
 --java-source <level>                     Sets the source level for Java source files;
                                           default is 1.8.
---stub-packages <path>                    List of packages (separated by : which will be
+--stub-packages <package-list>            List of packages (separated by :) which will be
                                           used to filter out irrelevant code. If
                                           specified, only code in these packages will be
                                           included in signature files, stubs, etc. (This
@@ -112,6 +116,11 @@ API sources:
                                           historical.) You can also use ".*" at the end to
                                           match subpackages, so `foo.*` will match both
                                           `foo` and `foo.bar`.
+--subtract-api <api file>                 Subtracts the API in the given signature or jar
+                                          file from the current API being emitted via
+                                          --api, --stubs, --doc-stubs, etc. Note that the
+                                          subtraction only applies to classes; it does not
+                                          subtract members.
 
 Documentation:
 --public                                  Only include elements that are public
diff --git a/src/test/java/com/android/tools/metalava/StubsTest.kt b/src/test/java/com/android/tools/metalava/StubsTest.kt
index 3143036218d450022a35bf0d0422b7127c7df4c0..b8719ed7a0716911fdccb69ff84ec0b1ef4454cd 100644
--- a/src/test/java/com/android/tools/metalava/StubsTest.kt
+++ b/src/test/java/com/android/tools/metalava/StubsTest.kt
@@ -1995,7 +1995,13 @@ class StubsTest : DriverTest() {
                 public MySubClass2() { super(0); throw new RuntimeException("Stub!"); }
                 }
                 """
-            )
+            ),
+            stubsSourceList = """
+                TESTROOT/stubs/test/pkg/MyClass1.java
+                TESTROOT/stubs/test/pkg/MyClass2.java
+                TESTROOT/stubs/test/pkg/MySubClass1.java
+                TESTROOT/stubs/test/pkg/MySubClass2.java
+            """
         )
     }
 
@@ -3715,6 +3721,41 @@ class StubsTest : DriverTest() {
         )
     }
 
+    @Test(expected = AssertionError::class)
+    fun `Test check-api should not generate stubs or API files`() {
+        check(
+            extraArguments = arrayOf(
+                ARG_CHECK_API,
+                ARG_EXCLUDE_ANNOTATIONS
+            ),
+            compatibilityMode = false,
+            sourceFiles = *arrayOf(
+                java(
+                    """
+                    package test.pkg;
+                    public class Foo {
+                        /**
+                         * @deprecated Use checkPermission instead.
+                         */
+                        @Deprecated
+                        protected boolean inClass(String name) {
+                            return false;
+                        }
+                    }
+                    """
+                )
+            ),
+            api = """
+            package test.pkg {
+              public class Foo {
+                ctor public Foo();
+                method @Deprecated protected boolean inClass(String);
+              }
+            }
+            """
+        )
+    }
+
     @Test
     fun `Include package private classes referenced from public API`() {
         // Real world example: android.net.http.Connection in apache-http referenced from RequestHandle
diff --git a/src/test/java/com/android/tools/metalava/SubtractApiTest.kt b/src/test/java/com/android/tools/metalava/SubtractApiTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..02cb8dd92dd7114484dbf35aeb809760c719958e
--- /dev/null
+++ b/src/test/java/com/android/tools/metalava/SubtractApiTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+@file:Suppress("ALL")
+
+package com.android.tools.metalava
+
+import org.junit.Test
+
+class SubtractApiTest : DriverTest() {
+    @Test
+    fun `Subtract APIs`() {
+        check(
+            sourceFiles = *arrayOf(
+                java(
+                    """
+                    package test.pkg;
+                    public class OnlyInNew {
+                        private OnlyInNew() { }
+                        public void method1() { }
+                        public void method5() { }
+                        public void method6() { }
+                    }
+                    """
+                ),
+                java(
+                    """
+                    package test.pkg;
+                    public class InBoth {
+                        private InBoth() { }
+                        public void method1() { }
+                        public void method5() { }
+                        public void method9() { }
+                    }
+                    """
+                )
+            ),
+            subtractApi = """
+                package test.pkg {
+                  public class InBoth {
+                    method public void method1();
+                    method public void method5();
+                    method public void method9();
+                  }
+                  public class OnlyInOld {
+                    method public void method1();
+                    method public void method2();
+                    method public void method3();
+                  }
+                }
+                """,
+            api = """
+                package test.pkg {
+                  public class OnlyInNew {
+                    method public void method1();
+                    method public void method5();
+                    method public void method6();
+                  }
+                }
+                """,
+            stubs = arrayOf(
+                """
+                package test.pkg;
+                @SuppressWarnings({"unchecked", "deprecation", "all"})
+                public class OnlyInNew {
+                OnlyInNew() { throw new RuntimeException("Stub!"); }
+                public void method1() { throw new RuntimeException("Stub!"); }
+                public void method5() { throw new RuntimeException("Stub!"); }
+                public void method6() { throw new RuntimeException("Stub!"); }
+                }
+                """
+            ),
+            stubsSourceList = """
+                TESTROOT/stubs/test/pkg/OnlyInNew.java
+            """
+        )
+    }
+}