Merge "Snap for 7482986 from 01990004ec2192d7c85bcbfb18f236c60d32828a to androidx-work-release" into androidx-work-release
diff --git a/Android.bp b/Android.bp
index d5ee50e..a3e2317 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,6 +12,41 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["external_doclava_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "external_doclava_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-CC-BY",
+        "SPDX-license-identifier-GPL",
+        "SPDX-license-identifier-GPL-2.0",
+        "SPDX-license-identifier-LGPL",
+        "SPDX-license-identifier-MIT",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 droiddoc_exported_dir {
     name: "droiddoc-templates-sdk",
     path: "res/assets/templates-sdk",
diff --git a/METADATA b/METADATA
index d97975c..95f8f51 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,6 @@
 third_party {
-  license_type: NOTICE
+  # would be NOTICE save for:
+  #   templates/
+  #   templates-sdk/
+  license_type: RESTRICTED
 }
diff --git a/build.gradle b/build.gradle
index 0a0ce4d..4f586df 100644
--- a/build.gradle
+++ b/build.gradle
@@ -47,7 +47,7 @@
         toolsJar = System.env.JAVA_TOOLS_JAR
     } else {
         throw new Exception("If you are not using Java 8, JAVA_TOOLS_JAR env variable " +
-                "needs to be set to build Doclava")
+                "needs to be set to tools.jar from a Java 8 installation to build Doclava")
     }
     implementation(files(toolsJar))
 
diff --git a/res/assets/templates-sdk/compatchanges.cs b/res/assets/templates-sdk/compatchanges.cs
index 001b937..fba233a 100644
--- a/res/assets/templates-sdk/compatchanges.cs
+++ b/res/assets/templates-sdk/compatchanges.cs
@@ -24,9 +24,9 @@
             Disabled for all apps.
         <?cs else ?>
             Enabled for
-            <?cs if:change.enableAfterTargetSdk ?>
-                apps with a <code>targetSdkVersion</code> of greater than
-                <?cs var:change.enableAfterTargetSdk ?>.
+            <?cs if:change.enableSinceTargetSdk ?>
+                apps with a <code>targetSdkVersion</code> of greater than or equal to
+                <?cs var:change.enableSinceTargetSdk ?>.
             <?cs else ?>
                 all apps.
             <?cs /if ?>
diff --git a/src/com/google/doclava/CompatInfo.java b/src/com/google/doclava/CompatInfo.java
index 167f6ab..1999818 100644
--- a/src/com/google/doclava/CompatInfo.java
+++ b/src/com/google/doclava/CompatInfo.java
@@ -44,12 +44,12 @@
     public final int sourceLine;
     public final boolean disabled;
     public final boolean loggingOnly;
-    public final int enableAfterTargetSdk;
+    public final int enableSinceTargetSdk;
 
 
     CompatChange(String name, long id, String description, String definedInClass,
             String sourceFile, int sourceLine, boolean disabled, boolean loggingOnly,
-            int enableAfterTargetSdk) {
+            int enableAfterTargetSdk, int enableSinceTargetSdk) {
       this.name = name;
       this.id = id;
       this.description = description;
@@ -58,7 +58,14 @@
       this.sourceLine = sourceLine;
       this.disabled = disabled;
       this.loggingOnly = loggingOnly;
-      this.enableAfterTargetSdk = enableAfterTargetSdk;
+      if (enableSinceTargetSdk > 0) {
+        this.enableSinceTargetSdk = enableSinceTargetSdk;
+      } else if (enableAfterTargetSdk > 0) {
+        this.enableSinceTargetSdk = enableAfterTargetSdk + 1;
+      } else {
+        this.enableSinceTargetSdk = 0;
+      }
+
     }
 
     static class Builder {
@@ -71,11 +78,12 @@
       private boolean mDisabled;
       private boolean mLoggingOnly;
       private int mEnableAfterTargetSdk;
+      private int mEnableSinceTargetSdk;
 
       CompatChange build() {
         return new CompatChange(
             mName, mId, mDescription, mDefinedInClass, mSourceFile, mSourceLine,
-                mDisabled, mLoggingOnly, mEnableAfterTargetSdk);
+                mDisabled, mLoggingOnly, mEnableAfterTargetSdk, mEnableSinceTargetSdk);
       }
 
       Builder name(String name) {
@@ -144,6 +152,18 @@
         }
         return this;
       }
+      Builder enableSinceTargetSdk(String enableSince) throws SAXException {
+        if (enableSince == null) {
+          mEnableSinceTargetSdk = 0;
+        } else {
+          try {
+            mEnableSinceTargetSdk = Integer.parseInt(enableSince);
+          } catch (NumberFormatException nfe) {
+            throw new SAXException("Invalid SDK version int: " + enableSince, nfe);
+          }
+        }
+        return this;
+      }
     }
 
   }
@@ -166,6 +186,7 @@
         mCurrentChange.name(attributes.getValue("name"))
                 .description(attributes.getValue("description"))
                 .enableAfterTargetSdk(attributes.getValue("enableAfterTargetSdk"))
+                .enableSinceTargetSdk(attributes.getValue("enableSinceTargetSdk"))
                 .disabled(attributes.getValue("disabled"))
                 .loggingOnly(attributes.getValue("loggingOnly"));
 
@@ -232,16 +253,16 @@
         definedInContainer = Converter.obtainPackage("android");
       }
       if (change.description == null) {
-        throw new RuntimeException("No desriprion found for @ChangeId " + change.name);
+        throw new RuntimeException("No description found for @ChangeId " + change.name);
       }
       Comment comment = new Comment(change.description, definedInContainer, new SourcePositionInfo(
           change.sourceFile, change.sourceLine, 1));
       String path = "change." + i;
       hdf.setValue(path + ".id", Long.toString(change.id));
       hdf.setValue(path + ".name", change.name);
-      if (change.enableAfterTargetSdk != 0) {
-        hdf.setValue(path + ".enableAfterTargetSdk",
-            Integer.toString(change.enableAfterTargetSdk));
+      if (change.enableSinceTargetSdk != 0) {
+        hdf.setValue(path + ".enableSinceTargetSdk",
+            Integer.toString(change.enableSinceTargetSdk));
       }
       if (change.loggingOnly) {
         hdf.setValue(path + ".loggingOnly", Boolean.toString(true));