aconfig: Add script to generate finalized flag proto.
Takes /prebuilts/sdk/<level>/finalized-flags.txt and creates
aconfig_internal FinalizedFlags proto. For use in automatically adding
the sdk check in exported flag codegen.
Test
1. m convert_finalized_flags_to_proto
2. /path/to/aosp/out/host/linux-x86/bin/convert_finalized_flags_to_proto /path/to/aosp/prebuits/sdk > tmp_flags.pb
3. inspect proto for correctness
Next steps:
-Add genrule which uses this binary
-Read proto output in codegen
Test: manual, see above
Change-Id: I730a1c20347fe1a11fe7213fa25fffbe4ea3fc23
diff --git a/tools/aconfig/aconfig/data/Android.bp b/tools/aconfig/aconfig/data/Android.bp
new file mode 100644
index 0000000..1b5eef0
--- /dev/null
+++ b/tools/aconfig/aconfig/data/Android.bp
@@ -0,0 +1,14 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_binary_host {
+ name: "convert_finalized_flags_to_proto",
+ srcs: ["convert_finalized_flags_to_proto.py"],
+ libs: ["aconfig_internal_proto_python"],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py b/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py
new file mode 100644
index 0000000..15ff03c
--- /dev/null
+++ b/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 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.
+
+import collections
+import sys
+import os
+
+from io import TextIOWrapper
+from protos import aconfig_internal_pb2
+from typing import Dict, List, Set
+
+def extract_finalized_flags(flag_file: TextIOWrapper):
+ finalized_flags_for_sdk = list()
+
+ for line in f:
+ flag_name = line.strip()
+ if flag_name:
+ finalized_flags_for_sdk.append(flag_name)
+
+ return finalized_flags_for_sdk
+
+def remove_duplicate_flags(all_flags_with_duplicates: Dict[int, List]):
+ result_flags = collections.defaultdict(set)
+
+ for api_level in sorted(all_flags_with_duplicates.keys(), key=int):
+ for flag in all_flags_with_duplicates[api_level]:
+ if not any(flag in value_set for value_set in result_flags.values()):
+ result_flags[api_level].add(flag)
+
+ return result_flags
+
+def build_proto(all_flags: Set):
+ finalized_flags = aconfig_internal_pb2.finalized_flags()
+ for api_level, qualified_name_list in all_flags.items():
+ for qualified_name in qualified_name_list:
+ package_name, flag_name = qualified_name.rsplit('.', 1)
+ finalized_flag = aconfig_internal_pb2.finalized_flag()
+ finalized_flag.name = flag_name
+ finalized_flag.package = package_name
+ finalized_flag.min_sdk = api_level
+ finalized_flags.finalized_flag.append(finalized_flag)
+ return finalized_flags
+
+if __name__ == '__main__':
+ if len(sys.argv) == 1:
+ sys.exit('No prebuilts/sdk directory provided.')
+ all_api_info_dir = sys.argv[1]
+
+ all_flags_with_duplicates = {}
+ for sdk_dir in os.listdir(all_api_info_dir):
+ api_level = sdk_dir.rsplit('/', 1)[0].rstrip('0').rstrip('.')
+
+ # No support for minor versions yet. This also removes non-numeric dirs.
+ # Update once floats are acceptable.
+ if not api_level.isdigit():
+ continue
+
+ flag_file_path = os.path.join(all_api_info_dir, sdk_dir, 'finalized-flags.txt')
+ try:
+ with open(flag_file_path, 'r') as f:
+ finalized_flags_for_sdk = extract_finalized_flags(f)
+ all_flags_with_duplicates[int(api_level)] = finalized_flags_for_sdk
+ except FileNotFoundError:
+ # Either this version is not finalized yet or looking at a
+ # /prebuilts/sdk/version before finalized-flags.txt was introduced.
+ continue
+
+ all_flags = remove_duplicate_flags(all_flags_with_duplicates)
+ finalized_flags = build_proto(all_flags)
+ sys.stdout.buffer.write(finalized_flags.SerializeToString())
diff --git a/tools/aconfig/aconfig_protos/Android.bp b/tools/aconfig/aconfig_protos/Android.bp
index 62a2b64..080688e 100644
--- a/tools/aconfig/aconfig_protos/Android.bp
+++ b/tools/aconfig/aconfig_protos/Android.bp
@@ -98,3 +98,13 @@
test_suites: ["general-tests"],
defaults: ["aconfig_protos.defaults"],
}
+
+// Internal protos
+
+python_library_host {
+ name: "aconfig_internal_proto_python",
+ srcs: ["protos/aconfig_internal.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}