예제 #1
0
 def process_func(filename, data):
   if filename == 'resources.pb':
     table = Resources_pb2.ResourceTable()
     table.ParseFromString(data)
     _HardcodeInTable(table, is_bundle_module, shared_resources_allowlist)
     data = table.SerializeToString()
   elif filename.endswith('.xml') and not filename.startswith('res/raw'):
     xml_node = Resources_pb2.XmlNode()
     xml_node.ParseFromString(data)
     _ProcessProtoXmlNode(xml_node)
     data = xml_node.SerializeToString()
   return data
예제 #2
0
def _HardcodeInTable(table, is_bundle_module, shared_resources_allowlist):
  translations_package = None
  if is_bundle_module:
    # A separate top level package will be added to the resources, which
    # contains only locale specific resources. The package ID of the locale
    # resources is hardcoded to SHARED_LIBRARY_HARDCODED_ID. This causes
    # resources in locale splits to all get assigned
    # SHARED_LIBRARY_HARDCODED_ID as their package ID, which prevents a bug
    # in shared library bundles where each split APK gets a separate dynamic
    # ID, and cannot be accessed by the main APK.
    translations_package = Resources_pb2.Package()
    translations_package.package_id.id = SHARED_LIBRARY_HARDCODED_ID
    translations_package.package_name = (table.package[0].package_name +
                                         '_translations')

    # These resources are allowed in the base resources, since they are needed
    # by WebView.
    allowed_resource_names = set()
    if shared_resources_allowlist:
      allowed_resource_names = set(
          resource_utils.GetRTxtStringResourceNames(shared_resources_allowlist))

  for package in table.package:
    for _type in package.type:
      for entry in _type.entry:
        for config_value in entry.config_value:
          _ProcessProtoValue(config_value.value)

      if translations_package is not None:
        locale_type = _SplitLocaleResourceType(_type, allowed_resource_names)
        if locale_type:
          translations_package.type.add().CopyFrom(locale_type)

  if translations_package is not None:
    table.package.add().CopyFrom(translations_package)
예제 #3
0
def _SplitLocaleResourceType(_type, allowed_resource_names):
    """Splits locale specific resources out of |_type| and returns them.

  Any locale specific resources will be removed from |_type|, and a new
  Resources_pb2.Type value will be returned which contains those resources.

  Args:
    _type: A Resources_pb2.Type value
    allowed_resource_names: Names of locale resources that should be kept in the
        main type.
  """
    locale_entries = []
    for entry in _type.entry:
        if entry.name in allowed_resource_names:
            continue

        # First collect all resources values with a locale set.
        config_values_with_locale = []
        for config_value in entry.config_value:
            if config_value.config.locale:
                config_values_with_locale.append(config_value)

        if config_values_with_locale:
            # Remove the locale resources from the original entry
            for value in config_values_with_locale:
                entry.config_value.remove(value)

            # Add locale resources to a new Entry, and save for later.
            locale_entry = Resources_pb2.Entry()
            locale_entry.CopyFrom(entry)
            del locale_entry.config_value[:]
            locale_entry.config_value.extend(config_values_with_locale)
            locale_entries.append(locale_entry)

    if not locale_entries:
        return None

    # Copy the original type and replace the entries with |locale_entries|.
    locale_type = Resources_pb2.Type()
    locale_type.CopyFrom(_type)
    del locale_type.entry[:]
    locale_type.entry.extend(locale_entries)
    return locale_type
예제 #4
0
def _TableFromFlatBytes(data):
  # https://cs.android.com/android/platform/superproject/+/master:frameworks/base/tools/aapt2/format/Container.cpp
  size_idx = len(_FLAT_ARSC_HEADER)
  proto_idx = size_idx + 8
  if data[:size_idx] != _FLAT_ARSC_HEADER:
    raise Exception('Error parsing {} in {}'.format(info.filename, zip_path))
  # Size is stored as uint64.
  size = struct.unpack('<Q', data[size_idx:proto_idx])[0]
  table = Resources_pb2.ResourceTable()
  proto_bytes = data[proto_idx:proto_idx + size]
  table.ParseFromString(proto_bytes)
  return table
예제 #5
0
def _HardcodeSharedLibraryDynamicAttributes(zip_path):
    """Hardcodes the package IDs of dynamic attributes to 0x02.

  This is a workaround for b/147674078, which affects Android versions pre-N.

  Args:
    zip_path: Path to proto APK file.
  """
    with build_utils.TempDir() as tmp_dir:
        build_utils.ExtractAll(zip_path, path=tmp_dir)

        # First process the resources file.
        table = Resources_pb2.ResourceTable()
        with open(os.path.join(tmp_dir, 'resources.pb')) as f:
            table.ParseFromString(f.read())

        for package in table.package:
            for _type in package.type:
                for entry in _type.entry:
                    for config_value in entry.config_value:
                        _ProcessProtoValue(config_value.value)

        with open(os.path.join(tmp_dir, 'resources.pb'), 'w') as f:
            f.write(table.SerializeToString())

        # Next process all the XML files.
        xml_files = build_utils.FindInDirectory(tmp_dir, '*.xml')
        for xml_file in xml_files:
            xml_node = Resources_pb2.XmlNode()
            with open(xml_file) as f:
                xml_node.ParseFromString(f.read())

            _ProcessProtoXmlNode(xml_node)

            with open(xml_file, 'w') as f:
                f.write(xml_node.SerializeToString())

        # Overwrite the original zip file.
        build_utils.ZipDir(zip_path, tmp_dir)