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

Commit 73bfe41b authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

Do not look for R.class of overlays

Now that RROs are loaded as shared libraries,
LoadedApk#makeApplication is attempting to find the onResourcesLoaded
method of the overlays. This is a performance hit and causes more
memory than necessary to be allocated during application start up.

Bug: 143314947
Test: com.android.performance.tests.HermeticMemoryTest
Change-Id: I3b8cd22dae83e0164d6678c80279f9fffceb34e6
parent 52a38018
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1215,7 +1215,8 @@ public final class LoadedApk {
        }

        // Rewrite the R 'constants' for all library apks.
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers();
        SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers(
                false, false);
        final int N = packageIdentifiers.size();
        for (int i = 0; i < N; i++) {
            final int id = packageIdentifiers.keyAt(i);
+10 −2
Original line number Diff line number Diff line
@@ -1491,9 +1491,17 @@ public final class AssetManager implements AutoCloseable {
     */
    @UnsupportedAppUsage
    public SparseArray<String> getAssignedPackageIdentifiers() {
        return getAssignedPackageIdentifiers(true, true);
    }

    /**
     * @hide
     */
    public SparseArray<String> getAssignedPackageIdentifiers(boolean includeOverlays,
            boolean includeLoaders) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetAssignedPackageIdentifiers(mObject);
            return nativeGetAssignedPackageIdentifiers(mObject, includeOverlays, includeLoaders);
        }
    }

@@ -1557,7 +1565,7 @@ public final class AssetManager implements AutoCloseable {
            int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout,
            int uiMode, int colorMode, int majorVersion);
    private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers(
            long ptr);
            long ptr, boolean includeOverlays, boolean includeLoaders);

    // File native methods.
    private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
+10 −3
Original line number Diff line number Diff line
@@ -556,7 +556,9 @@ static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin
  assetmanager->SetConfiguration(configuration);
}

static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                                   jboolean includeOverlays,
                                                   jboolean includeLoaders) {
  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));

  jobject sparse_array =
@@ -567,6 +569,10 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
    return nullptr;
  }

  // Optionally exclude overlays and loaders.
  uint64_t exclusion_flags = ((includeOverlays) ? 0U : PROPERTY_OVERLAY)
      | ((includeLoaders) ? 0U : PROPERTY_LOADER);

  assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) -> bool {
    jstring jpackage_name = env->NewStringUTF(package_name.c_str());
    if (jpackage_name == nullptr) {
@@ -577,7 +583,8 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
    env->CallVoidMethod(sparse_array, gSparseArrayOffsets.put, static_cast<jint>(package_id),
                        jpackage_name);
    return true;
  });
  }, exclusion_flags);

  return sparse_array;
}

@@ -1591,7 +1598,7 @@ static const JNINativeMethod gAssetManagerMethods[] = {
    {"nativeSetApkAssets", "(J[Landroid/content/res/ApkAssets;Z)V", (void*)NativeSetApkAssets},
    {"nativeSetConfiguration", "(JIILjava/lang/String;IIIIIIIIIIIIIII)V",
     (void*)NativeSetConfiguration},
    {"nativeGetAssignedPackageIdentifiers", "(J)Landroid/util/SparseArray;",
    {"nativeGetAssignedPackageIdentifiers", "(JZZ)Landroid/util/SparseArray;",
     (void*)NativeGetAssignedPackageIdentifiers},

    // AssetManager file methods.
+28 −21
Original line number Diff line number Diff line
@@ -43,20 +43,22 @@ static const std::string kResourcesArsc("resources.arsc");
ApkAssets::ApkAssets(ZipArchiveHandle unmanaged_handle,
                     const std::string& path,
                     time_t last_mod_time,
                     bool for_loader)
                     package_property_t property_flags)
    : zip_handle_(unmanaged_handle, ::CloseArchive), path_(path), last_mod_time_(last_mod_time),
      for_loader_(for_loader) {
      property_flags_(property_flags) {
}

std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system,
                                                 bool for_loader) {
  return LoadImpl({} /*fd*/, path, nullptr, nullptr, system, false /*load_as_shared_library*/,
                  for_loader);
  package_property_t flags = (system ? PROPERTY_SYSTEM : 0U) |
                             (for_loader ? PROPERTY_LOADER : 0U);
  return LoadImpl({} /*fd*/, path, nullptr, nullptr, flags);
}

std::unique_ptr<const ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path,
                                                                bool system) {
  return LoadImpl({} /*fd*/, path, nullptr, nullptr, system, true /*load_as_shared_library*/);
  package_property_t flags = PROPERTY_DYNAMIC | (system ? PROPERTY_SYSTEM : 0U);
  return LoadImpl({} /*fd*/, path, nullptr, nullptr, flags);
}

std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
@@ -74,27 +76,33 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap
    LOG(ERROR) << "failed to load IDMAP " << idmap_path;
    return {};
  }
  return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(), std::move(idmap_asset),
                  std::move(loaded_idmap), system, true /*load_as_shared_library*/);

  return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(),
                  std::move(idmap_asset),
                  std::move(loaded_idmap),
                  PROPERTY_OVERLAY | (system ? PROPERTY_SYSTEM : 0U));
}

