Revert^2 "Add @RequiresApi annotation to generated code for repeated fields"

This reverts commit 2d28ba26be981ea1a85b0dc32ced997401b6fb2b.

Reason for revert: Original breakage fixed by aosp/3014753

Change-Id: I9e6120ebc63786d3f67af0cfe3c94b1087d61eed
diff --git a/stats/stats_log_api_gen/java_writer.cpp b/stats/stats_log_api_gen/java_writer.cpp
index dae0c0e..3c84b54 100644
--- a/stats/stats_log_api_gen/java_writer.cpp
+++ b/stats/stats_log_api_gen/java_writer.cpp
@@ -18,6 +18,8 @@
 
 #include <stdio.h>
 
+#include <algorithm>
+
 #include "Collation.h"
 #include "java_writer_q.h"
 #include "utils.h"
@@ -42,6 +44,9 @@
     return 0;
 }
 
+// TODO(b/330817229): Get rid of these generated constants and inline the logic inside the generated
+// write/buildStatsEvent methods. Also add @RequiresApi support for annotations added in S and
+// earlier.
 static void write_java_annotation_constants(FILE* out, const int minApiLevel) {
     fprintf(out, "    // Annotation constants.\n");
 
@@ -51,16 +56,18 @@
         if (annotation.minApiLevel >= API_U) {  // we don't generate annotation constants for U+
             continue;
         }
+        fprintf(out, "    @android.annotation.SuppressLint(\"InlinedApi\")\n",
+                annotation.name.c_str());
         if (minApiLevel <= API_R) {
             fprintf(out, "    public static final byte %s =\n", annotation.name.c_str());
             fprintf(out, "            Build.VERSION.SDK_INT <= %s ?\n",
                     get_java_build_version_code(API_R).c_str());
             fprintf(out, "            %hhu : StatsLog.%s;\n", id, annotation.name.c_str());
-            fprintf(out, "\n");
         } else {
             fprintf(out, "    public static final byte %s = StatsLog.%s;\n",
                     annotation.name.c_str(), annotation.name.c_str());
         }
+        fprintf(out, "\n");
     }
 
     fprintf(out, "\n");
@@ -127,8 +134,7 @@
 
 static int write_method_body(FILE* out, const vector<java_type_t>& signature,
                              const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
-                             const AtomDecl& attributionDecl, const string& indent,
-                             const int minApiLevel) {
+                             const AtomDecl& attributionDecl, const string& indent) {
     // Start StatsEvent.Builder.
     fprintf(out,
             "%s        final StatsEvent.Builder builder = "
@@ -143,10 +149,6 @@
     int argIndex = 1;
     for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
          arg++) {
-        if (minApiLevel < API_T && is_repeated_field(*arg)) {
-            fprintf(stderr, "Found repeated field type with min api level < T.");
-            return 1;
-        }
         switch (*arg) {
             case JAVA_TYPE_BOOLEAN:
                 fprintf(out, "%s        builder.writeBoolean(arg%d);\n", indent.c_str(), argIndex);
@@ -220,25 +222,32 @@
     return 0;
 }
 
+static void write_requires_api_annotation(FILE* out, int minApiLevel,
+                                          const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
+                                          const vector<java_type_t>& signature) {
+    const auto fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet.find(ATOM_ID_FIELD_NUMBER);
+    const AtomDeclSet* atomDeclSet = fieldNumberToAtomDeclSetIt == fieldNumberToAtomDeclSet.end()
+                                             ? nullptr
+                                             : &fieldNumberToAtomDeclSetIt->second;
+    const int maxRequiresApiLevel = get_max_requires_api_level(minApiLevel, atomDeclSet, signature);
+    if (maxRequiresApiLevel > 0) {
+        // Suppress lint error complaining the @RequiresApi annotation is unnecessary because
+        // minSdk of the binary is already at least the SDK level specified in @RequiresApi.
+        fprintf(out, "    @android.annotation.SuppressLint(\"ObsoleteSdkInt\")\n");
+        fprintf(out, "    @RequiresApi(%s)\n",
+                get_java_build_version_code(maxRequiresApiLevel).c_str());
+    }
+}
+
 static int write_java_pushed_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
                                      const AtomDecl& attributionDecl, const int minApiLevel) {
     for (auto signatureInfoMapIt = signatureInfoMap.begin();
          signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
         const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
-        const FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
-                fieldNumberToAtomDeclSet.find(ATOM_ID_FIELD_NUMBER);
-        const AtomDeclSet* atomDeclSet =
-                fieldNumberToAtomDeclSetIt == fieldNumberToAtomDeclSet.end()
-                        ? nullptr
-                        : &fieldNumberToAtomDeclSetIt->second;
-        const int requiresApiLevel = get_requires_api_level(minApiLevel, atomDeclSet);
-        if (requiresApiLevel != API_LEVEL_CURRENT) {
-            fprintf(out, "    @RequiresApi(%s)\n",
-                    get_java_build_version_code(requiresApiLevel).c_str());
-        }
+        const vector<java_type_t>& signature = signatureInfoMapIt->first;
+        write_requires_api_annotation(out, minApiLevel, fieldNumberToAtomDeclSet, signature);
         // Print method signature.
         fprintf(out, "    public static void write(int code");
-        const vector<java_type_t>& signature = signatureInfoMapIt->first;
         write_java_method_signature(out, signature, attributionDecl);
         fprintf(out, ") {\n");
 
@@ -251,7 +260,7 @@
         }
 
         const int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet, attributionDecl,
-                                          indent, minApiLevel);
+                                          indent);
         if (ret != 0) {
             return ret;
         }
