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

Commit db54beb9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Prepare for switch to idmap2"

parents c2d93fcb 06a1ac82
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -4333,6 +4333,16 @@ public abstract class Context {
     */
    public static final String OVERLAY_SERVICE = "overlay";

    /**
     * Use with {@link #getSystemService(String)} to retrieve a
     * {android.os.IIdmap2} for managing idmap files (used by overlay
     * packages).
     *
     * @see #getSystemService(String)
     * @hide
     */
    public static final String IDMAP_SERVICE = "idmap";

    /**
     * Use with {@link #getSystemService(String)} to retrieve a
     * {@link VrManager} for accessing the VR service.
+15 −3
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import java.util.HashMap;
public final class AssetManager implements AutoCloseable {
    private static final String TAG = "AssetManager";
    private static final boolean DEBUG_REFS = false;
    private static final boolean FEATURE_FLAG_IDMAP2 = false;

    private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";

@@ -195,13 +196,23 @@ public final class AssetManager implements AutoCloseable {
            return;
        }

        // Make sure that all IDMAPs are up to date.
        nativeVerifySystemIdmaps();

        try {
            final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
            apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/));
            if (FEATURE_FLAG_IDMAP2) {
                final String[] systemIdmapPaths =
                    nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
                if (systemIdmapPaths == null) {
                    throw new IOException("idmap2 scan failed");
                }
                for (String idmapPath : systemIdmapPaths) {
                    apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
                }
            } else {
                nativeVerifySystemIdmaps();
                loadStaticRuntimeOverlays(apkAssets);
            }

            sSystemApkAssetsSet = new ArraySet<>(apkAssets);
            sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]);
@@ -1404,6 +1415,7 @@ public final class AssetManager implements AutoCloseable {
    private static native long nativeAssetGetRemainingLength(long assetPtr);

    private static native void nativeVerifySystemIdmaps();
    private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid();

    // Global debug native methods.
    /**
+83 −4
Original line number Diff line number Diff line
@@ -24,9 +24,13 @@
#include <sys/system_properties.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <private/android_filesystem_config.h> // for AID_SYSTEM

#include <sstream>
#include <string>

#include "android-base/logging.h"
#include "android-base/properties.h"
#include "android-base/stringprintf.h"
@@ -38,6 +42,7 @@
#include "androidfw/AssetManager2.h"
#include "androidfw/AttributeResolution.h"
#include "androidfw/MutexGuard.h"
#include "androidfw/PosixUtils.h"
#include "androidfw/ResourceTypes.h"
#include "core_jni_helpers.h"
#include "jni.h"
@@ -54,6 +59,7 @@ extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);

using ::android::base::StringPrintf;
using ::android::util::ExecuteBinary;

namespace android {

@@ -161,18 +167,20 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
      argv[argc++] = AssetManager::IDMAP_DIR;

      // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
      // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
      // use VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
      // addition to VENDOR_OVERLAY_DIR.
      std::string overlay_theme_path = base::GetProperty(AssetManager::OVERLAY_THEME_DIR_PROPERTY,
                                                         "");
      if (!overlay_theme_path.empty()) {
        overlay_theme_path = std::string(AssetManager::OVERLAY_DIR) + "/" + overlay_theme_path;
        overlay_theme_path =
          std::string(AssetManager::VENDOR_OVERLAY_DIR) + "/" + overlay_theme_path;
        if (stat(overlay_theme_path.c_str(), &st) == 0) {
          argv[argc++] = overlay_theme_path.c_str();
        }
      }

      if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
        argv[argc++] = AssetManager::OVERLAY_DIR;
      if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
        argv[argc++] = AssetManager::VENDOR_OVERLAY_DIR;
      }

      if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
@@ -200,6 +208,75 @@ static void NativeVerifySystemIdmaps(JNIEnv* /*env*/, jclass /*clazz*/) {
  }
}

