Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/make/tools/finalization/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 9 kB image not shown  

Quelle  finalize_res.py

  Sprache: Python
 

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

#  Copyright (C) 2022 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.
#
# 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.

"""
Finalize resource values in <staging-public-group> tags
and convert those to <staging-public-group-final>

Build and execute a python binary using soong. This will included the aconfig flags for the lunched configuration.

Usage: m finalize_res && \
      finalize_res \
      $ANDROID_BUILD_TOP/frameworks/base/core/res/res/values/public-staging.xml \
      $ANDROID_BUILD_TOP/frameworks/base/core/res/res/values/public-final.xml
"""

import importlib.resources
import re
import sys
import subprocess
from collections import defaultdict
from protos import aconfig_pb2

resTypes = ["attr""id""style""string""dimen""color""array""drawable""layout",
            "anim""animator""interpolator""mipmap""integer""transition""raw""bool",
            "fraction"]

NO_FLAG_MAGIC_CONSTANT = "no_flag"

_aconfig_map = {}
_not_finalized = defaultdict(list)
_type_ids = {}
_type = ""
_finalized_flags = defaultdict(list)
_non_finalized_flags = defaultdict(list)


_lowest_staging_first_id = 0x01FFFFFF

"""
    Created finalized <public> declarations for staging resources, ignoring them if they've been
    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(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)

    match = re.search(r'<!-- @FlaggedApi\((.+?)\)', comment, flags=re.DOTALL)
    if match:
        flag = match.group(1)
    else:
        flag = NO_FLAG_MAGIC_CONSTANT

    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)

    # Any flag that is not both READ_ONLY and ENABLED is left in the staging file.
    if not _aconfig_map[flag]:
        _non_finalized_flags[flag].append(name)
        # 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[flag].append(name)

    id = _type_ids[_type]
    _type_ids[_type] += 1

    # 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)))


"""
    Finalizes staging-public-groups if they have any entries in them. Also keeps track of the
    lowest first-id of the non-empty groups so that the next release's staging-public-groups can
    be assigned the next down shifted first-id.
"""
def finalize_group(raw):
    global _type, _lowest_staging_first_id
    _type = raw.group(1)
    id = int(raw.group(2), 16)
    _type_ids[_type] = _type_ids.get(_type, id)


    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)

    # Potenitally bump _lowest_staging_first_id if this group had any flags (finalize or not).
    if all:
        _lowest_staging_first_id = min(id, _lowest_staging_first_id)

    return res

"""
    Collects the max ID for each resType so that the new IDs can be assigned afterwards
"""
def collect_ids(raw):
    for m in re.finditer(r'<public type="(.+?)" name=".+?" id="(.+?)" />', raw):
        type = m.group(1)
        id = int(m.group(2), 16)
        _type_ids[type] = max(id + 1, _type_ids.get(type, 0))

try:
    with importlib.resources.files('res').joinpath('all_aconfig_declarations.pb').open('rb'as f:
        parsed_flags = aconfig_pb2.parsed_flags.FromString(f.read())
except FileNotFoundError as error:
    print(error)
    print("Could not access aconfig flags. Did you build the script using soong?")
    sys.exit()

for flag in parsed_flags.parsed_flag:
    key = "{}.{}".format(flag.package, flag.name)
    value = (
        flag.permission == aconfig_pb2.flag_permission.READ_ONLY
        and flag.state == aconfig_pb2.flag_state.ENABLED
    )
    _aconfig_map[key] = value

_aconfig_map[NO_FLAG_MAGIC_CONSTANT] = False

with open(sys.argv[1], "r+"as stagingFile:
    with open(sys.argv[2], "r+"as finalFile:
        existing = finalFile.read()
        # Cut out the closing resources tag so that it can be concatenated easily later
        existing = "\n".join(existing.rsplit("</resources>"1))

        # Collect the IDs from the existing already finalized resources
        collect_ids(existing)

        staging = stagingFile.read()
        stagingSplit = staging.rsplit("<resources>")
        staging = stagingSplit[1]
        staging = re.sub(
            r'<staging-public-group type="(.+?)" first-id="(.+?)">(.+?)</staging-public-group>',
            finalize_group, staging, flags=re.DOTALL)
        staging = re.sub(r' *\n''\n', staging)
        staging = re.sub(r'\n{3,}''\n\n', staging)

        # First write the existing finalized declarations and then append the new stuff
        finalFile.seek(0)
        finalFile.write(existing.strip("\n"))
        finalFile.write("\n\n")
        finalFile.write(staging.strip("\n"))
        finalFile.write("\n")
        finalFile.truncate()

        stagingFile.seek(0)
        # Include the documentation from public-staging.xml that was previously split out
        stagingFile.write(stagingSplit[0])
        # Write the next platform header
        stagingFile.write("<resources>\n\n")
        stagingFile.write("  <!-- ===============================================================\n")
        stagingFile.write("    Resources added in version NEXT of the platform\n\n")
        stagingFile.write("    NOTE: After this version of the platform is forked, changes cannot be made to the root\n")
        stagingFile.write("    branch's groups for that release. Only merge changes to the forked platform branch.\n")
        stagingFile.write("    =============================================================== -->\n")
        stagingFile.write("  <eat-comment/>\n\n")

        # Seed the next release's staging-public-groups as empty declarations,
        # so its easy for another developer to expose a new public resource
        nextId = _lowest_staging_first_id - 0x00010000
        for resType in resTypes:
            stagingFile.write('  <staging-public-group type="%s" first-id="%s">\n'
                               % (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()


_non_finalized_flags = sorted([f"    {flag}: {resource}" for flag, values in _non_finalized_flags.items() for resource in values])
print(f"\n{len(_non_finalized_flags)} resource(s) were NOT finalized:")
print("\n".join(_non_finalized_flags))

_finalized_flags = sorted([f"    {flag}: {resource}" for flag, values in _finalized_flags.items() for resource in values])
print(f"\n{len(_finalized_flags)} resource(s) were finalized:")
print("\n".join(_finalized_flags))

Messung V0.5 in Prozent
C=97 H=91 G=93

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-28) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.