summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtools/aapt2/tools/finalize_res.py98
1 files changed, 87 insertions, 11 deletions
diff --git a/tools/aapt2/tools/finalize_res.py b/tools/aapt2/tools/finalize_res.py
index 0e4d865bc890..f9add7d90125 100755
--- a/tools/aapt2/tools/finalize_res.py
+++ b/tools/aapt2/tools/finalize_res.py
@@ -38,13 +38,20 @@ Usage: $ANDROID_BUILD_TOP/frameworks/base/tools/aapt2/tools/finalize_res.py \
import re
import sys
+import subprocess
+from collections import defaultdict
resTypes = ["attr", "id", "style", "string", "dimen", "color", "array", "drawable", "layout",
"anim", "animator", "interpolator", "mipmap", "integer", "transition", "raw", "bool",
"fraction"]
+_aconfig_map = {}
+_not_finalized = defaultdict(list)
_type_ids = {}
_type = ""
+_finalized_flags = set()
+_non_finalized_flags = set()
+
_lowest_staging_first_id = 0x01FFFFFF
@@ -53,13 +60,48 @@ _lowest_staging_first_id = 0x01FFFFFF
prefixed with removed_. The IDs are assigned without holes starting from the last ID for that
type currently finalized in public-final.xml.
"""
-def finalize_item(raw):
- name = raw.group(1)
- if re.match(r'_*removed.+', name):
- return ""
+def finalize_item(comment_and_item):
+ print("Processing:\n" + comment_and_item)
+ name = re.search('<public name="(.+?)"',comment_and_item, flags=re.DOTALL).group(1)
+ if re.match('removed_.+', name):
+ # Remove it from <staging-public-group> in public-staging.xml
+ # Include it as is in <staging-public-group-final> in public-final.xml
+ # Don't assign an id in public-final.xml
+ return ("", comment_and_item, "")
+
+ comment = re.search(' *<!--.+?-->\n', comment_and_item, flags=re.DOTALL).group(0)
+
+ flag = re.search('<!-- @FlaggedApi\((.+?)\)', comment, flags=re.DOTALL).group(1)
+ if flag.startswith("\""):
+ # Flag is a string value, just remove "
+ flag = flag.replace("\"", "")
+ else:
+ # Flag is a java constant, convert to string value
+ flag = flag.replace(".Flags.FLAG_", ".").lower()
+
+ if flag not in _aconfig_map:
+ raise Exception("Unknown flag: " + flag)
+
+ # READ_ONLY-ENABLED is a magic string from printflags output below
+ if _aconfig_map[flag] != "READ_ONLY-ENABLED":
+ _non_finalized_flags.add(flag)
+ # Keep it as is in <staging-public-group> in public-staging.xml
+ # Include as magic constant "removed_" in <staging-public-group-final> in public-final.xml
+ # Don't assign an id in public-final.xml
+ return (comment_and_item, " <public name=\"removed_\" />\n", "")
+
+ _finalized_flags.add(flag)
+
id = _type_ids[_type]
_type_ids[_type] += 1
- return ' <public type="%s" name="%s" id="%s" />\n' % (_type, name, '0x{0:0{1}x}'.format(id, 8))
+
+ # Removes one indentation step to align the comment with the item outside the
+ comment = re.sub("^ ", "", comment, flags=re.MULTILINE)
+
+ # Remove from <staging-public-group> in public-staging.xml
+ # Include as is in <staging-public-group-final> in public-final.xml
+ # Assign an id in public-final.xml
+ return ("", comment_and_item, comment + ' <public type="%s" name="%s" id="%s" />\n' % (_type, name, '0x{0:0{1}x}'.format(id, 8)))
"""
@@ -72,10 +114,26 @@ def finalize_group(raw):
_type = raw.group(1)
id = int(raw.group(2), 16)
_type_ids[_type] = _type_ids.get(_type, id)
- (res, count) = re.subn(' {0,4}<public name="(.+?)" */>\n', finalize_item, raw.group(3))
- if count > 0:
- res = raw.group(0).replace("staging-public-group",
- "staging-public-group-final") + '\n' + res
+
+
+ all = re.findall(' *<!--.*?<public name=".+?" */>\n', raw.group(3), flags=re.DOTALL)
+ res = ""
+ group_matches = ""
+ for match in all:
+ (staging_group, final_group, final_id_assignment) = finalize_item(match)
+
+ if staging_group:
+ _not_finalized[_type].append(staging_group)
+
+ if final_group:
+ group_matches += final_group
+
+ if final_id_assignment:
+ res += final_id_assignment
+
+ # Only add it to final.xml if new ids were actually assigned
+ if res:
+ res = '<staging-public-group-final type="%s" first-id="%s">\n%s </staging-public-group-final>\n\n%s' % (_type, raw.group(2), group_matches, res)
_lowest_staging_first_id = min(id, _lowest_staging_first_id)
return res
@@ -88,6 +146,13 @@ def collect_ids(raw):
id = int(m.group(2), 16)
_type_ids[type] = max(id + 1, _type_ids.get(type, 0))
+# This is a hack and assumes this script is run from the top directory
+output=subprocess.run("printflags --format='{fully_qualified_name} {permission}-{state}'", shell=True, capture_output=True, encoding="utf-8", check=True)
+for line in output.stdout.splitlines():
+ parts = line.split()
+ key = parts[0]
+ value = parts[1]
+ _aconfig_map[key]=value
with open(sys.argv[1], "r+") as stagingFile:
with open(sys.argv[2], "r+") as finalFile:
@@ -132,10 +197,21 @@ with open(sys.argv[1], "r+") as stagingFile:
nextId = _lowest_staging_first_id - 0x00010000
for resType in resTypes:
stagingFile.write(' <staging-public-group type="%s" first-id="%s">\n'
- ' </staging-public-group>\n\n' %
- (resType, '0x{0:0{1}x}'.format(nextId, 8)))
+ % (resType, '0x{0:0{1}x}'.format(nextId, 8)))
+ for item in _not_finalized[resType]:
+ stagingFile.write(item)
+ stagingFile.write(' </staging-public-group>\n\n')
nextId -= 0x00010000
# Close the resources tag and truncate, since the file will be shorter than the previous
stagingFile.write("</resources>\n")
stagingFile.truncate()
+
+
+print("\nFlags that had resources that were NOT finalized:")
+for flag in sorted(_non_finalized_flags):
+ print(flag)
+
+print("\nFlags that had resources that were finalized:")
+for flag in sorted(_finalized_flags):
+ print(flag)