static jobjectArray NativeCreateIdmapsForStaticOverlaysTargetingAndroid(JNIEnv* env,
                                                                        jclass /*clazz*/) {
  // --input-directory can be given multiple times, but idmap2 expects the directory to exist
  std::vector<std::string> input_dirs;
  struct stat st;
  if (stat(AssetManager::VENDOR_OVERLAY_DIR, &st) == 0) {
    input_dirs.push_back(AssetManager::VENDOR_OVERLAY_DIR);
  }

  if (stat(AssetManager::PRODUCT_OVERLAY_DIR, &st) == 0) {
    input_dirs.push_back(AssetManager::PRODUCT_OVERLAY_DIR);
  }

  if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
    input_dirs.push_back(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR);
  }

  if (input_dirs.empty()) {
    LOG(WARNING) << "no directories for idmap2 to scan";
    return env->NewObjectArray(0, g_stringClass, nullptr);
  }

  std::vector<std::string> argv{"/system/bin/idmap2",
    "scan",
    "--recursive",
    "--target-package-name", "android",
    "--target-apk-path", "/system/framework/framework-res.apk",
    "--output-directory", "/data/resource-cache"};

  for (const auto& dir : input_dirs) {
    argv.push_back("--input-directory");
    argv.push_back(dir);
  }

  const auto result = ExecuteBinary(argv);

  if (!result) {
      LOG(ERROR) << "failed to execute idmap2";
      return nullptr;
  }

  if (result->status != 0) {
    LOG(ERROR) << "idmap2: " << result->stderr;
    return nullptr;
  }

  std::vector<std::string> idmap_paths;
  std::istringstream input(result->stdout);
  std::string path;
  while (std::getline(input, path)) {
    idmap_paths.push_back(path);
  }

  jobjectArray array = env->NewObjectArray(idmap_paths.size(), g_stringClass, nullptr);
  if (array == nullptr) {
    return nullptr;
  }
  for (size_t i = 0; i < idmap_paths.size(); i++) {
    const std::string path = idmap_paths[i];
    jstring java_string = env->NewStringUTF(path.c_str());
    if (env->ExceptionCheck()) {
      return nullptr;
    }
    env->SetObjectArrayElement(array, i, java_string);
    env->DeleteLocalRef(java_string);
  }
  return array;
}

static jint CopyValue(JNIEnv* env, ApkAssetsCookie cookie, const Res_value& value, uint32_t ref,
                      uint32_t type_spec_flags, ResTable_config* config, jobject out_typed_value) {
  env->SetIntField(out_typed_value, gTypedValueOffsets.mType, value.dataType);
@@ -1405,6 +1482,8 @@ static const JNINativeMethod gAssetManagerMethods[] = {

    // System/idmap related methods.
    {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps},
    {"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;",
     (void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid},

    // Global management/debug methods.
    {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount},
+2 −2
Original line number Diff line number Diff line
@@ -85,7 +85,7 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
  // See AssetManager.cpp for more details on overlay-subdir.
  static const char* kOverlayDir = "/system/vendor/overlay/";
  static const char* kVendorOverlayDir = "/vendor/overlay";
  static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
  static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
  static const char* kSystemProductOverlayDir = "/system/product/overlay/";
  static const char* kProductOverlayDir = "/product/overlay";
  static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
@@ -93,7 +93,7 @@ bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
  static const char* kApkSuffix = ".apk";

  if ((android::base::StartsWith(path, kOverlayDir)
       || android::base::StartsWith(path, kOverlaySubdir)
       || android::base::StartsWith(path, kVendorOverlaySubdir)
       || android::base::StartsWith(path, kVendorOverlayDir)
       || android::base::StartsWith(path, kSystemProductOverlayDir)
       || android::base::StartsWith(path, kProductOverlayDir)
+1 −1
Original line number Diff line number Diff line
@@ -72,7 +72,7 @@ static volatile int32_t gCount = 0;

const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
const char* AssetManager::VENDOR_OVERLAY_DIR = "/vendor/overlay";
const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
Loading