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

Commit 01642009 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi Committed by Android (Google) Code Review
Browse files

Merge changes I82f4d684,Ide34e48f,I5c76515a,I1c7b2053 into main

* changes:
  [res] Optimize name lookups in idmap service
  [res] Store the number of types in typeSpec
  [cleanup] Fix initializers order
  [cleanup] Preallocate memory in CollectionUtils
parents 17934b1b 596fa178
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -468,9 +468,9 @@ Result<OverlayData> FabContainer::GetOverlayData(const OverlayManifestInfo& info
                                       entry.name().c_str());
        const auto& res_value = entry.res_value();
        result.pairs.emplace_back(OverlayData::Value{
            name, TargetValueWithConfig{.config = entry.configuration(), .value = TargetValue{
            name, TargetValueWithConfig{.value = TargetValue{
                    .data_type = static_cast<uint8_t>(res_value.data_type()),
                    .data_value = res_value.data_value()}}});
                    .data_value = res_value.data_value()}, .config = entry.configuration()}});
      }
    }
  }
+8 −7
Original line number Diff line number Diff line
@@ -227,9 +227,9 @@ Result<OverlayData> CreateResourceMapping(ResourceId id, const ZipAssetsProvider
    } else {
      overlay_data.pairs.emplace_back(
          OverlayData::Value{*target_resource, TargetValueWithConfig{
              .config = std::string(),
              .value = TargetValue{.data_type = overlay_resource->dataType,
                                   .data_value = overlay_resource->data}}});
                                   .data_value = overlay_resource->data},
              .config = std::string()}});
    }
  }

