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

Commit c92c4dd6 authored by Mårten Kongstad's avatar Mårten Kongstad Committed by Todd Kennedy
Browse files

Surface <overlayable> info in Java AssetManager

Add a new, hidden method to AssetManager to extract a mapping
overlayable name -> overlayable actor for all <overlayable> blocks in a
package. [This will eventually be used to check if the caller of the OMS
AIDL API is the registered actor for a given overlay.]

Also, teach AssetManager2 to not accept packages that re-use the same
overlayable name. [Such packages have always been ill-formed.]

Bug: 123894537
Test: make libandroidfw_tests
Change-Id: I1117fd3503f04fe4c73eb7114901e022508f4d9e
parent 23f34cd6
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Provides access to an application's raw asset files; see {@link Resources}
@@ -1345,6 +1346,17 @@ public final class AssetManager implements AutoCloseable {
        }
    }

    /**
     * @hide
     */
    @GuardedBy("this")
    public @Nullable Map<String, String> getOverlayableMap(String packageName) {
        synchronized (this) {
            ensureValidLocked();
            return nativeGetOverlayableMap(mObject, packageName);
        }
    }

    @GuardedBy("this")
    private void incRefsLocked(long id) {
        if (DEBUG_REFS) {
@@ -1462,6 +1474,8 @@ public final class AssetManager implements AutoCloseable {

    private static native void nativeVerifySystemIdmaps();
    private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
    private static native @Nullable Map nativeGetOverlayableMap(long ptr,
            @NonNull String packageName);

    // Global debug native methods.
    /**
+60 −0
Original line number Diff line number Diff line
@@ -104,6 +104,12 @@ static struct configuration_offsets_t {
  jfieldID mScreenHeightDpOffset;
} gConfigurationOffsets;

static struct arraymap_offsets_t {
  jclass classObject;
  jmethodID constructor;
  jmethodID put;
} gArrayMapOffsets;

jclass g_stringClass = nullptr;

// ----------------------------------------------------------------------------
@@ -326,6 +332,50 @@ static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) {
  return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr));
}

static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr,
                                        jstring package_name) {
  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
  const ScopedUtfChars package_name_utf8(env, package_name);
  CHECK(package_name_utf8.c_str() != nullptr);
  const std::string std_package_name(package_name_utf8.c_str());
  const std::unordered_map<std::string, std::string>* map = nullptr;

  assetmanager->ForEachPackage([&](const std::string& this_package_name, uint8_t package_id) {
    if (this_package_name == std_package_name) {
      map = assetmanager->GetOverlayableMapForPackage(package_id);
    }
  });

  if (map == nullptr) {
    return nullptr;
  }

  jobject array_map = env->NewObject(gArrayMapOffsets.classObject, gArrayMapOffsets.constructor);
  if (array_map == nullptr) {
    return nullptr;
  }

  for (const auto& iter : *map) {
    jstring name = env->NewStringUTF(iter.first.c_str());
    if (env->ExceptionCheck()) {
      return nullptr;
    }

    jstring actor = env->NewStringUTF(iter.second.c_str());
    if (env->ExceptionCheck()) {
      env->DeleteLocalRef(name);
      return nullptr;
    }

    env->CallObjectMethod(array_map, gArrayMapOffsets.put, name, actor);

    env->DeleteLocalRef(name);
    env->DeleteLocalRef(actor);
  }

  return array_map;
}

static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset,
                                          jlongArray out_offsets) {
  off64_t start_offset, length;
@@ -1524,6 +1574,8 @@ static const JNINativeMethod gAssetManagerMethods[] = {
    {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
    {"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;",
     (void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid},
    {"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;",
     (void*)NativeGetOverlayableMap},

    // Global management/debug methods.
    {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
@@ -1575,6 +1627,14 @@ int register_android_content_AssetManager(JNIEnv* env) {
  gConfigurationOffsets.mScreenHeightDpOffset =
      GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I");

  jclass arrayMapClass = FindClassOrDie(env, "android/util/ArrayMap");
  gArrayMapOffsets.classObject = MakeGlobalRefOrDie(env, arrayMapClass);
  gArrayMapOffsets.constructor =
      GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "<init>", "()V");
  gArrayMapOffsets.put =
      GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "put",
                       "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

  return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
                              NELEM(gAssetManagerMethods));
}
+21 −0
Original line number Diff line number Diff line
@@ -203,6 +203,27 @@ const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCooki
  return nullptr;
}

const std::unordered_map<std::string, std::string>*
  AssetManager2::GetOverlayableMapForPackage(uint32_t package_id) const {

  if (package_id >= package_ids_.size()) {
    return nullptr;
  }

  const size_t idx = package_ids_[package_id];
  if (idx == 0xff) {
    return nullptr;
  }

  const PackageGroup& package_group = package_groups_[idx];
  if (package_group.packages_.size() == 0) {
    return nullptr;
  }

  const auto loaded_package = package_group.packages_[0].loaded_package_;
  return &loaded_package->GetOverlayableMap();
}

void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
  const int diff = configuration_.diff(configuration);
  configuration_ = configuration;
+7 −0
Original line number Diff line number Diff line
@@ -598,6 +598,13 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
        std::string actor;
        util::ReadUtf16StringFromDevice(header->actor, arraysize(header->actor), &actor);

        if (loaded_package->overlayable_map_.find(name) !=
            loaded_package->overlayable_map_.end()) {
          LOG(ERROR) << "Multiple <overlayable> blocks with the same name '" << name << "'.";
          return {};
        }
        loaded_package->overlayable_map_.emplace(name, actor);

        // Iterate over the overlayable policy chunks contained within the overlayable chunk data
        ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size());
        while (overlayable_iter.HasNext()) {
+3 −0
Original line number Diff line number Diff line
@@ -124,6 +124,9 @@ class AssetManager2 {
  // This may be nullptr if the APK represented by `cookie` has no resource table.
  const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const;

  const std::unordered_map<std::string, std::string>*
    GetOverlayableMapForPackage(uint32_t package_id) const;

  // Sets/resets the configuration for this AssetManager. This will cause all
  // caches that are related to the configuration change to be invalidated.
  void SetConfiguration(const ResTable_config& configuration);
Loading