Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9eee3f95 authored by Peiyong Lin's avatar Peiyong Lin
Browse files

[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
parent bef3d76b
Loading
Loading
Loading
Loading
+68 −50
Original line number Original line Diff line number Diff line
@@ -72,6 +72,14 @@ public class GraphicsEnvironment {
    private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message";
    private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message";
    private static final String GAME_DRIVER_WHITELIST_ALL = "*";
    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 ClassLoader mClassLoader;
    private String mLayerPath;
    private String mLayerPath;
    private String mDebugLayerPath;
    private String mDebugLayerPath;
@@ -96,6 +104,65 @@ public class GraphicsEnvironment {
        Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
        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<String> 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
     * Check whether application is debuggable
     */
     */
@@ -652,58 +719,9 @@ public class GraphicsEnvironment {
            return false;
            return false;
        }
        }


        // To minimize risk of driver updates crippling the device beyond user repair, never use an
        if (!shouldUseGameDriver(context, coreSettings, context.getApplicationInfo())) {
        // 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");
            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<String> 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;
            return false;
        }
        }
        }


        final String abi = chooseAbi(driverAppInfo);
        final String abi = chooseAbi(driverAppInfo);
        if (abi == null) {
        if (abi == null) {
+7 −4
Original line number Original line Diff line number Diff line
@@ -513,6 +513,7 @@ public class Process {
     * @param packageName null-ok the name of the package this process belongs to.
     * @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 packagesForUid null-ok all the packages with the same uid as this process.
     * @param zygoteArgs Additional arguments to supply to the zygote 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.
     * @return An object that describes the result of the attempt to start the process.
     * @throws RuntimeException on fatal start failure
     * @throws RuntimeException on fatal start failure
@@ -532,12 +533,13 @@ public class Process {
                                  @Nullable String packageName,
                                  @Nullable String packageName,
                                  @Nullable String[] packagesForUid,
                                  @Nullable String[] packagesForUid,
                                  @Nullable String sandboxId,
                                  @Nullable String sandboxId,
                                  @Nullable String[] zygoteArgs) {
                                  @Nullable String[] zygoteArgs,
                                  boolean useSystemGraphicsDriver) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    packagesForUid, sandboxId, /*useUnspecializedAppProcessPool=*/ true,
                    packagesForUid, sandboxId, /*useUnspecializedAppProcessPool=*/ true,
                    zygoteArgs);
                    zygoteArgs, useSystemGraphicsDriver);
    }
    }


    /** @hide */
    /** @hide */
@@ -554,12 +556,13 @@ public class Process {
                                  @Nullable String packageName,
                                  @Nullable String packageName,
                                  @Nullable String[] packagesForUid,
                                  @Nullable String[] packagesForUid,
                                  @Nullable String sandboxId,
                                  @Nullable String sandboxId,
                                  @Nullable String[] zygoteArgs) {
                                  @Nullable String[] zygoteArgs,
                                  boolean useSystemGraphicsDriver) {
        return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
        return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    packagesForUid, sandboxId, /*useUnspecializedAppProcessPool=*/ false,
                    packagesForUid, sandboxId, /*useUnspecializedAppProcessPool=*/ false,
                    zygoteArgs);
                    zygoteArgs, useSystemGraphicsDriver);
    }
    }


    /**
    /**
+3 −1
Original line number Original line Diff line number Diff line
@@ -308,6 +308,7 @@ public class ZygoteProcess {
     * @param packageName null-ok the name of the package this process belongs to.
     * @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 packagesForUid null-ok all the packages with the same uid as this process.
     * @param zygoteArgs Additional arguments to supply to the zygote 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.
     * @return An object that describes the result of the attempt to start the process.
     * @throws RuntimeException on fatal start failure
     * @throws RuntimeException on fatal start failure
@@ -326,7 +327,8 @@ public class ZygoteProcess {
                                                  @Nullable String[] packagesForUid,
                                                  @Nullable String[] packagesForUid,
                                                  @Nullable String sandboxId,
                                                  @Nullable String sandboxId,
                                                  boolean useUsapPool,
                                                  boolean useUsapPool,
                                                  @Nullable String[] zygoteArgs) {
                                                  @Nullable String[] zygoteArgs,
                                                  boolean useSystemGraphicsDriver) {
        // TODO (chriswailes): Is there a better place to check this value?
        // TODO (chriswailes): Is there a better place to check this value?
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
            informZygotesOfUsapPoolStatus();
            informZygotesOfUsapPoolStatus();
+16 −3
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ import android.os.AppZygote;
import android.os.Binder;
import android.os.Binder;
import android.os.Build;
import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.GraphicsEnvironment;
import android.os.Handler;
import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Looper;
import android.os.Looper;
@@ -703,6 +704,13 @@ public final class ProcessList {
        return prefix + "+" + Integer.toString(diff);
        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) {
    public static String makeOomAdjString(int setAdj, boolean compact) {
        if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
        if (setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
            return buildOomTag("cch", "cch", "   ", setAdj,
            return buildOomTag("cch", "cch", "   ", setAdj,
@@ -1783,6 +1791,8 @@ public final class ProcessList {
            final StorageManagerInternal storageManagerInternal =
            final StorageManagerInternal storageManagerInternal =
                    LocalServices.getService(StorageManagerInternal.class);
                    LocalServices.getService(StorageManagerInternal.class);
            final String sandboxId = storageManagerInternal.getSandboxId(app.info.packageName);
            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: " +
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
                    app.processName);
            checkSlow(startTime, "startProcess: asking zygote to start proc");
            checkSlow(startTime, "startProcess: asking zygote to start proc");
@@ -1793,7 +1803,8 @@ public final class ProcessList {
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        app.info.dataDir, null, app.info.packageName,
                        packageNames, sandboxId,
                        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")) {
            } else if (hostingType.equals("app_zygote")) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);


@@ -1802,14 +1813,16 @@ public final class ProcessList {
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        app.info.dataDir, null, app.info.packageName,
                        packageNames, sandboxId, /*useUnspecializedAppProcessPool=*/ false,
                        packageNames, sandboxId, /*useUnspecializedAppProcessPool=*/ false,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq},
                        useSystemGraphicsDriver);
            } else {
            } else {
                startResult = Process.start(entryPoint,
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, app.info.packageName,
                        app.info.dataDir, invokeWith, app.info.packageName,
                        packageNames, sandboxId,
                        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!");
            checkSlow(startTime, "startProcess: returned from zygote!");
            return startResult;
            return startResult;