diff options
| author | Ryan Mitchell <rtmitchell@google.com> | 2020-04-13 14:57:19 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-04-13 14:57:19 +0000 |
| commit | b8a61d13c2fd447abe5ce9cd635ea3a49c08ebe9 (patch) | |
| tree | 409f4650f743226a23edce1febcafd7700af4f02 /core/java/android | |
| parent | 2dc9632eb555fe4e3fe46ccf6454200025569c86 (diff) | |
| parent | 192400cf334e0e8befe336861a6d214c6a88c993 (diff) | |
Merge "Fail install when resources.arsc is compressed" into rvc-dev
Diffstat (limited to 'core/java/android')
4 files changed, 49 insertions, 1 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 9a2e07e9cfbd..9ca2db970eb7 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -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, diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 6bd8b1d9d7c0..c61362feaeae 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -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(); diff --git a/core/java/android/content/pm/parsing/result/ParseInput.java b/core/java/android/content/pm/parsing/result/ParseInput.java index 538510049e04..6b659bea84f1 100644 --- a/core/java/android/content/pm/parsing/result/ParseInput.java +++ b/core/java/android/content/pm/parsing/result/ParseInput.java @@ -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); diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index d2103af1d247..15a184f0e5ef 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -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); |