@@ -294,10 +303,11 @@
                                      const AtomDecl& attributionDecl, const int minApiLevel) {
     for (auto signatureInfoMapIt = signatureInfoMap.begin();
          signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
-        // Print method signature.
-        fprintf(out, "    public static StatsEvent buildStatsEvent(int code");
         const vector<java_type_t>& signature = signatureInfoMapIt->first;
         const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
+        write_requires_api_annotation(out, minApiLevel, fieldNumberToAtomDeclSet, signature);
+        // Print method signature.
+        fprintf(out, "    public static StatsEvent buildStatsEvent(int code");
         int ret = write_java_method_signature(out, signature, attributionDecl);
         if (ret != 0) {
             return ret;
@@ -306,8 +316,7 @@
 
         // Print method body.
         const string indent("");
-        ret = write_method_body(out, signature, fieldNumberToAtomDeclSet, attributionDecl,
-                                    indent, minApiLevel);
+        ret = write_method_body(out, signature, fieldNumberToAtomDeclSet, attributionDecl, indent);
         if (ret != 0) {
             return ret;
         }
@@ -321,6 +330,21 @@
     return 0;
 }
 
+static int get_max_requires_api_level(int minApiLevel, const SignatureInfoMap& signatureInfoMap) {
+    int maxRequiresApiLevel = 0;
+    for (const auto& [signature, fieldNumberToAtomDeclSet] : signatureInfoMap) {
+        const auto fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet.find(ATOM_ID_FIELD_NUMBER);
+        const AtomDeclSet* atomDeclSet =
+                fieldNumberToAtomDeclSetIt == fieldNumberToAtomDeclSet.end()
+                        ? nullptr
+                        : &fieldNumberToAtomDeclSetIt->second;
+        maxRequiresApiLevel =
+                std::max(maxRequiresApiLevel,
+                         get_max_requires_api_level(minApiLevel, atomDeclSet, signature));
+    }
+    return maxRequiresApiLevel;
+}
+
 int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
                          const string& javaClass, const string& javaPackage, const int minApiLevel,
                          const bool supportWorkSource) {
@@ -337,7 +361,10 @@
 
     fprintf(out, "import android.util.StatsEvent;\n");
     fprintf(out, "import android.util.StatsLog;\n");
-    if (get_requires_api_level(minApiLevel, &atoms.decls) != API_LEVEL_CURRENT) {
+    const int maxRequiresApiLevel =
+            std::max(get_max_requires_api_level(minApiLevel, atoms.signatureInfoMap),
+                     get_max_requires_api_level(minApiLevel, atoms.pulledAtomsSignatureInfoMap));
+    if (maxRequiresApiLevel > 0) {
         fprintf(out, "import androidx.annotation.RequiresApi;\n");
     }
 
diff --git a/stats/stats_log_api_gen/main.cpp b/stats/stats_log_api_gen/main.cpp
index 7533708..f18b955 100644
--- a/stats/stats_log_api_gen/main.cpp
+++ b/stats/stats_log_api_gen/main.cpp
@@ -1,5 +1,4 @@
 
-#include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/common.h>
 #include <stdio.h>
diff --git a/stats/stats_log_api_gen/utils.cpp b/stats/stats_log_api_gen/utils.cpp
index 19a403a..94efdca 100644
--- a/stats/stats_log_api_gen/utils.cpp
+++ b/stats/stats_log_api_gen/utils.cpp
@@ -655,14 +655,34 @@
     return false;
 }
 
-int get_requires_api_level(int minApiLevel, const AtomDeclSet* atomDeclSet) {
+static bool contains_repeated_field(const vector<java_type_t>& signature) {
+    for (const java_type_t& javaType : signature) {
+        switch (javaType) {
+            case JAVA_TYPE_BOOLEAN_ARRAY:
+            case JAVA_TYPE_INT_ARRAY:
+            case JAVA_TYPE_FLOAT_ARRAY:
+            case JAVA_TYPE_LONG_ARRAY:
+            case JAVA_TYPE_STRING_ARRAY:
+                return true;
+            default:
+                break;
+        }
+    }
+    return false;
+}
+
+int get_max_requires_api_level(int minApiLevel, const AtomDeclSet* atomDeclSet,
+                               const vector<java_type_t>& signature) {
     if (atomDeclSet != nullptr && contains_restricted(*atomDeclSet)) {
         return API_U;
     }
+    if (contains_repeated_field(signature)) {
+        return API_T;
+    }
     if (minApiLevel <= API_Q) {
         return API_Q;  // for StatsLog.writeRaw()
     }
-    return API_LEVEL_CURRENT;
+    return 0;
 }
 
 AtomDeclSet get_annotations(int argIndex,
diff --git a/stats/stats_log_api_gen/utils.h b/stats/stats_log_api_gen/utils.h
index 3ac08c8..75f6123 100644
--- a/stats/stats_log_api_gen/utils.h
+++ b/stats/stats_log_api_gen/utils.h
@@ -124,7 +124,8 @@
     }
 };
 
-int get_requires_api_level(int minApiLevel, const AtomDeclSet* atomDeclSet);
+int get_max_requires_api_level(int minApiLevel, const AtomDeclSet* atomDeclSet,
+                               const vector<java_type_t>& signature);
 
 }  // namespace stats_log_api_gen
 }  // namespace android