Merge "Fail install when resources.arsc is compressed" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b8a61d13c2
@@ -1550,6 +1550,16 @@ public abstract class PackageManager {
|
|||||||
*/
|
*/
|
||||||
public static final int INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED = -123;
|
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 */
|
/** @hide */
|
||||||
@IntDef(flag = true, prefix = { "DELETE_" }, value = {
|
@IntDef(flag = true, prefix = { "DELETE_" }, value = {
|
||||||
DELETE_KEEP_DATA,
|
DELETE_KEEP_DATA,
|
||||||
|
|||||||
@@ -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_BAD_MANIFEST;
|
||||||
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
|
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_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.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
|
||||||
import static android.os.Build.VERSION_CODES.DONUT;
|
import static android.os.Build.VERSION_CODES.DONUT;
|
||||||
import static android.os.Build.VERSION_CODES.O;
|
import static android.os.Build.VERSION_CODES.O;
|
||||||
@@ -344,7 +345,20 @@ public class ParsingPackageUtils {
|
|||||||
+ result.getErrorMessage());
|
+ 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];
|
ApkAssets apkAssets = assets.getApkAssets()[0];
|
||||||
if (apkAssets.definesOverlayable()) {
|
if (apkAssets.definesOverlayable()) {
|
||||||
SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
|
SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ public interface ParseInput {
|
|||||||
@ChangeId
|
@ChangeId
|
||||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
|
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
|
||||||
public static final long EMPTY_INTENT_ACTION_CATEGORY = 151163173;
|
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);
|
<ResultType> ParseResult<ResultType> success(ResultType result);
|
||||||
|
|||||||
@@ -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) {
|
CharSequence getPooledStringForCookie(int cookie, int id) {
|
||||||
// Cookies map to ApkAssets starting at 1.
|
// Cookies map to ApkAssets starting at 1.
|
||||||
return getApkAssets()[cookie - 1].getStringFromPool(id);
|
return getApkAssets()[cookie - 1].getStringFromPool(id);
|
||||||
@@ -1482,6 +1495,7 @@ public final class AssetManager implements AutoCloseable {
|
|||||||
long ptr, boolean includeOverlays, boolean includeLoaders);
|
long ptr, boolean includeOverlays, boolean includeLoaders);
|
||||||
|
|
||||||
// File native methods.
|
// File native methods.
|
||||||
|
private static native boolean nativeContainsAllocatedTable(long ptr);
|
||||||
private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
|
private static native @Nullable String[] nativeList(long ptr, @NonNull String path)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
|
private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode);
|
||||||
|
|||||||
@@ -481,6 +481,11 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
|
|||||||
return sparse_array;
|
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) {
|
static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring path) {
|
||||||
ScopedUtfChars path_utf8(env, path);
|
ScopedUtfChars path_utf8(env, path);
|
||||||
if (path_utf8.c_str() == nullptr) {
|
if (path_utf8.c_str() == nullptr) {
|
||||||
@@ -1495,6 +1500,7 @@ static const JNINativeMethod gAssetManagerMethods[] = {
|
|||||||
(void*)NativeGetAssignedPackageIdentifiers},
|
(void*)NativeGetAssignedPackageIdentifiers},
|
||||||
|
|
||||||
// AssetManager file methods.
|
// AssetManager file methods.
|
||||||
|
{"nativeContainsAllocatedTable", "(J)Z", (void*)ContainsAllocatedTable},
|
||||||
{"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList},
|
{"nativeList", "(JLjava/lang/String;)[Ljava/lang/String;", (void*)NativeList},
|
||||||
{"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset},
|
{"nativeOpenAsset", "(JLjava/lang/String;I)J", (void*)NativeOpenAsset},
|
||||||
{"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
|
{"nativeOpenAssetFd", "(JLjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
|
||||||
|
|||||||
@@ -331,6 +331,11 @@ bool AssetManager2::GetOverlayablesToString(const android::StringPiece& package_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssetManager2::ContainsAllocatedTable() const {
|
||||||
|
return std::find_if(apk_assets_.begin(), apk_assets_.end(),
|
||||||
|
std::mem_fn(&ApkAssets::IsTableAllocated)) != apk_assets_.end();
|
||||||
|
}
|
||||||
|
|
||||||
void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
|
void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
|
||||||
const int diff = configuration_.diff(configuration);
|
const int diff = configuration_.diff(configuration);
|
||||||
configuration_ = configuration;
|
configuration_ = configuration;
|
||||||
|
|||||||
@@ -119,31 +119,36 @@ class ApkAssets {
|
|||||||
package_property_t flags = 0U,
|
package_property_t flags = 0U,
|
||||||
std::unique_ptr<const AssetsProvider> override_asset = nullptr);
|
std::unique_ptr<const AssetsProvider> override_asset = nullptr);
|
||||||
|
|
||||||
inline const std::string& GetPath() const {
|
const std::string& GetPath() const {
|
||||||
return path_;
|
return path_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const AssetsProvider* GetAssetsProvider() const {
|
const AssetsProvider* GetAssetsProvider() const {
|
||||||
return assets_provider_.get();
|
return assets_provider_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is never nullptr.
|
// This is never nullptr.
|
||||||
inline const LoadedArsc* GetLoadedArsc() const {
|
const LoadedArsc* GetLoadedArsc() const {
|
||||||
return loaded_arsc_.get();
|
return loaded_arsc_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const LoadedIdmap* GetLoadedIdmap() const {
|
const LoadedIdmap* GetLoadedIdmap() const {
|
||||||
return loaded_idmap_.get();
|
return loaded_idmap_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsLoader() const {
|
bool IsLoader() const {
|
||||||
return (property_flags_ & PROPERTY_LOADER) != 0;
|
return (property_flags_ & PROPERTY_LOADER) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsOverlay() const {
|
bool IsOverlay() const {
|
||||||
return loaded_idmap_ != nullptr;
|
return loaded_idmap_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns whether the resources.arsc is allocated in RAM (not mmapped).
|
||||||
|
bool IsTableAllocated() const {
|
||||||
|
return resources_asset_ && resources_asset_->isAllocated();
|
||||||
|
}
|
||||||
|
|
||||||
bool IsUpToDate() const;
|
bool IsUpToDate() const;
|
||||||
|
|
||||||
// Creates an Asset from a file on disk.
|
// Creates an Asset from a file on disk.
|
||||||
|
|||||||
@@ -134,6 +134,9 @@ class AssetManager2 {
|
|||||||
const std::unordered_map<std::string, std::string>*
|
const std::unordered_map<std::string, std::string>*
|
||||||
GetOverlayableMapForPackage(uint32_t package_id) const;
|
GetOverlayableMapForPackage(uint32_t package_id) const;
|
||||||
|
|
||||||
|
// Returns whether the resources.arsc of any loaded apk assets is allocated in RAM (not mmapped).
|
||||||
|
bool ContainsAllocatedTable() const;
|
||||||
|
|
||||||
// Sets/resets the configuration for this AssetManager. This will cause all
|
// Sets/resets the configuration for this AssetManager. This will cause all
|
||||||
// caches that are related to the configuration change to be invalidated.
|
// caches that are related to the configuration change to be invalidated.
|
||||||
void SetConfiguration(const ResTable_config& configuration);
|
void SetConfiguration(const ResTable_config& configuration);
|
||||||
|
|||||||
Reference in New Issue
Block a user