Loading tools/aapt2/tools/finalize_res.py +87 −11 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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))) """ Loading @@ -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 Loading @@ -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: Loading Loading @@ -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) Loading
tools/aapt2/tools/finalize_res.py +87 −11 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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))) """ Loading @@ -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 Loading @@ -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: Loading Loading @@ -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)