Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1d171f1 authored by Linus Tufvesson's avatar Linus Tufvesson Committed by Android (Google) Code Review
Browse files

Merge "Make finalize_res flag aware" into main

parents 574ce485 60e7729b
Loading
Loading
Loading
Loading
+87 −11
Original line number Diff line number Diff line
@@ -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)