Have zygote mount appcompat system properties
If needed, the zygote should mount
/dev/__properties__/appcompat_override in place of /dev/__properties__,
and reload system properties (and any constants derived from them)
Bug: 291814949
Test: atest AppcompatOverrideSystemPropertiesDeclarationTest
Change-Id: Ifd364f5d9463e88b2ee928c1f71a6b96b8c29f45
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index e37b2b5..677143a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -730,13 +730,14 @@
whitelistedDataInfoMap,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
+ boolean bindMountSystemOverrides,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
- bindMountAppStorageDirs, zygoteArgs);
+ bindMountAppStorageDirs, bindMountSystemOverrides, zygoteArgs);
}
/** @hide */
@@ -753,6 +754,7 @@
@Nullable String invokeWith,
@Nullable String packageName,
@Nullable long[] disabledCompatChanges,
+ boolean bindMountSyspropOverrides,
@Nullable String[] zygoteArgs) {
// Webview zygote can't access app private data files, so doesn't need to know its data
// info.
@@ -761,7 +763,8 @@
abi, instructionSet, appDataDir, invokeWith, packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
disabledCompatChanges, /* pkgDataInfoMap */ null,
- /* whitelistedDataInfoMap */ null, false, false, zygoteArgs);
+ /* whitelistedDataInfoMap */ null, /* bindMountAppsData */ false,
+ /* bindMountAppStorageDirs */ false, bindMountSyspropOverrides, zygoteArgs);
}
/**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 3cb5c60..c14810b 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -355,6 +355,7 @@
allowlistedDataInfoList,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
+ boolean bindOverrideSysprops,
@Nullable String[] zygoteArgs) {
// TODO (chriswailes): Is there a better place to check this value?
if (fetchUsapPoolEnabledPropWithMinInterval()) {
@@ -367,7 +368,7 @@
abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,
- bindMountAppStorageDirs, zygoteArgs);
+ bindMountAppStorageDirs, bindOverrideSysprops, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
@@ -638,6 +639,7 @@
allowlistedDataInfoList,
boolean bindMountAppsData,
boolean bindMountAppStorageDirs,
+ boolean bindMountOverrideSysprops,
@Nullable String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<>();
@@ -753,6 +755,10 @@
argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
}
+ if (bindMountOverrideSysprops) {
+ argsForZygote.add(Zygote.BIND_MOUNT_SYSPROP_OVERRIDES);
+ }
+
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--disabled-compat-changes=");
@@ -1306,7 +1312,8 @@
ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
null /* allowlistedDataInfoList */, true /* bindMountAppsData*/,
- /* bindMountAppStorageDirs */ false, extraArgs);
+ /* bindMountAppStorageDirs */ false, /*bindMountOverrideSysprops */ false,
+ extraArgs);
} catch (ZygoteStartFailedEx ex) {
throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 1c5f4f0..cab84bb 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -236,6 +236,9 @@
/** Bind mount app storage dirs to lower fs not via fuse */
public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
+ /** Bind the system properties to an alternate set, for appcompat reasons */
+ public static final String BIND_MOUNT_SYSPROP_OVERRIDES = "--bind-mount-sysprop-overrides";
+
/**
* An extraArg passed when a zygote process is forking a child-zygote, specifying a name
* in the abstract socket namespace. This socket name is what the new child zygote
@@ -353,6 +356,8 @@
* @param allowlistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps.
* @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
+ * @param bindMountSyspropOverrides True if the zygote needs to mount the override system
+ * properties
*
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
@@ -361,14 +366,15 @@
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
boolean isTopApp, String[] pkgDataInfoList, String[] allowlistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
+ boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs,
+ boolean bindMountSyspropOverrides) {
ZygoteHooks.preFork();
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, allowlistedDataInfoList, bindMountAppDataDirs,
- bindMountAppStorageDirs);
+ bindMountAppStorageDirs, bindMountSyspropOverrides);
if (pid == 0) {
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -391,7 +397,7 @@
int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
String[] allowlistedDataInfoList, boolean bindMountAppDataDirs,
- boolean bindMountAppStorageDirs);
+ boolean bindMountAppStorageDirs, boolean bindMountSyspropOverrides);
/**
* Specialize an unspecialized app process. The current VM must have been started
@@ -421,16 +427,19 @@
* @param allowlistedDataInfoList Like pkgDataInfoList, but it's for allowlisted apps.
* @param bindMountAppDataDirs True if the zygote needs to mount data dirs.
* @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs.
+ * @param bindMountSyspropOverrides True if the zygote needs to mount the override system
+ * properties
*/
private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
String[] pkgDataInfoList, String[] allowlistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
+ boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs,
+ boolean bindMountSyspropOverrides) {
nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
pkgDataInfoList, allowlistedDataInfoList,
- bindMountAppDataDirs, bindMountAppStorageDirs);
+ bindMountAppDataDirs, bindMountAppStorageDirs, bindMountSyspropOverrides);
// Note that this event ends at the end of handleChildProc.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -455,7 +464,8 @@
int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
String[] pkgDataInfoList, String[] allowlistedDataInfoList,
- boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
+ boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs,
+ boolean bindMountSyspropOverrides);
/**
* Called to do any initialization before starting an application.
@@ -866,7 +876,8 @@
args.mSeInfo, args.mNiceName, args.mStartChildZygote,
args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
args.mPkgDataInfoList, args.mAllowlistedDataInfoList,
- args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
+ args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs,
+ args.mBindMountSyspropOverrides);
// While `specializeAppProcess` sets the thread name on the process's main thread, this
// is distinct from the app process name which appears in stack traces, as the latter is
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index ef83982..86b9a59 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -243,6 +243,11 @@
boolean mBindMountAppDataDirs;
/**
+ * @see Zygote#BIND_MOUNT_SYSPROP_OVERRIDES
+ */
+ boolean mBindMountSyspropOverrides;
+
+ /**
* Constructs instance and parses args
*
* @param args zygote command-line args as ZygoteCommandBuffer, positioned after argument count.
@@ -481,6 +486,8 @@
mBindMountAppStorageDirs = true;
} else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
mBindMountAppDataDirs = true;
+ } else if (arg.equals(Zygote.BIND_MOUNT_SYSPROP_OVERRIDES)) {
+ mBindMountSyspropOverrides = true;
} else {
unprocessedArg = arg;
break;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 5fe086d..cbe0700 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -257,7 +257,8 @@
parsedArgs.mInstructionSet, parsedArgs.mAppDataDir,
parsedArgs.mIsTopApp, parsedArgs.mPkgDataInfoList,
parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
- parsedArgs.mBindMountAppStorageDirs);
+ parsedArgs.mBindMountAppStorageDirs,
+ parsedArgs.mBindMountSyspropOverrides);
try {
if (pid == 0) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index b12e147..9c1bea7 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -59,6 +59,8 @@
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
+#include <sys/_system_properties.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
@@ -1691,6 +1693,131 @@
fail_fn(CREATE_ERROR("Error dir is not ready %s: %s", dir_path, strerror(errno)));
}
+// All public String android.os.Build constants, and the system properties they're pulled from
+std::pair<const char*, const char*> build_constants[] = {
+ std::pair("ID", "ro.build.id"),
+ std::pair("DISPLAY", "ro.build.display.id"),
+ std::pair("PRODUCT", "ro.product.name"),
+ std::pair("DEVICE", "ro.product.device"),
+ std::pair("BOARD", "ro.product.board"),
+ std::pair("MANUFACTURER", "ro.product.manufacturer"),
+ std::pair("BRAND", "ro.product.brand"),
+ std::pair("MODEL", "ro.product.model"),
+ std::pair("BOOTLOADER", "ro.bootloader"),
+ std::pair("HARDWARE", "ro.hardware"),
+ std::pair("SKU", "ro.boot.hardware.sku"),
+ std::pair("ODM_SKU", "ro.boot.product.hardware.sku"),
+ std::pair("TAGS", "ro.build.tags"),
+ std::pair("TYPE", "ro.build.type"),
+ std::pair("USER", "ro.build.user"),
+ std::pair("HOST", "ro.build.host"),
+};
+
+// All public String Build.VERSION constants, and the system properties they're pulled from
+std::pair<const char*, const char*> build_version_constants[] = {
+ std::pair("INCREMENTAL", "ro.build.version.incremental"),
+ std::pair("RELEASE", "ro.build.version.release"),
+ std::pair("RELEASE_OR_CODENAME", "ro.build.version.release_or_codename"),
+ std::pair("RELEASE_OR_PREVIEW_DISPLAY", "ro.build.version.release_or_preview_display"),
+ std::pair("BASE_OS", "ro.build.version.base_os"),
+ std::pair("SECURITY_PATCH", "ro.build.version.security_patch"),
+ std::pair("SDK", "ro.build.version.sdk"),
+ std::pair("PREVIEW_SDK_FINGERPRINT", "ro.build.version.preview_sdk_fingerprint"),
+ std::pair("CODENAME", "ro.build.version.codename"),
+};
+
+static void ReloadBuildJavaConstant(JNIEnv* env, jclass build_class, const char* field_name,
+ const char* field_signature, const char* sysprop_name) {
+ const prop_info* prop_info = __system_property_find(sysprop_name);
+ std::string new_value;
+ __system_property_read_callback(
+ prop_info,
+ [](void* cookie, const char* name, const char* value, unsigned serial) {
+ auto new_value = reinterpret_cast<std::string*>(cookie);
+ *new_value = value;
+ },
+ &new_value);
+ jfieldID fieldId = env->GetStaticFieldID(build_class, field_name, field_signature);
+ if (strcmp(field_signature, "I") == 0) {
+ env->SetStaticIntField(build_class, fieldId, jint(strtol(new_value.c_str(), nullptr, 0)));
+ } else if (strcmp(field_signature, "Ljava/lang/String;") == 0) {
+ jstring string_val = env->NewStringUTF(new_value.c_str());
+ env->SetStaticObjectField(build_class, fieldId, string_val);
+ } else if (strcmp(field_signature, "[Ljava/lang/String;") == 0) {
+ auto stream = std::stringstream(new_value);
+ std::vector<std::string> items;
+ std::string segment;
+ while (std::getline(stream, segment, ',')) {
+ items.push_back(segment);
+ }
+ jclass string_class = env->FindClass("java/lang/String");
+ jobjectArray string_arr = env->NewObjectArray(items.size(), string_class, nullptr);
+ for (size_t i = 0; i < items.size(); i++) {
+ jstring string_arr_val = env->NewStringUTF(items.at(i).c_str());
+ env->SetObjectArrayElement(string_arr, i, string_arr_val);
+ }
+ env->SetStaticObjectField(build_class, fieldId, string_arr);
+ } else if (strcmp(field_signature, "J") == 0) {
+ env->SetStaticLongField(build_class, fieldId, jlong(strtoll(new_value.c_str(), nullptr, 0)));
+ }
+}
+
+static void ReloadBuildJavaConstants(JNIEnv* env) {
+ jclass build_cls = env->FindClass("android/os/Build");
+ size_t arr_size = sizeof(build_constants) / sizeof(build_constants[0]);
+ for (int i = 0; i < arr_size; i++) {
+ const char* field_name = build_constants[i].first;
+ const char* sysprop_name = build_constants[i].second;
+ ReloadBuildJavaConstant(env, build_cls, field_name, "Ljava/lang/String;", sysprop_name);
+ }
+ jclass build_version_cls = env->FindClass("android/os/Build$VERSION");
+ arr_size = sizeof(build_version_constants) / sizeof(build_version_constants[0]);
+ for (int i = 0; i < arr_size; i++) {
+ const char* field_name = build_version_constants[i].first;
+ const char* sysprop_name = build_version_constants[i].second;
+ ReloadBuildJavaConstant(env, build_version_cls, field_name, "Ljava/lang/String;", sysprop_name);
+ }
+
+ // Reload the public String[] constants
+ ReloadBuildJavaConstant(env, build_cls, "SUPPORTED_ABIS", "[Ljava/lang/String;",
+ "ro.product.cpu.abilist");
+ ReloadBuildJavaConstant(env, build_cls, "SUPPORTED_32_BIT_ABIS", "[Ljava/lang/String;",
+ "ro.product.cpu.abilist32");
+ ReloadBuildJavaConstant(env, build_cls, "SUPPORTED_64_BIT_ABIS", "[Ljava/lang/String;",
+ "ro.product.cpu.abilist64");
+ ReloadBuildJavaConstant(env, build_version_cls, "ALL_CODENAMES", "[Ljava/lang/String;",
+ "ro.build.version.all_codenames");
+
+ // Reload the public int/long constants
+ ReloadBuildJavaConstant(env, build_cls, "TIME", "J", "ro.build.date.utc");
+ ReloadBuildJavaConstant(env, build_version_cls, "SDK_INT", "I", "ro.build.version.sdk");
+ ReloadBuildJavaConstant(env, build_version_cls, "PREVIEW_SDK_INT", "I",
+ "ro.build.version.preview_sdk");
+
+ // Re-derive the fingerprint
+ jmethodID derive_fingerprint =
+ env->GetStaticMethodID(build_cls, "deriveFingerprint", "()Ljava/lang/String;");
+ auto new_fingerprint = (jstring)(env->CallStaticObjectMethod(build_cls, derive_fingerprint));
+ jfieldID fieldId = env->GetStaticFieldID(build_cls, "FINGERPRINT", "Ljava/lang/String;");
+ env->SetStaticObjectField(build_cls, fieldId, new_fingerprint);
+}
+
+static void BindMountSyspropOverride(fail_fn_t fail_fn, JNIEnv* env) {
+ std::string source = "/dev/__properties__/appcompat_override";
+ std::string target = "/dev/__properties__";
+ if (access(source.c_str(), F_OK) != 0) {
+ fail_fn(CREATE_ERROR("Error accessing %s: %s", source.c_str(), strerror(errno)));
+ }
+ if (access(target.c_str(), F_OK) != 0) {
+ fail_fn(CREATE_ERROR("Error accessing %s: %s", target.c_str(), strerror(errno)));
+ }
+ BindMount(source, target, fail_fn);
+ // Reload the system properties file, to ensure new values are read into memory
+ __system_properties_zygote_reload();
+ // android.os.Build constants are pulled from system properties, so they must be reloaded, too
+ ReloadBuildJavaConstants(env);
+}
+
static void BindMountStorageToLowerFs(const userid_t user_id, const uid_t uid,
const char* dir_name, const char* package, fail_fn_t fail_fn) {
bool hasSdcardFs = IsSdcardfsUsed();
@@ -1754,7 +1881,7 @@
jstring managed_instruction_set, jstring managed_app_data_dir,
bool is_top_app, jobjectArray pkg_data_info_list,
jobjectArray allowlisted_data_info_list, bool mount_data_dirs,
- bool mount_storage_dirs) {
+ bool mount_storage_dirs, bool mount_sysprop_overrides) {
const char* process_name = is_system_server ? "system_server" : "zygote";
auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1807,6 +1934,10 @@
fail_fn);
}
+ if (mount_sysprop_overrides) {
+ BindMountSyspropOverride(fail_fn, env);
+ }
+
// If this zygote isn't root, it won't be able to create a process group,
// since the directory is owned by root.
if (!is_system_server && getuid() == 0) {
@@ -2360,7 +2491,7 @@
jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
jobjectArray pkg_data_info_list, jobjectArray allowlisted_data_info_list,
- jboolean mount_data_dirs, jboolean mount_storage_dirs) {
+ jboolean mount_data_dirs, jboolean mount_storage_dirs, jboolean mount_sysprop_overrides) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -2403,7 +2534,7 @@
mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
- mount_storage_dirs == JNI_TRUE);
+ mount_storage_dirs == JNI_TRUE, mount_sysprop_overrides == JNI_TRUE);
}
return pid;
}
@@ -2439,7 +2570,7 @@
effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr, /* is_top_app= */ false,
/* pkg_data_info_list */ nullptr,
- /* allowlisted_data_info_list */ nullptr, false, false);
+ /* allowlisted_data_info_list */ nullptr, false, false, false);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
@@ -2591,14 +2722,14 @@
jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir,
jboolean is_top_app, jobjectArray pkg_data_info_list,
jobjectArray allowlisted_data_info_list, jboolean mount_data_dirs,
- jboolean mount_storage_dirs) {
+ jboolean mount_storage_dirs, jboolean mount_sysprop_overrides) {
jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities,
mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE,
instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list,
allowlisted_data_info_list, mount_data_dirs == JNI_TRUE,
- mount_storage_dirs == JNI_TRUE);
+ mount_storage_dirs == JNI_TRUE, mount_sysprop_overrides == JNI_TRUE);
}
/**
@@ -2876,7 +3007,7 @@
static const JNINativeMethod gMethods[] = {
{"nativeForkAndSpecialize",
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
- "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
+ "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZZ)I",
(void*)com_android_internal_os_Zygote_nativeForkAndSpecialize},
{"nativeForkSystemServer", "(II[II[[IJJ)I",
(void*)com_android_internal_os_Zygote_nativeForkSystemServer},
@@ -2892,7 +3023,7 @@
(void*)com_android_internal_os_Zygote_nativeAddUsapTableEntry},
{"nativeSpecializeAppProcess",
"(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
- "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
+ "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZZ)V",
(void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
{"nativeInitNativeState", "(Z)V",
(void*)com_android_internal_os_Zygote_nativeInitNativeState},
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 614caffe..0f9c64e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2414,6 +2414,18 @@
allowlistedAppDataInfoMap = null;
}
+ boolean bindOverrideSysprops = false;
+ String[] syspropOverridePkgNames = DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_APP_COMPAT,
+ "appcompat_sysprop_override_pkgs", "").split(",");
+ String[] pkgs = app.getPackageList();
+ for (int i = 0; i < pkgs.length; i++) {
+ if (ArrayUtils.contains(syspropOverridePkgNames, pkgs[i])) {
+ bindOverrideSysprops = true;
+ break;
+ }
+ }
+
AppStateTracker ast = mService.mServices.mAppStateTracker;
if (ast != null) {
final boolean inBgRestricted = ast.isAppBackgroundRestricted(
@@ -2436,6 +2448,7 @@
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
app.getDisabledCompatChanges(),
+ bindOverrideSysprops,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
@@ -2447,7 +2460,7 @@
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
- false, false,
+ false, false, bindOverrideSysprops,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
} else {
regularZygote = true;
@@ -2457,6 +2470,7 @@
app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
+ bindOverrideSysprops,
new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
// By now the process group should have been created by zygote.
app.mProcessGroupCreated = true;