@@ -268,10 +268,11 @@ struct ResState {
  std::unique_ptr<AssetManager2> am;
  ZipAssetsProvider* zip_assets;

  static Result<ResState> Initialize(std::unique_ptr<ZipAssetsProvider> zip) {
  static Result<ResState> Initialize(std::unique_ptr<ZipAssetsProvider> zip,
                                     package_property_t flags) {
    ResState state;
    state.zip_assets = zip.get();
    if ((state.apk_assets = ApkAssets::Load(std::move(zip))) == nullptr) {
    if ((state.apk_assets = ApkAssets::Load(std::move(zip), flags)) == nullptr) {
      return Error("failed to load apk asset");
    }

@@ -284,7 +285,7 @@ struct ResState {
    }

    state.am = std::make_unique<AssetManager2>();
    if (!state.am->SetApkAssets({state.apk_assets})) {
    if (!state.am->SetApkAssets({state.apk_assets}, false)) {
      return Error("failed to create asset manager");
    }

@@ -343,8 +344,8 @@ Result<const ResState*> ApkResourceContainer::GetState() const {
    return state;
  }

  auto state =
      ResState::Initialize(std::move(std::get<std::unique_ptr<ZipAssetsProvider>>(state_)));
  auto state = ResState::Initialize(std::move(std::get<std::unique_ptr<ZipAssetsProvider>>(state_)),
                                    PROPERTY_OPTIMIZE_NAME_LOOKUPS);
  if (!state) {
    return state.GetError();
  }
+7 −6
Original line number Diff line number Diff line
@@ -120,8 +120,9 @@ public class CollectionUtils {
    public static @NonNull <I, O> List<O> map(@Nullable List<I> cur,
            Function<? super I, ? extends O> f) {
        if (isEmpty(cur)) return Collections.emptyList();
        final ArrayList<O> result = new ArrayList<>();
        for (int i = 0; i < cur.size(); i++) {
        final int size = cur.size();
        final ArrayList<O> result = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            result.add(f.apply(cur.get(i)));
        }
        return result;
@@ -133,7 +134,7 @@ public class CollectionUtils {
    public static @NonNull <I, O> Set<O> map(@Nullable Set<I> cur,
            Function<? super I, ? extends O> f) {
        if (isEmpty(cur)) return emptySet();
        ArraySet<O> result = new ArraySet<>();
        ArraySet<O> result = new ArraySet<>(cur.size());
        if (cur instanceof ArraySet) {
            ArraySet<I> arraySet = (ArraySet<I>) cur;
            int size = arraySet.size();
@@ -163,7 +164,7 @@ public class CollectionUtils {
            Function<? super I, ? extends O> f) {
        if (isEmpty(cur)) return Collections.emptyList();
        List<O> result = null;
        for (int i = 0; i < cur.size(); i++) {
        for (int i = 0, size = cur.size(); i < size; i++) {
            O transformed = f.apply(cur.get(i));
            if (transformed != null) {
                result = add(result, transformed);
@@ -239,7 +240,7 @@ public class CollectionUtils {
    public static @NonNull <T> List<T> filter(@Nullable List<?> list, Class<T> c) {
        if (isEmpty(list)) return Collections.emptyList();
        ArrayList<T> result = null;
        for (int i = 0; i < list.size(); i++) {
        for (int i = 0, size = list.size(); i < size; i++) {
            final Object item = list.get(i);
            if (c.isInstance(item)) {
                result = ArrayUtils.add(result, (T) item);
@@ -273,7 +274,7 @@ public class CollectionUtils {
    public static @Nullable <T> T find(@Nullable List<T> items,
            java.util.function.Predicate<T> predicate) {
        if (isEmpty(items)) return null;
        for (int i = 0; i < items.size(); i++) {
        for (int i = 0, size = items.size(); i < size; i++) {
            final T item = items.get(i);
            if (predicate.test(item)) return item;
        }
+15 −10
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <algorithm>
#include <cstddef>
#include <limits>
#include <optional>

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
@@ -50,7 +51,9 @@ namespace {
// contiguous block of memory to store both the TypeSpec struct and
// the Type structs.
struct TypeSpecBuilder {
  explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {}
  explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {
    type_entries.reserve(dtohs(header_->typesCount));
  }

  void AddType(incfs::verified_map_ptr<ResTable_type> type) {
    TypeSpec::TypeEntry& entry = type_entries.emplace_back();
@@ -59,6 +62,7 @@ struct TypeSpecBuilder {
  }

  TypeSpec Build() {
    type_entries.shrink_to_fit();
    return {header_, std::move(type_entries)};
  }

@@ -450,7 +454,8 @@ const LoadedPackage* LoadedArsc::GetPackageById(uint8_t package_id) const {
std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
                                                         package_property_t property_flags) {
  ATRACE_NAME("LoadedPackage::Load");
  std::unique_ptr<LoadedPackage> loaded_package(new LoadedPackage());
  const bool optimize_name_lookups = (property_flags & PROPERTY_OPTIMIZE_NAME_LOOKUPS) != 0;
  std::unique_ptr<LoadedPackage> loaded_package(new LoadedPackage(optimize_name_lookups));

  // typeIdOffset was added at some point, but we still must recognize apps built before this
  // was added.
@@ -499,7 +504,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
  // A map of TypeSpec builders, each associated with an type index.
  // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
  // contiguous block of memory that holds all the Types together with the TypeSpec.
  std::unordered_map<int, std::unique_ptr<TypeSpecBuilder>> type_builder_map;
  std::unordered_map<int, std::optional<TypeSpecBuilder>> type_builder_map;

  ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
  while (iter.HasNext()) {
@@ -567,14 +572,14 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
          return {};
        }

        if (entry_count * sizeof(uint32_t) > chunk.data_size()) {
        if (entry_count * sizeof(uint32_t) > child_chunk.data_size()) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small to hold entries.";
          return {};
        }

        std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type_spec->id];
        if (builder_ptr == nullptr) {
          builder_ptr = util::make_unique<TypeSpecBuilder>(type_spec.verified());
        auto& maybe_type_builder = type_builder_map[type_spec->id];
        if (!maybe_type_builder) {
          maybe_type_builder.emplace(type_spec.verified());
          loaded_package->resource_ids_.set(type_spec->id, entry_count);
        } else {
          LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
@@ -594,9 +599,9 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
        }

        // Type chunks must be preceded by their TypeSpec chunks.
        std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type->id];
        if (builder_ptr != nullptr) {
          builder_ptr->AddType(type.verified());
        auto& maybe_type_builder = type_builder_map[type->id];
        if (maybe_type_builder) {
          maybe_type_builder->AddType(type.verified());
        } else {
          LOG(ERROR) << StringPrintf(
              "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.",
+55 −15
Original line number Diff line number Diff line
@@ -447,14 +447,18 @@ Res_png_9patch* Res_png_9patch::deserialize(void* inData)
// --------------------------------------------------------------------
// --------------------------------------------------------------------

ResStringPool::ResStringPool()
    : mError(NO_INIT), mOwnedData(NULL), mHeader(NULL), mCache(NULL)
{
ResStringPool::ResStringPool() : mError(NO_INIT), mOwnedData(NULL), mHeader(NULL), mCache(NULL) {
}

ResStringPool::ResStringPool(const void* data, size_t size, bool copyData)
    : mError(NO_INIT), mOwnedData(NULL), mHeader(NULL), mCache(NULL)
{
ResStringPool::ResStringPool(bool optimize_name_lookups) : ResStringPool() {
  if (optimize_name_lookups) {
    mIndexLookupCache.emplace();
  }
}

ResStringPool::ResStringPool(const void* data, size_t size, bool copyData,
                             bool optimize_name_lookups)
    : ResStringPool(optimize_name_lookups) {
  setTo(data, size, copyData);
}

@@ -683,6 +687,14 @@ status_t ResStringPool::setTo(incfs::map_ptr<void> data, size_t size, bool copyD
        mStylePoolSize = 0;
    }

    if (mIndexLookupCache) {
      if ((mHeader->flags & ResStringPool_header::UTF8_FLAG) != 0) {
        mIndexLookupCache->first.reserve(mHeader->stringCount);
      } else {
        mIndexLookupCache->second.reserve(mHeader->stringCount);
      }
    }

    return (mError=NO_ERROR);
}

@@ -708,6 +720,10 @@ void ResStringPool::uninit()
        free(mOwnedData);
        mOwnedData = NULL;
    }
    if (mIndexLookupCache) {
      mIndexLookupCache->first.clear();
      mIndexLookupCache->second.clear();
    }
}

/**
@@ -824,7 +840,7 @@ base::expected<StringPiece16, NullOrIOError> ResStringPool::stringAt(size_t idx)

                // encLen must be less than 0x7FFF due to encoding.
                if ((uint32_t)(u8str+*u8len-strings) < mStringPoolSize) {
                    AutoMutex lock(mDecodeLock);
                  AutoMutex lock(mCachesLock);

                  if (mCache != NULL && mCache[idx] != NULL) {
                    return StringPiece16(mCache[idx], *u16len);
@@ -1093,12 +1109,24 @@ base::expected<size_t, NullOrIOError> ResStringPool::indexOfString(const char16_
            // block, start searching at the back.
            String8 str8(str, strLen);
            const size_t str8Len = str8.size();
            std::optional<AutoMutex> cacheLock;
            if (mIndexLookupCache) {
              cacheLock.emplace(mCachesLock);
              if (auto it = mIndexLookupCache->first.find(std::string_view(str8));
                  it != mIndexLookupCache->first.end()) {
                return it->second;
              }
            }

            for (int i=mHeader->stringCount-1; i>=0; i--) {
                const base::expected<StringPiece, NullOrIOError> s = string8At(i);
                if (UNLIKELY(IsIOError(s))) {
                    return base::unexpected(s.error());
                }
                if (s.has_value()) {
                  if (mIndexLookupCache) {
                    mIndexLookupCache->first.insert({*s, i});
                  }
                    if (kDebugStringPoolNoisy) {
                        ALOGI("Looking at %s, i=%d\n", s->data(), i);
                    }
@@ -1151,24 +1179,36 @@ base::expected<size_t, NullOrIOError> ResStringPool::indexOfString(const char16_
            // most often this happens because we want to get IDs for style
            // span tags; since those always appear at the end of the string
            // block, start searching at the back.
            std::optional<AutoMutex> cacheLock;
            if (mIndexLookupCache) {
              cacheLock.emplace(mCachesLock);
              if (auto it = mIndexLookupCache->second.find({str, strLen});
                  it != mIndexLookupCache->second.end()) {
                return it->second;
              }
            }
            for (int i=mHeader->stringCount-1; i>=0; i--) {
                const base::expected<StringPiece16, NullOrIOError> s = stringAt(i);
                if (UNLIKELY(IsIOError(s))) {
                    return base::unexpected(s.error());
                }
                if (kDebugStringPoolNoisy) {
                    ALOGI("Looking at %s, i=%d\n", String8(s->data(), s->size()).c_str(), i);
                  ALOGI("Looking16 at %s, i=%d\n", String8(s->data(), s->size()).c_str(), i);
                }
                if (s.has_value()) {
                  if (mIndexLookupCache) {
                    mIndexLookupCache->second.insert({*s, i});
                  }
                if (s.has_value() && strLen == s->size() &&
                        strzcmp16(s->data(), s->size(), str, strLen) == 0) {
                  if (strLen == s->size() && strzcmp16(s->data(), s->size(), str, strLen) == 0) {
                    if (kDebugStringPoolNoisy) {
                        ALOGI("MATCH!");
                      ALOGI("MATCH16!");
                    }
                    return i;
                  }
                }
            }
        }
    }
    return base::unexpected(std::nullopt);
}

Loading