diff options
| author | 2023-09-05 17:41:55 -0700 | |
|---|---|---|
| committer | 2023-11-01 14:53:31 -0700 | |
| commit | 2cfe9651b5e90e7968e21b2d4b58d54e2b83b7d9 (patch) | |
| tree | 1f46f6625135e9bd4eb6005d44021558a2165db1 | |
| parent | 0be58372bdbd3d30c53c345f5c42dfc95250b585 (diff) | |
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
| -rw-r--r-- | core/java/android/os/Process.java | 7 | ||||
| -rw-r--r-- | core/java/android/os/ZygoteProcess.java | 11 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 25 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteArguments.java | 7 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 3 | ||||
| -rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 147 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ProcessList.java | 16 |
7 files changed, 195 insertions, 21 deletions
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index e37b2b5ef3ef..677143afd4fb 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -730,13 +730,14 @@ public class Process { 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 @@ public class Process { @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 @@ public class Process { 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 3cb5c60259eb..c14810bbcd64 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -355,6 +355,7 @@ public class ZygoteProcess { 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 @@ public class ZygoteProcess { 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 @@ public class ZygoteProcess { allowlistedDataInfoList, boolean bindMountAppsData, boolean bindMountAppStorageDirs, + boolean bindMountOverrideSysprops, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<>(); @@ -753,6 +755,10 @@ public class ZygoteProcess { 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 @@ public class ZygoteProcess { 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 1c5f4f0f1369..cab84bb01f70 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -236,6 +236,9 @@ public final class Zygote { /** 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 @@ public final class Zygote { * @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 @@ public final class Zygote { 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 @@ public final class Zygote { 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 @@ public final class Zygote { * @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 @@ public final class Zygote { 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 @@ public final class Zygote { 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 ef8398294c5b..86b9a59fef72 100644 --- a/core/java/com/android/internal/os/ZygoteArguments.java +++ b/core/java/com/android/internal/os/ZygoteArguments.java @@ -243,6 +243,11 @@ class ZygoteArguments { 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 @@ class ZygoteArguments { 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 5fe086da8c6a..cbe070048811 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -257,7 +257,8 @@ class ZygoteConnection { 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 b12e14782361..9c1bea779201 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 @@ static void WaitUntilDirReady(const std::string& target, fail_fn_t fail_fn) { 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 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, 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 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, 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 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( 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 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess( 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 void com_android_internal_os_Zygote_nativeAllowFilesOpenedByPreload(JNIEn 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 @@ static const JNINativeMethod gMethods[] = { (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 614caffe2f57..0f9c64e9e707 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { 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; |