diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index e56b6e0a33b89..779790c09dc82 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 */ @@ -657,59 +724,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 ab19fd6e8ca1b..b7789c0c28572 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;