[KeepAnno] Add `constraintAdditions` to UsedBy annotations

Bug: b/248408342
Change-Id: I89d0770e878810950137c4ed49f1cab8476a992a
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java
index 2bcf8dd..6157cbd 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByNative.java
@@ -111,11 +111,27 @@
    *   <li>{@link KeepConstraint#FIELD_SET}
    * </ul>
    *
+   * <p>Mutually exclusive with the property `constraintAdditions` also defining constraints.
+   *
    * @return Usage constraints for the target.
    */
   KeepConstraint[] constraints() default {};
 
   /**
+   * Add additional usage constraints of the target.
+   *
+   * <p>The specified constraints must remain valid for the target in addition to the default
+   * constraints.
+   *
+   * <p>The default constraints are documented in {@link #constraints}
+   *
+   * <p>Mutually exclusive with the property `constraints` also defining constraints.
+   *
+   * @return Additional usage constraints for the target.
+   */
+  KeepConstraint[] constraintAdditions() default {};
+
+  /**
    * Define the member-annotated-by pattern by fully qualified class name.
    *
    * <p>Mutually exclusive with the following other properties defining member-annotated-by:
diff --git a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java
index 7133e96..17add2d 100644
--- a/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java
+++ b/src/keepanno/java/com/android/tools/r8/keepanno/annotations/UsedByReflection.java
@@ -111,11 +111,27 @@
    *   <li>{@link KeepConstraint#FIELD_SET}
    * </ul>
    *
+   * <p>Mutually exclusive with the property `constraintAdditions` also defining constraints.
+   *
    * @return Usage constraints for the target.
    */
   KeepConstraint[] constraints() default {};
 
   /**
+   * Add additional usage constraints of the target.
+   *
+   * <p>The specified constraints must remain valid for the target in addition to the default
+   * constraints.
+   *
+   * <p>The default constraints are documented in {@link #constraints}
+   *
+   * <p>Mutually exclusive with the property `constraints` also defining constraints.
+   *
+   * @return Additional usage constraints for the target.
+   */
+  KeepConstraint[] constraintAdditions() default {};
+
+  /**
    * Define the member-annotated-by pattern by fully qualified class name.
    *
    * <p>Mutually exclusive with the following other properties defining member-annotated-by:
diff --git a/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java b/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java
index b3a1579..19e2290 100644
--- a/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java
+++ b/src/test/java/com/android/tools/r8/keepanno/KeepUsedByNativeAnnotationTest.java
@@ -11,12 +11,16 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.keepanno.annotations.KeepCondition;
+import com.android.tools.r8.keepanno.annotations.KeepConstraint;
 import com.android.tools.r8.keepanno.annotations.KeepItemKind;
 import com.android.tools.r8.keepanno.annotations.UsedByNative;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.google.common.collect.ImmutableList;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.Method;
 import java.util.List;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -25,7 +29,7 @@
 @RunWith(Parameterized.class)
 public class KeepUsedByNativeAnnotationTest extends TestBase {
 
-  static final String EXPECTED = StringUtils.lines("Hello, world");
+  static final String EXPECTED = StringUtils.lines("@Anno.value = anno-on-bar", "Hello, world");
 
   private final TestParameters parameters;
 
@@ -59,7 +63,7 @@
   }
 
   public List<Class<?>> getInputClasses() {
-    return ImmutableList.of(TestClass.class, A.class, B.class, C.class);
+    return ImmutableList.of(TestClass.class, Anno.class, A.class, B.class, C.class);
   }
 
   private void checkOutput(CodeInspector inspector) {
@@ -71,6 +75,11 @@
     assertThat(inspector.clazz(B.class).method("void", "bar", "int"), isAbsent());
   }
 
+  @Retention(RetentionPolicy.RUNTIME)
+  private @interface Anno {
+    String value();
+  }
+
   @UsedByNative(
       description = "Ensure that the class A remains as we are assuming the contents of its name.",
       preconditions = {@KeepCondition(classConstant = A.class, methodName = "foo")},
@@ -81,7 +90,10 @@
 
     public void foo() throws Exception {
       Class<?> clazz = Class.forName(A.class.getTypeName().replace("$A", "$B"));
-      clazz.getDeclaredMethod("bar").invoke(clazz);
+      Method bar = clazz.getDeclaredMethod("bar");
+      Anno annotation = bar.getAnnotation(Anno.class);
+      System.out.println("@Anno.value = " + annotation.value());
+      bar.invoke(clazz);
     }
 
     public void bar() {
@@ -95,7 +107,9 @@
         // Only if A.foo is live do we need to keep this.
         preconditions = {@KeepCondition(classConstant = A.class, methodName = "foo")},
         // Both the class and method are reflectively accessed.
-        kind = KeepItemKind.CLASS_AND_MEMBERS)
+        kind = KeepItemKind.CLASS_AND_MEMBERS,
+        constraintAdditions = {KeepConstraint.ANNOTATIONS})
+    @Anno("anno-on-bar")
     public static void bar() {
       System.out.println("Hello, world");
     }
diff --git a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
index c6bb24b..0852bde 100644
--- a/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
+++ b/src/test/java/com/android/tools/r8/keepanno/utils/KeepItemAnnotationGenerator.java
@@ -1294,7 +1294,7 @@
                         + " if annotating a member.")
                 .generate(this);
             println();
-            constraints().generate(this);
+            getKeepConstraintsGroup().generate(this);
             println();
             generateMemberPropertiesNoBinding();
           });