From 9eee3f956e0943feae9fde0f2b3656e31b628f16 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 9 Apr 2019 17:16:20 -0700 Subject: [PATCH] [GraphicsEnvironment] Expose API to query whether an app should use game driver. Game Driver and ANGLE require to disable graphics driver preloading, which results in app launch time regression. Given that in early stage, only a few applications will use them, we would like to make sure Zygote prefork comes with a preloaded graphics driver, such that applications that don't go through ANGLE or Game Driver can directly use Zygote prefork without having to load the driver. BUG: 130029351 Test: Verify with testing applications. Change-Id: I8097f0f7a908be9967b08afb01dc0ce5ff7b3413 --- core/java/android/os/GraphicsEnvironment.java | 118 ++++++++++-------- core/java/android/os/Process.java | 11 +- core/java/android/os/ZygoteProcess.java | 4 +- .../com/android/server/am/ProcessList.java | 19 ++- 4 files changed, 94 insertions(+), 58 deletions(-) diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index 53503f47ca74a..06720f98d9875 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -72,6 +72,14 @@ public class GraphicsEnvironment { private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message"; private static final String GAME_DRIVER_WHITELIST_ALL = "*"; + // GAME_DRIVER_ALL_APPS + // 0: Default (Invalid values fallback to default as well) + // 1: All apps use Game Driver + // 2: All apps use system graphics driver + private static final int GAME_DRIVER_GLOBAL_OPT_IN_DEFAULT = 0; + private static final int GAME_DRIVER_GLOBAL_OPT_IN_ALL = 1; + private static final int GAME_DRIVER_GLOBAL_OPT_IN_NONE = 2; + private ClassLoader mClassLoader; private String mLayerPath; private String mDebugLayerPath; @@ -96,6 +104,65 @@ public class GraphicsEnvironment { Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS); } + /** + * Allow to query whether an application will use Game Driver. + */ + public static boolean shouldUseGameDriver(Context context, Bundle coreSettings, + ApplicationInfo applicationInfo) { + final String driverPackageName = SystemProperties.get(PROPERTY_GFX_DRIVER); + if (driverPackageName == null || driverPackageName.isEmpty()) { + return false; + } + + // To minimize risk of driver updates crippling the device beyond user repair, never use an + // updated driver for privileged or non-updated system apps. Presumably pre-installed apps + // were tested thoroughly with the pre-installed driver. + if (applicationInfo.isPrivilegedApp() || (applicationInfo.isSystemApp() + && !applicationInfo.isUpdatedSystemApp())) { + if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app"); + return false; + } + final ContentResolver contentResolver = context.getContentResolver(); + final String packageName = applicationInfo.packageName; + final int globalOptIn; + if (coreSettings != null) { + globalOptIn = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); + } else { + globalOptIn = Settings.Global.getInt(contentResolver, + Settings.Global.GAME_DRIVER_ALL_APPS, 0); + } + if (globalOptIn == GAME_DRIVER_GLOBAL_OPT_IN_ALL) { + return true; + } + if (globalOptIn == GAME_DRIVER_GLOBAL_OPT_IN_NONE) { + return false; + } + + // GAME_DRIVER_OPT_OUT_APPS has higher priority than GAME_DRIVER_OPT_IN_APPS + if (getGlobalSettingsString(contentResolver, coreSettings, + Settings.Global.GAME_DRIVER_OPT_OUT_APPS).contains(packageName)) { + return false; + } + final boolean isOptIn = getGlobalSettingsString(contentResolver, coreSettings, + Settings.Global.GAME_DRIVER_OPT_IN_APPS).contains(packageName); + final List whitelist = getGlobalSettingsString(contentResolver, coreSettings, + Settings.Global.GAME_DRIVER_WHITELIST); + if (!isOptIn && whitelist.indexOf(GAME_DRIVER_WHITELIST_ALL) != 0 + && !whitelist.contains(packageName)) { + return false; + } + + // If the application is not opted-in, then check whether it's on the blacklist, + // terminate early if it's on the blacklist and fallback to system driver. + if (!isOptIn + && getGlobalSettingsString(contentResolver, coreSettings, + Settings.Global.GAME_DRIVER_BLACKLIST) + .contains(packageName)) { + return false; + } + return true; + } + /** * Check whether application is debuggable */ @@ -652,59 +719,10 @@ public class GraphicsEnvironment { return false; } - // To minimize risk of driver updates crippling the device beyond user repair, never use an - // updated driver for privileged or non-updated system apps. Presumably pre-installed apps - // were tested thoroughly with the pre-installed driver. - final ApplicationInfo ai = context.getApplicationInfo(); - if (ai.isPrivilegedApp() || (ai.isSystemApp() && !ai.isUpdatedSystemApp())) { - if (DEBUG) Log.v(TAG, "ignoring driver package for privileged/non-updated system app"); + if (!shouldUseGameDriver(context, coreSettings, context.getApplicationInfo())) { return false; } - // GAME_DRIVER_ALL_APPS - // 0: Default (Invalid values fallback to default as well) - // 1: All apps use Game Driver - // 2: All apps use system graphics driver - final int gameDriverAllApps = coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0); - if (gameDriverAllApps == 2) { - if (DEBUG) { - Log.w(TAG, "Game Driver is turned off on this device"); - } - return false; - } - - if (gameDriverAllApps != 1) { - // GAME_DRIVER_OPT_OUT_APPS has higher priority than GAME_DRIVER_OPT_IN_APPS - if (getGlobalSettingsString(null, coreSettings, - Settings.Global.GAME_DRIVER_OPT_OUT_APPS).contains(packageName)) { - if (DEBUG) { - Log.w(TAG, packageName + " opts out from Game Driver."); - } - return false; - } - final boolean isOptIn = - getGlobalSettingsString(null, coreSettings, - Settings.Global.GAME_DRIVER_OPT_IN_APPS).contains(packageName); - final List whitelist = getGlobalSettingsString(null, coreSettings, - Settings.Global.GAME_DRIVER_WHITELIST); - if (!isOptIn && whitelist.indexOf(GAME_DRIVER_WHITELIST_ALL) != 0 - && !whitelist.contains(packageName)) { - if (DEBUG) { - Log.w(TAG, packageName + " is not on the whitelist."); - } - return false; - } - - // If the application is not opted-in and check whether it's on the blacklist, - // terminate early if it's on the blacklist and fallback to system driver. - if (!isOptIn - && getGlobalSettingsString(null, coreSettings, - Settings.Global.GAME_DRIVER_BLACKLIST) - .contains(ai.packageName)) { - return false; - } - } - final String abi = chooseAbi(driverAppInfo); if (abi == null) { if (DEBUG) { diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index a7ac7a1fd6892..fb35db11027ba 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -513,6 +513,7 @@ public class Process { * @param packageName null-ok the name of the package this process belongs to. * @param packagesForUid null-ok all the packages with the same uid as this process. * @param zygoteArgs Additional arguments to supply to the zygote process. + * @param useSystemGraphicsDriver whether the process uses system graphics driver. * * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure @@ -532,12 +533,13 @@ public class Process { @Nullable String packageName, @Nullable String[] packagesForUid, @Nullable String sandboxId, - @Nullable String[] zygoteArgs) { + @Nullable String[] zygoteArgs, + boolean useSystemGraphicsDriver) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, packagesForUid, sandboxId, /*useUnspecializedAppProcessPool=*/ true, - zygoteArgs); + zygoteArgs, useSystemGraphicsDriver); } /** @hide */ @@ -554,12 +556,13 @@ public class Process { @Nullable String packageName, @Nullable String[] packagesForUid, @Nullable String sandboxId, - @Nullable String[] zygoteArgs) { + @Nullable String[] zygoteArgs, + boolean useSystemGraphicsDriver) { return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, packagesForUid, sandboxId, /*useUnspecializedAppProcessPool=*/ false, - zygoteArgs); + zygoteArgs, useSystemGraphicsDriver); } /** diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index bd70f23c8b5d1..7ad996e449c7c 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -308,6 +308,7 @@ public class ZygoteProcess { * @param packageName null-ok the name of the package this process belongs to. * @param packagesForUid null-ok all the packages with the same uid as this process. * @param zygoteArgs Additional arguments to supply to the zygote process. + * @param useSystemGraphicsDriver whether the process uses system graphics driver. * * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure @@ -326,7 +327,8 @@ public class ZygoteProcess { @Nullable String[] packagesForUid, @Nullable String sandboxId, boolean useUsapPool, - @Nullable String[] zygoteArgs) { + @Nullable String[] zygoteArgs, + boolean useSystemGraphicsDriver) { // TODO (chriswailes): Is there a better place to check this value? if (fetchUsapPoolEnabledPropWithMinInterval()) { informZygotesOfUsapPoolStatus(); diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index f1f40d49ccd17..9780a7f71970b 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -62,6 +62,7 @@ import android.os.AppZygote; import android.os.Binder; import android.os.Build; import android.os.Bundle; +import android.os.GraphicsEnvironment; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -703,6 +704,13 @@ public final class ProcessList { return prefix + "+" + Integer.toString(diff); } + private static boolean shouldUseSystemGraphicsDriver(Context context, Bundle coreSettings, + ApplicationInfo applicationInfo) { + final boolean shouldUseGameDriver = + GraphicsEnvironment.shouldUseGameDriver(context, coreSettings, applicationInfo); + return !shouldUseGameDriver; + } + public static String makeOomAdjString(int setAdj, boolean compact) { if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) { return buildOomTag("cch", "cch", " ", setAdj, @@ -1783,6 +1791,8 @@ public final class ProcessList { final StorageManagerInternal storageManagerInternal = LocalServices.getService(StorageManagerInternal.class); final String sandboxId = storageManagerInternal.getSandboxId(app.info.packageName); + final boolean useSystemGraphicsDriver = shouldUseSystemGraphicsDriver(mService.mContext, + mService.mCoreSettingsObserver.getCoreSettingsLocked(), app.info); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkSlow(startTime, "startProcess: asking zygote to start proc"); @@ -1793,7 +1803,8 @@ public final class ProcessList { app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, packageNames, sandboxId, - new String[] {PROC_START_SEQ_IDENT + app.startSeq}); + new String[] {PROC_START_SEQ_IDENT + app.startSeq}, + useSystemGraphicsDriver); } else if (hostingType.equals("app_zygote")) { final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app); @@ -1802,14 +1813,16 @@ public final class ProcessList { app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, packageNames, sandboxId, /*useUnspecializedAppProcessPool=*/ false, - new String[] {PROC_START_SEQ_IDENT + app.startSeq}); + new String[] {PROC_START_SEQ_IDENT + app.startSeq}, + useSystemGraphicsDriver); } else { startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, app.info.packageName, packageNames, sandboxId, - new String[] {PROC_START_SEQ_IDENT + app.startSeq}); + new String[] {PROC_START_SEQ_IDENT + app.startSeq}, + useSystemGraphicsDriver); } checkSlow(startTime, "startProcess: returned from zygote!"); return startResult;