std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(unique_fd fd,
                                                       const std::string& friendly_name,
                                                       bool system, bool force_shared_lib,
                                                       bool for_loader) {
  package_property_t flags = (system ? PROPERTY_SYSTEM : 0U) |
                             (force_shared_lib ? PROPERTY_DYNAMIC : 0U) |
                             (for_loader ? PROPERTY_LOADER : 0U);
  return LoadImpl(std::move(fd), friendly_name, nullptr /*idmap_asset*/, nullptr /*loaded_idmap*/,
                  system, force_shared_lib, for_loader);
                  flags);
}

std::unique_ptr<const ApkAssets> ApkAssets::LoadArsc(const std::string& path,
                                                     bool for_loader) {
  return LoadArscImpl({} /*fd*/, path, for_loader);
  return LoadArscImpl({} /*fd*/, path, for_loader ? PROPERTY_LOADER : 0U);
}

std::unique_ptr<const ApkAssets> ApkAssets::LoadArsc(unique_fd fd,
                                                     const std::string& friendly_name,
                                                     bool for_loader) {
  return LoadArscImpl(std::move(fd), friendly_name, for_loader);
  return LoadArscImpl(std::move(fd), friendly_name, for_loader ? PROPERTY_LOADER : 0U);
}

std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {
@@ -120,8 +128,7 @@ std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {

std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
    unique_fd fd, const std::string& path, std::unique_ptr<Asset> idmap_asset,
    std::unique_ptr<const LoadedIdmap> loaded_idmap, bool system, bool load_as_shared_library,
    bool for_loader) {
    std::unique_ptr<const LoadedIdmap> loaded_idmap, package_property_t property_flags) {
  ::ZipArchiveHandle unmanaged_handle;
  int32_t result;
  if (fd >= 0) {
@@ -141,7 +148,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(

  // Wrap the handle in a unique_ptr so it gets automatically closed.
  std::unique_ptr<ApkAssets>
      loaded_apk(new ApkAssets(unmanaged_handle, path, last_mod_time, for_loader));
      loaded_apk(new ApkAssets(unmanaged_handle, path, last_mod_time, property_flags));

  // Find the resource table.
  ::ZipEntry entry;
@@ -170,9 +177,8 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
  const StringPiece data(
      reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
      loaded_apk->resources_asset_->getLength());
  loaded_apk->loaded_arsc_ =
      LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(), system, load_as_shared_library,
                       for_loader);
  loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(),
                                              property_flags);
  if (loaded_apk->loaded_arsc_ == nullptr) {
    LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
    return {};
@@ -184,7 +190,7 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(

std::unique_ptr<const ApkAssets> ApkAssets::LoadArscImpl(unique_fd fd,
                                                         const std::string& path,
                                                         bool for_loader) {
                                                         package_property_t property_flags) {
  std::unique_ptr<Asset> resources_asset;

  if (fd >= 0) {
@@ -201,13 +207,14 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadArscImpl(unique_fd fd,

  time_t last_mod_time = getFileModDate(path.c_str());

  std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(nullptr, path, last_mod_time, for_loader));
  std::unique_ptr<ApkAssets> loaded_apk(
      new ApkAssets(nullptr, path, last_mod_time, property_flags));
  loaded_apk->resources_asset_ = std::move(resources_asset);

  const StringPiece data(
      reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
      loaded_apk->resources_asset_->getLength());
  loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, nullptr, false, false, for_loader);
  loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, nullptr, property_flags);
  if (loaded_apk->loaded_arsc_ == nullptr) {
    LOG(ERROR) << "Failed to load '" << kResourcesArsc << path;
    return {};
@@ -320,8 +327,8 @@ bool ApkAssets::ForEachFile(const std::string& root_path,
}

bool ApkAssets::IsUpToDate() const {
  // Loaders are invalidated by the app, not the system, so assume up to date
  if (for_loader_) {
  if (IsLoader()) {
    // Loaders are invalidated by the app, not the system, so assume up to date.
    return true;
  }

+9 −8
Original line number Diff line number Diff line
@@ -188,7 +188,8 @@ LoadedIdmap::LoadedIdmap(const Idmap_header* header,
                         const Idmap_data_header* data_header,
                         const Idmap_target_entry* target_entries,
                         const Idmap_overlay_entry* overlay_entries,
                         ResStringPool* string_pool) : header_(header),
                         ResStringPool* string_pool)
     : header_(header),
       data_header_(data_header),
       target_entries_(target_entries),
       overlay_entries_(overlay_entries),
@@ -264,7 +265,7 @@ std::unique_ptr<const LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_da
    }
  }

   // Can't use make_unique because LoadedImpl constructor is private.
  // Can't use make_unique because LoadedIdmap constructor is private.
  std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
      new LoadedIdmap(header, data_header, target_entries, overlay_entries,
                      idmap_string_pool.release()));
Loading