diff options
| -rwxr-xr-x | tools/aapt2/tools/finalize_res.py | 98 |
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) |