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

Commit b8a61d13 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Android (Google) Code Review
Browse files

Merge "Fail install when resources.arsc is compressed" into rvc-dev

parents 2dc9632e 192400cf
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1550,6 +1550,16 @@ public abstract class PackageManager {
     */
    public static final int INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED = -123;

    /**
     * Installation failed return code: the {@code resources.arsc} of one of the APKs being
     * installed is compressed or not aligned on a 4-byte boundary. Resource tables that cannot be
     * memory mapped exert excess memory pressure on the system and drastically slow down
     * construction of {@link Resources} objects.
     *
     * @hide
     */
    public static final int INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED = -124;

    /** @hide */
    @IntDef(flag = true, prefix = { "DELETE_" }, value = {
            DELETE_KEEP_DATA,
+15 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED;
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
import static android.os.Build.VERSION_CODES.DONUT;
import static android.os.Build.VERSION_CODES.O;
@@ -344,7 +345,20 @@ public class ParsingPackageUtils {
                                + result.getErrorMessage());
            }

            ParsingPackage pkg = result.getResult();
            final ParsingPackage pkg = result.getResult();
            if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.R
                    && assets.containsAllocatedTable()) {
                final ParseResult<?> deferResult = input.deferError(
                        "Targeting R+ (version" + Build.VERSION_CODES.R + " and above) requires the"
                                + " resources.arsc of installed APKs to be stored uncompressed and"
                                + " aligned on a 4-byte boundary",
                        DeferredError.RESOURCES_ARSC_COMPRESSED);
                if (deferResult.isError()) {
                    return input.error(INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED,
                            deferResult.getErrorMessage());
                }
            }

            ApkAssets apkAssets = assets.getApkAssets()[0];
            if (apkAssets.definesOverlayable()) {
                SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
+10 −0
Original line number Diff line number Diff line
@@ -59,6 +59,16 @@ public interface ParseInput {
        @ChangeId
        @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
        public static final long EMPTY_INTENT_ACTION_CATEGORY = 151163173;

        /**
         * The {@code resources.arsc} of one of the APKs being installed is compressed or not
         * aligned on a 4-byte boundary. Resource tables that cannot be memory mapped exert excess
         * memory pressure on the system and drastically slow down construction of
         * {@link android.content.res.Resources} objects.
         */
        @ChangeId
        @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
        public static final long RESOURCES_ARSC_COMPRESSED = 132742131;
    }

    <ResultType> ParseResult<ResultType> success(ResultType result);
+14 −0
Original line number Diff line number Diff line
@@ -819,6 +819,19 @@ public final class AssetManager implements AutoCloseable {
        }
    }

    /**
     * Returns whether the {@code resources.arsc} of any loaded apk assets is allocated in RAM
     * (not mmapped).
     *
     * @hide
     */
    public boolean containsAllocatedTable() {
        synchronized (this) {
            ensureValidLocked();
            return nativeContainsAllocatedTable(mObject);
        }
    }

    CharSequence getPooledStringForCookie(int cookie, int id) {
        // Cookies map to ApkAssets starting at 1.
        return getApkAssets()[cookie - 1].getStringFromPool(id);
@@ -1482,6 +1495,7 @@ public final class AssetManager implements AutoCloseable {
            long ptr, boolean includeOverlays, boolean includeLoaders);

    // File native methods.
    private static native boolean nativeContainsAllocatedTable(long ptr);
    private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
            throws IOException;
    private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
+6 −0
Original line number Diff line number Diff line
@@ -481,6 +481,11 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
  return sparse_array;
}

static jboolean ContainsAllocatedTable(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
  ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr));
  return assetmanager->ContainsAllocatedTable();
}

static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring path) {
  ScopedUtfChars path_utf8(env, path);
  if (path_utf8.c_str() == nullptr) {
@@ -1495,6 +1500,7 @@ static const JNINativeMethod gAssetManagerMethods[] = {
     (void*)NativeGetAssignedPackageIdentifiers},

    // AssetManager file methods.
    {"nativeContainsAllocatedTable", "(J)Z", (void*)ContainsAllocatedTable},
    {"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList},
    {"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset},
    {"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
Loading