Merge changes from topic "inc-dis" into sc-dev
* changes: Disable incremental hardening on own resources StringBlock incremental hardening default values
This commit is contained in:
committed by
Android (Google) Code Review
commit
488522c9c5
@@ -323,7 +323,7 @@ ApkResourceContainer::ApkResourceContainer(std::unique_ptr<ZipAssetsProvider> zi
|
|||||||
|
|
||||||
Result<std::unique_ptr<ApkResourceContainer>> ApkResourceContainer::FromPath(
|
Result<std::unique_ptr<ApkResourceContainer>> ApkResourceContainer::FromPath(
|
||||||
const std::string& path) {
|
const std::string& path) {
|
||||||
auto zip_assets = ZipAssetsProvider::Create(path);
|
auto zip_assets = ZipAssetsProvider::Create(path, 0 /* flags */);
|
||||||
if (zip_assets == nullptr) {
|
if (zip_assets == nullptr) {
|
||||||
return Error("failed to load zip assets");
|
return Error("failed to load zip assets");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
namespace android::idmap2 {
|
namespace android::idmap2 {
|
||||||
|
|
||||||
Result<XmlParser> CreateTestParser(const std::string& test_file) {
|
Result<XmlParser> CreateTestParser(const std::string& test_file) {
|
||||||
auto zip = ZipAssetsProvider::Create(GetTestDataPath() + "/target/target.apk");
|
auto zip = ZipAssetsProvider::Create(GetTestDataPath() + "/target/target.apk", 0 /* flags */);
|
||||||
if (zip == nullptr) {
|
if (zip == nullptr) {
|
||||||
return Error("Failed to open zip file");
|
return Error("Failed to open zip file");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1289,6 +1289,10 @@ public final class LoadedApk {
|
|||||||
throw new AssertionError("null split not found");
|
throw new AssertionError("null split not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Process.myUid() == mApplicationInfo.uid) {
|
||||||
|
ResourcesManager.getInstance().initializeApplicationPaths(mResDir, splitPaths);
|
||||||
|
}
|
||||||
|
|
||||||
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
|
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
|
||||||
splitPaths, mLegacyOverlayDirs, mOverlayPaths,
|
splitPaths, mLegacyOverlayDirs, mOverlayPaths,
|
||||||
mApplicationInfo.sharedLibraryFiles, null, null, getCompatibilityInfo(),
|
mApplicationInfo.sharedLibraryFiles, null, null, getCompatibilityInfo(),
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import android.os.IBinder;
|
|||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@@ -260,6 +261,12 @@ public class ResourcesManager {
|
|||||||
*/
|
*/
|
||||||
private final UpdateHandler mUpdateCallbacks = new UpdateHandler();
|
private final UpdateHandler mUpdateCallbacks = new UpdateHandler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set of APK paths belonging to this process. This is used to disable incremental
|
||||||
|
* installation crash protections on these APKs so the app either behaves as expects or crashes.
|
||||||
|
*/
|
||||||
|
private final ArraySet<String> mApplicationOwnedApks = new ArraySet<>();
|
||||||
|
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public ResourcesManager() {
|
public ResourcesManager() {
|
||||||
}
|
}
|
||||||
@@ -424,6 +431,32 @@ public class ResourcesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the set of APKs owned by the application running in this process.
|
||||||
|
*/
|
||||||
|
public void initializeApplicationPaths(@NonNull String sourceDir,
|
||||||
|
@Nullable String[] splitDirs) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mApplicationOwnedApks.isEmpty()) {
|
||||||
|
addApplicationPathsLocked(sourceDir, splitDirs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the set of APKs owned by the application running in this process.
|
||||||
|
*
|
||||||
|
* This method only appends to the set of APKs owned by this process because the previous APKs
|
||||||
|
* paths still belong to the application running in this process.
|
||||||
|
*/
|
||||||
|
private void addApplicationPathsLocked(@NonNull String sourceDir,
|
||||||
|
@Nullable String[] splitDirs) {
|
||||||
|
mApplicationOwnedApks.add(sourceDir);
|
||||||
|
if (splitDirs != null) {
|
||||||
|
mApplicationOwnedApks.addAll(Arrays.asList(splitDirs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String overlayPathToIdmapPath(String path) {
|
private static String overlayPathToIdmapPath(String path) {
|
||||||
return "/data/resource-cache/" + path.substring(1).replace('/', '@') + "@idmap";
|
return "/data/resource-cache/" + path.substring(1).replace('/', '@') + "@idmap";
|
||||||
}
|
}
|
||||||
@@ -445,13 +478,17 @@ public class ResourcesManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must load this from disk.
|
int flags = 0;
|
||||||
|
if (key.sharedLib) {
|
||||||
|
flags |= ApkAssets.PROPERTY_DYNAMIC;
|
||||||
|
}
|
||||||
|
if (mApplicationOwnedApks.contains(key.path)) {
|
||||||
|
flags |= ApkAssets.PROPERTY_DISABLE_INCREMENTAL_HARDENING;
|
||||||
|
}
|
||||||
if (key.overlay) {
|
if (key.overlay) {
|
||||||
apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(key.path),
|
apkAssets = ApkAssets.loadOverlayFromPath(overlayPathToIdmapPath(key.path), flags);
|
||||||
0 /*flags*/);
|
|
||||||
} else {
|
} else {
|
||||||
apkAssets = ApkAssets.loadFromPath(key.path,
|
apkAssets = ApkAssets.loadFromPath(key.path, flags);
|
||||||
key.sharedLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -1437,6 +1474,10 @@ public class ResourcesManager {
|
|||||||
String[] copiedResourceDirs = combinedOverlayPaths(appInfo.resourceDirs,
|
String[] copiedResourceDirs = combinedOverlayPaths(appInfo.resourceDirs,
|
||||||
appInfo.overlayPaths);
|
appInfo.overlayPaths);
|
||||||
|
|
||||||
|
if (appInfo.uid == myUid) {
|
||||||
|
addApplicationPathsLocked(baseCodePath, copiedSplitDirs);
|
||||||
|
}
|
||||||
|
|
||||||
final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
|
final ArrayMap<ResourcesImpl, ResourcesKey> updatedResourceKeys = new ArrayMap<>();
|
||||||
final int implCount = mResourceImpls.size();
|
final int implCount = mResourceImpls.size();
|
||||||
for (int i = 0; i < implCount; i++) {
|
for (int i = 0; i < implCount; i++) {
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ public final class ApkAssets {
|
|||||||
*/
|
*/
|
||||||
private static final int PROPERTY_OVERLAY = 1 << 3;
|
private static final int PROPERTY_OVERLAY = 1 << 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The apk assets is owned by the application running in this process and incremental crash
|
||||||
|
* protections for this APK must be disabled.
|
||||||
|
*/
|
||||||
|
public static final int PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1 << 4;
|
||||||
|
|
||||||
/** Flags that change the behavior of loaded apk assets. */
|
/** Flags that change the behavior of loaded apk assets. */
|
||||||
@IntDef(prefix = { "PROPERTY_" }, value = {
|
@IntDef(prefix = { "PROPERTY_" }, value = {
|
||||||
PROPERTY_SYSTEM,
|
PROPERTY_SYSTEM,
|
||||||
@@ -334,13 +340,14 @@ public final class ApkAssets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
CharSequence getStringFromPool(int idx) {
|
CharSequence getStringFromPool(int idx) {
|
||||||
if (mStringBlock == null) {
|
if (mStringBlock == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
return mStringBlock.get(idx);
|
return mStringBlock.getSequence(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -550,7 +550,9 @@ public final class AssetManager implements AutoCloseable {
|
|||||||
outValue.changingConfigurations);
|
outValue.changingConfigurations);
|
||||||
|
|
||||||
if (outValue.type == TypedValue.TYPE_STRING) {
|
if (outValue.type == TypedValue.TYPE_STRING) {
|
||||||
outValue.string = getPooledStringForCookie(cookie, outValue.data);
|
if ((outValue.string = getPooledStringForCookie(cookie, outValue.data)) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -731,7 +733,9 @@ public final class AssetManager implements AutoCloseable {
|
|||||||
outValue.changingConfigurations);
|
outValue.changingConfigurations);
|
||||||
|
|
||||||
if (outValue.type == TypedValue.TYPE_STRING) {
|
if (outValue.type == TypedValue.TYPE_STRING) {
|
||||||
outValue.string = getPooledStringForCookie(cookie, outValue.data);
|
if ((outValue.string = getPooledStringForCookie(cookie, outValue.data)) == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -833,6 +837,7 @@ public final class AssetManager implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
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);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package android.content.res;
|
package android.content.res;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
@@ -86,8 +88,19 @@ public final class StringBlock implements Closeable {
|
|||||||
+ ": " + nativeGetSize(mNative));
|
+ ": " + nativeGetSize(mNative));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #getSequence(int)} which can return null when a string cannot be found
|
||||||
|
* due to incremental installation.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
@UnsupportedAppUsage
|
@UnsupportedAppUsage
|
||||||
public CharSequence get(int idx) {
|
public CharSequence get(int idx) {
|
||||||
|
CharSequence seq = getSequence(idx);
|
||||||
|
return seq == null ? "" : seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public CharSequence getSequence(int idx) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
if (mStrings != null) {
|
if (mStrings != null) {
|
||||||
CharSequence res = mStrings[idx];
|
CharSequence res = mStrings[idx];
|
||||||
@@ -108,6 +121,9 @@ public final class StringBlock implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String str = nativeGetString(mNative, idx);
|
String str = nativeGetString(mNative, idx);
|
||||||
|
if (str == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
CharSequence res = str;
|
CharSequence res = str;
|
||||||
int[] style = nativeGetStyle(mNative, idx);
|
int[] style = nativeGetStyle(mNative, idx);
|
||||||
if (localLOGV) Log.v(TAG, "Got string: " + str);
|
if (localLOGV) Log.v(TAG, "Got string: " + str);
|
||||||
@@ -133,6 +149,9 @@ public final class StringBlock implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String styleTag = nativeGetString(mNative, styleId);
|
String styleTag = nativeGetString(mNative, styleId);
|
||||||
|
if (styleTag == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (styleTag.equals("b")) {
|
if (styleTag.equals("b")) {
|
||||||
mStyleIDs.boldId = styleId;
|
mStyleIDs.boldId = styleId;
|
||||||
@@ -161,8 +180,10 @@ public final class StringBlock implements Closeable {
|
|||||||
|
|
||||||
res = applyStyles(str, style, mStyleIDs);
|
res = applyStyles(str, style, mStyleIDs);
|
||||||
}
|
}
|
||||||
if (mStrings != null) mStrings[idx] = res;
|
if (res != null) {
|
||||||
else mSparseStrings.put(idx, res);
|
if (mStrings != null) mStrings[idx] = res;
|
||||||
|
else mSparseStrings.put(idx, res);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,6 +224,7 @@ public final class StringBlock implements Closeable {
|
|||||||
private int marqueeId = -1;
|
private int marqueeId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private CharSequence applyStyles(String str, int[] style, StyleIDs ids) {
|
private CharSequence applyStyles(String str, int[] style, StyleIDs ids) {
|
||||||
if (style.length == 0)
|
if (style.length == 0)
|
||||||
return str;
|
return str;
|
||||||
@@ -260,6 +282,9 @@ public final class StringBlock implements Closeable {
|
|||||||
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
Spannable.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
} else {
|
} else {
|
||||||
String tag = nativeGetString(mNative, type);
|
String tag = nativeGetString(mNative, type);
|
||||||
|
if (tag == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (tag.startsWith("font;")) {
|
if (tag.startsWith("font;")) {
|
||||||
String sub;
|
String sub;
|
||||||
|
|||||||
@@ -1376,6 +1376,7 @@ public class TypedArray implements AutoCloseable {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
private CharSequence loadStringValueAt(int index) {
|
private CharSequence loadStringValueAt(int index) {
|
||||||
final int[] data = mData;
|
final int[] data = mData;
|
||||||
final int cookie = data[index + STYLE_ASSET_COOKIE];
|
final int cookie = data[index + STYLE_ASSET_COOKIE];
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.content.res;
|
|||||||
import static android.content.res.Resources.ID_NULL;
|
import static android.content.res.Resources.ID_NULL;
|
||||||
|
|
||||||
import android.annotation.AnyRes;
|
import android.annotation.AnyRes;
|
||||||
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.compat.annotation.UnsupportedAppUsage;
|
import android.compat.annotation.UnsupportedAppUsage;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@@ -161,9 +162,10 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
public int getDepth() {
|
public int getDepth() {
|
||||||
return mDepth;
|
return mDepth;
|
||||||
}
|
}
|
||||||
|
@Nullable
|
||||||
public String getText() {
|
public String getText() {
|
||||||
int id = nativeGetText(mParseState);
|
int id = nativeGetText(mParseState);
|
||||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null;
|
||||||
}
|
}
|
||||||
public int getLineNumber() {
|
public int getLineNumber() {
|
||||||
return nativeGetLineNumber(mParseState);
|
return nativeGetLineNumber(mParseState);
|
||||||
@@ -189,25 +191,29 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
|
@Nullable
|
||||||
public String getNamespace() {
|
public String getNamespace() {
|
||||||
int id = nativeGetNamespace(mParseState);
|
int id = nativeGetNamespace(mParseState);
|
||||||
return id >= 0 ? mStrings.get(id).toString() : "";
|
return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : "";
|
||||||
}
|
}
|
||||||
|
@Nullable
|
||||||
public String getName() {
|
public String getName() {
|
||||||
int id = nativeGetName(mParseState);
|
int id = nativeGetName(mParseState);
|
||||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null;
|
||||||
}
|
}
|
||||||
|
@NonNull
|
||||||
public String getAttributeNamespace(int index) {
|
public String getAttributeNamespace(int index) {
|
||||||
int id = nativeGetAttributeNamespace(mParseState, index);
|
int id = nativeGetAttributeNamespace(mParseState, index);
|
||||||
if (DEBUG) System.out.println("getAttributeNamespace of " + index + " = " + id);
|
if (DEBUG) System.out.println("getAttributeNamespace of " + index + " = " + id);
|
||||||
if (id >= 0) return mStrings.get(id).toString();
|
if (id >= 0) return getSequenceString(mStrings.getSequence(id));
|
||||||
else if (id == -1) return "";
|
else if (id == -1) return "";
|
||||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||||
}
|
}
|
||||||
|
@NonNull
|
||||||
public String getAttributeName(int index) {
|
public String getAttributeName(int index) {
|
||||||
int id = nativeGetAttributeName(mParseState, index);
|
int id = nativeGetAttributeName(mParseState, index);
|
||||||
if (DEBUG) System.out.println("getAttributeName of " + index + " = " + id);
|
if (DEBUG) System.out.println("getAttributeName of " + index + " = " + id);
|
||||||
if (id >= 0) return mStrings.get(id).toString();
|
if (id >= 0) return getSequenceString(mStrings.getSequence(id));
|
||||||
throw new IndexOutOfBoundsException(String.valueOf(index));
|
throw new IndexOutOfBoundsException(String.valueOf(index));
|
||||||
}
|
}
|
||||||
public String getAttributePrefix(int index) {
|
public String getAttributePrefix(int index) {
|
||||||
@@ -220,10 +226,11 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
public int getAttributeCount() {
|
public int getAttributeCount() {
|
||||||
return mEventType == START_TAG ? nativeGetAttributeCount(mParseState) : -1;
|
return mEventType == START_TAG ? nativeGetAttributeCount(mParseState) : -1;
|
||||||
}
|
}
|
||||||
|
@NonNull
|
||||||
public String getAttributeValue(int index) {
|
public String getAttributeValue(int index) {
|
||||||
int id = nativeGetAttributeStringValue(mParseState, index);
|
int id = nativeGetAttributeStringValue(mParseState, index);
|
||||||
if (DEBUG) System.out.println("getAttributeValue of " + index + " = " + id);
|
if (DEBUG) System.out.println("getAttributeValue of " + index + " = " + id);
|
||||||
if (id >= 0) return mStrings.get(id).toString();
|
if (id >= 0) return getSequenceString(mStrings.getSequence(id));
|
||||||
|
|
||||||
// May be some other type... check and try to convert if so.
|
// May be some other type... check and try to convert if so.
|
||||||
int t = nativeGetAttributeDataType(mParseState, index);
|
int t = nativeGetAttributeDataType(mParseState, index);
|
||||||
@@ -390,7 +397,7 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
int v = nativeGetAttributeData(mParseState, idx);
|
int v = nativeGetAttributeData(mParseState, idx);
|
||||||
if (t == TypedValue.TYPE_STRING) {
|
if (t == TypedValue.TYPE_STRING) {
|
||||||
return XmlUtils.convertValueToList(
|
return XmlUtils.convertValueToList(
|
||||||
mStrings.get(v), options, defaultValue);
|
mStrings.getSequence(v), options, defaultValue);
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -444,14 +451,15 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
throw new RuntimeException("not a float!");
|
throw new RuntimeException("not a float!");
|
||||||
}
|
}
|
||||||
|
@Nullable
|
||||||
public String getIdAttribute() {
|
public String getIdAttribute() {
|
||||||
int id = nativeGetIdAttribute(mParseState);
|
int id = nativeGetIdAttribute(mParseState);
|
||||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null;
|
||||||
}
|
}
|
||||||
|
@Nullable
|
||||||
public String getClassAttribute() {
|
public String getClassAttribute() {
|
||||||
int id = nativeGetClassAttribute(mParseState);
|
int id = nativeGetClassAttribute(mParseState);
|
||||||
return id >= 0 ? mStrings.get(id).toString() : null;
|
return id >= 0 ? getSequenceString(mStrings.getSequence(id)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIdAttributeResourceValue(int defaultValue) {
|
public int getIdAttributeResourceValue(int defaultValue) {
|
||||||
@@ -463,6 +471,17 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
return nativeGetStyleAttribute(mParseState);
|
return nativeGetStyleAttribute(mParseState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getSequenceString(@Nullable CharSequence str) {
|
||||||
|
if (str == null) {
|
||||||
|
// A value of null retrieved from a StringPool indicates that retrieval of the
|
||||||
|
// string failed due to incremental installation. The presence of all the XmlBlock
|
||||||
|
// data is verified when it is created, so this exception must not be possible.
|
||||||
|
throw new IllegalStateException("Retrieving a string from the StringPool of an"
|
||||||
|
+ " XmlBlock should never fail");
|
||||||
|
}
|
||||||
|
return str.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
synchronized (mBlock) {
|
synchronized (mBlock) {
|
||||||
if (mParseState != 0) {
|
if (mParseState != 0) {
|
||||||
@@ -472,13 +491,14 @@ public final class XmlBlock implements AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
/*package*/ final CharSequence getPooledString(int id) {
|
/*package*/ final CharSequence getPooledString(int id) {
|
||||||
return mStrings.get(id);
|
return mStrings.getSequence(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||||||
|
|||||||
@@ -212,10 +212,11 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma
|
|||||||
std::unique_ptr<ApkAssets> apk_assets;
|
std::unique_ptr<ApkAssets> apk_assets;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case FORMAT_APK: {
|
case FORMAT_APK: {
|
||||||
auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
|
auto assets = MultiAssetsProvider::Create(std::move(loader_assets),
|
||||||
ZipAssetsProvider::Create(path.c_str()));
|
ZipAssetsProvider::Create(path.c_str(),
|
||||||
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
|
property_flags));
|
||||||
break;
|
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case FORMAT_IDMAP:
|
case FORMAT_IDMAP:
|
||||||
apk_assets = ApkAssets::LoadOverlay(path.c_str(), property_flags);
|
apk_assets = ApkAssets::LoadOverlay(path.c_str(), property_flags);
|
||||||
@@ -271,11 +272,13 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t
|
|||||||
std::unique_ptr<const ApkAssets> apk_assets;
|
std::unique_ptr<const ApkAssets> apk_assets;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case FORMAT_APK: {
|
case FORMAT_APK: {
|
||||||
auto assets = MultiAssetsProvider::Create(
|
auto assets =
|
||||||
std::move(loader_assets),
|
MultiAssetsProvider::Create(std::move(loader_assets),
|
||||||
ZipAssetsProvider::Create(std::move(dup_fd), friendly_name_utf8.c_str()));
|
ZipAssetsProvider::Create(std::move(dup_fd),
|
||||||
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
|
friendly_name_utf8.c_str(),
|
||||||
break;
|
property_flags));
|
||||||
|
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case FORMAT_ARSC:
|
case FORMAT_ARSC:
|
||||||
apk_assets = ApkAssets::LoadTable(
|
apk_assets = ApkAssets::LoadTable(
|
||||||
@@ -336,12 +339,16 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_
|
|||||||
std::unique_ptr<const ApkAssets> apk_assets;
|
std::unique_ptr<const ApkAssets> apk_assets;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case FORMAT_APK: {
|
case FORMAT_APK: {
|
||||||
auto assets = MultiAssetsProvider::Create(
|
auto assets =
|
||||||
std::move(loader_assets),
|
MultiAssetsProvider::Create(std::move(loader_assets),
|
||||||
ZipAssetsProvider::Create(std::move(dup_fd), friendly_name_utf8.c_str(),
|
ZipAssetsProvider::Create(std::move(dup_fd),
|
||||||
static_cast<off64_t>(offset), static_cast<off64_t>(length)));
|
friendly_name_utf8.c_str(),
|
||||||
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
|
property_flags,
|
||||||
break;
|
static_cast<off64_t>(offset),
|
||||||
|
static_cast<off64_t>(
|
||||||
|
length)));
|
||||||
|
apk_assets = ApkAssets::Load(std::move(assets), property_flags);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case FORMAT_ARSC:
|
case FORMAT_ARSC:
|
||||||
apk_assets = ApkAssets::LoadTable(
|
apk_assets = ApkAssets::LoadTable(
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ static jstring android_content_StringBlock_nativeGetString(JNIEnv* env, jobject
|
|||||||
ResStringPool* osb = reinterpret_cast<ResStringPool*>(token);
|
ResStringPool* osb = reinterpret_cast<ResStringPool*>(token);
|
||||||
if (osb == NULL) {
|
if (osb == NULL) {
|
||||||
jniThrowNullPointerException(env, NULL);
|
jniThrowNullPointerException(env, NULL);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto str8 = osb->string8At(idx); str8.has_value()) {
|
if (auto str8 = osb->string8At(idx); str8.has_value()) {
|
||||||
@@ -80,9 +80,11 @@ static jstring android_content_StringBlock_nativeGetString(JNIEnv* env, jobject
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto str = osb->stringAt(idx);
|
auto str = osb->stringAt(idx);
|
||||||
if (UNLIKELY(!str.has_value())) {
|
if (IsIOError(str)) {
|
||||||
|
return NULL;
|
||||||
|
} else if (UNLIKELY(!str.has_value())) {
|
||||||
jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
|
jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return env->NewString((const jchar*)str->data(), str->size());
|
return env->NewString((const jchar*)str->data(), str->size());
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ ApkAssets::ApkAssets(std::unique_ptr<Asset> resources_asset,
|
|||||||
loaded_idmap_(std::move(loaded_idmap)) {}
|
loaded_idmap_(std::move(loaded_idmap)) {}
|
||||||
|
|
||||||
std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) {
|
std::unique_ptr<ApkAssets> ApkAssets::Load(const std::string& path, package_property_t flags) {
|
||||||
return Load(ZipAssetsProvider::Create(path), flags);
|
return Load(ZipAssetsProvider::Create(path, flags), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd,
|
std::unique_ptr<ApkAssets> ApkAssets::LoadFromFd(base::unique_fd fd,
|
||||||
@@ -91,7 +91,7 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
|
|||||||
overlay_assets = EmptyAssetsProvider::Create(overlay_path);
|
overlay_assets = EmptyAssetsProvider::Create(overlay_path);
|
||||||
} else {
|
} else {
|
||||||
// The overlay should be an APK.
|
// The overlay should be an APK.
|
||||||
overlay_assets = ZipAssetsProvider::Create(overlay_path);
|
overlay_assets = ZipAssetsProvider::Create(overlay_path, flags);
|
||||||
}
|
}
|
||||||
if (overlay_assets == nullptr) {
|
if (overlay_assets == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -85,12 +85,14 @@ const std::string& ZipAssetsProvider::PathOrDebugName::GetDebugName() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ZipAssetsProvider::ZipAssetsProvider(ZipArchiveHandle handle, PathOrDebugName&& path,
|
ZipAssetsProvider::ZipAssetsProvider(ZipArchiveHandle handle, PathOrDebugName&& path,
|
||||||
time_t last_mod_time)
|
package_property_t flags, time_t last_mod_time)
|
||||||
: zip_handle_(handle, ::CloseArchive),
|
: zip_handle_(handle, ::CloseArchive),
|
||||||
name_(std::forward<PathOrDebugName>(path)),
|
name_(std::forward<PathOrDebugName>(path)),
|
||||||
|
flags_(flags),
|
||||||
last_mod_time_(last_mod_time) {}
|
last_mod_time_(last_mod_time) {}
|
||||||
|
|
||||||
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path) {
|
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path,
|
||||||
|
package_property_t flags) {
|
||||||
ZipArchiveHandle handle;
|
ZipArchiveHandle handle;
|
||||||
if (int32_t result = OpenArchive(path.c_str(), &handle); result != 0) {
|
if (int32_t result = OpenArchive(path.c_str(), &handle); result != 0) {
|
||||||
LOG(ERROR) << "Failed to open APK '" << path << "': " << ::ErrorCodeString(result);
|
LOG(ERROR) << "Failed to open APK '" << path << "': " << ::ErrorCodeString(result);
|
||||||
@@ -109,11 +111,12 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(std::string path) {
|
|||||||
|
|
||||||
return std::unique_ptr<ZipAssetsProvider>(
|
return std::unique_ptr<ZipAssetsProvider>(
|
||||||
new ZipAssetsProvider(handle, PathOrDebugName{std::move(path),
|
new ZipAssetsProvider(handle, PathOrDebugName{std::move(path),
|
||||||
true /* is_path */}, sb.st_mtime));
|
true /* is_path */}, flags, sb.st_mtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
|
std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
|
||||||
std::string friendly_name,
|
std::string friendly_name,
|
||||||
|
package_property_t flags,
|
||||||
off64_t offset,
|
off64_t offset,
|
||||||
off64_t len) {
|
off64_t len) {
|
||||||
ZipArchiveHandle handle;
|
ZipArchiveHandle handle;
|
||||||
@@ -140,7 +143,7 @@ std::unique_ptr<ZipAssetsProvider> ZipAssetsProvider::Create(base::unique_fd fd,
|
|||||||
|
|
||||||
return std::unique_ptr<ZipAssetsProvider>(
|
return std::unique_ptr<ZipAssetsProvider>(
|
||||||
new ZipAssetsProvider(handle, PathOrDebugName{std::move(friendly_name),
|
new ZipAssetsProvider(handle, PathOrDebugName{std::move(friendly_name),
|
||||||
false /* is_path */}, sb.st_mtime));
|
false /* is_path */}, flags, sb.st_mtime));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
|
std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
|
||||||
@@ -161,10 +164,11 @@ std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
|
|||||||
|
|
||||||
const int fd = GetFileDescriptor(zip_handle_.get());
|
const int fd = GetFileDescriptor(zip_handle_.get());
|
||||||
const off64_t fd_offset = GetFileDescriptorOffset(zip_handle_.get());
|
const off64_t fd_offset = GetFileDescriptorOffset(zip_handle_.get());
|
||||||
|
const bool incremental_hardening = (flags_ & PROPERTY_DISABLE_INCREMENTAL_HARDENING) == 0U;
|
||||||
incfs::IncFsFileMap asset_map;
|
incfs::IncFsFileMap asset_map;
|
||||||
if (entry.method == kCompressDeflated) {
|
if (entry.method == kCompressDeflated) {
|
||||||
if (!asset_map.Create(fd, entry.offset + fd_offset, entry.compressed_length,
|
if (!asset_map.Create(fd, entry.offset + fd_offset, entry.compressed_length,
|
||||||
name_.GetDebugName().c_str())) {
|
name_.GetDebugName().c_str(), incremental_hardening)) {
|
||||||
LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName()
|
LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName()
|
||||||
<< "'";
|
<< "'";
|
||||||
return {};
|
return {};
|
||||||
@@ -181,7 +185,7 @@ std::unique_ptr<Asset> ZipAssetsProvider::OpenInternal(const std::string& path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!asset_map.Create(fd, entry.offset + fd_offset, entry.uncompressed_length,
|
if (!asset_map.Create(fd, entry.offset + fd_offset, entry.uncompressed_length,
|
||||||
name_.GetDebugName().c_str())) {
|
name_.GetDebugName().c_str(), incremental_hardening)) {
|
||||||
LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName() << "'";
|
LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << name_.GetDebugName() << "'";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
"presubmit": [
|
"presubmit": [
|
||||||
{
|
{
|
||||||
"name": "CtsResourcesLoaderTests"
|
"name": "CtsResourcesLoaderTests"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ResourcesHardeningTest"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -80,9 +80,12 @@ struct AssetsProvider {
|
|||||||
|
|
||||||
// Supplies assets from a zip archive.
|
// Supplies assets from a zip archive.
|
||||||
struct ZipAssetsProvider : public AssetsProvider {
|
struct ZipAssetsProvider : public AssetsProvider {
|
||||||
static std::unique_ptr<ZipAssetsProvider> Create(std::string path);
|
static std::unique_ptr<ZipAssetsProvider> Create(std::string path,
|
||||||
|
package_property_t flags);
|
||||||
|
|
||||||
static std::unique_ptr<ZipAssetsProvider> Create(base::unique_fd fd,
|
static std::unique_ptr<ZipAssetsProvider> Create(base::unique_fd fd,
|
||||||
std::string friendly_name,
|
std::string friendly_name,
|
||||||
|
package_property_t flags,
|
||||||
off64_t offset = 0,
|
off64_t offset = 0,
|
||||||
off64_t len = kUnknownLength);
|
off64_t len = kUnknownLength);
|
||||||
|
|
||||||
@@ -101,7 +104,8 @@ struct ZipAssetsProvider : public AssetsProvider {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct PathOrDebugName;
|
struct PathOrDebugName;
|
||||||
ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, time_t last_mod_time);
|
ZipAssetsProvider(ZipArchive* handle, PathOrDebugName&& path, package_property_t flags,
|
||||||
|
time_t last_mod_time);
|
||||||
|
|
||||||
struct PathOrDebugName {
|
struct PathOrDebugName {
|
||||||
PathOrDebugName(std::string&& value, bool is_path);
|
PathOrDebugName(std::string&& value, bool is_path);
|
||||||
@@ -119,6 +123,7 @@ struct ZipAssetsProvider : public AssetsProvider {
|
|||||||
|
|
||||||
std::unique_ptr<ZipArchive, void (*)(ZipArchive*)> zip_handle_;
|
std::unique_ptr<ZipArchive, void (*)(ZipArchive*)> zip_handle_;
|
||||||
PathOrDebugName name_;
|
PathOrDebugName name_;
|
||||||
|
package_property_t flags_;
|
||||||
time_t last_mod_time_;
|
time_t last_mod_time_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ enum : package_property_t {
|
|||||||
|
|
||||||
// The package is a RRO.
|
// The package is a RRO.
|
||||||
PROPERTY_OVERLAY = 1U << 3U,
|
PROPERTY_OVERLAY = 1U << 3U,
|
||||||
|
|
||||||
|
// The apk assets is owned by the application running in this process and incremental crash
|
||||||
|
// protections for this APK must be disabled.
|
||||||
|
PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1U << 4U,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OverlayableInfo {
|
struct OverlayableInfo {
|
||||||
|
|||||||
Reference in New Issue
Block a user