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

Commit 7adb2bc3 authored by Xiang Wang's avatar Xiang Wang Committed by Android (Google) Code Review
Browse files

Merge changes I4adae903,I17f973dd

* changes:
  Update `set` and add `list-modes` adb shell game commands
  Persist custom game mode configuration in settings
parents 74be42a2 98ca4c80
Loading
Loading
Loading
Loading
+50 −7
Original line number Diff line number Diff line
@@ -118,6 +118,14 @@ import java.util.Set;
 */
public final class GameManagerService extends IGameManagerService.Stub {
    public static final String TAG = "GameManagerService";
    // event strings used for logging
    private static final String EVENT_SET_GAME_MODE = "SET_GAME_MODE";
    private static final String EVENT_UPDATE_CUSTOM_GAME_MODE_CONFIG =
            "UPDATE_CUSTOM_GAME_MODE_CONFIG";
    private static final String EVENT_RECEIVE_SHUTDOWN_INDENT = "RECEIVE_SHUTDOWN_INDENT";
    private static final String EVENT_ON_USER_STARTING = "ON_USER_STARTING";
    private static final String EVENT_ON_USER_SWITCHING = "ON_USER_SWITCHING";
    private static final String EVENT_ON_USER_STOPPING = "ON_USER_STOPPING";

    private static final boolean DEBUG = false;

@@ -1154,9 +1162,9 @@ public final class GameManagerService extends IGameManagerService.Stub {
                }
            }
        }
        sendUserMessage(userId, WRITE_SETTINGS, "SET_GAME_MODE", WRITE_DELAY_MILLIS);
        sendUserMessage(userId, WRITE_SETTINGS, EVENT_SET_GAME_MODE, WRITE_DELAY_MILLIS);
        sendUserMessage(userId, WRITE_GAME_MODE_INTERVENTION_LIST_FILE,
                "SET_GAME_MODE", 0 /*delayMillis*/);
                EVENT_SET_GAME_MODE, 0 /*delayMillis*/);
        int gameUid = -1;
        try {
            gameUid = mPackageManager.getPackageUidAsUser(packageName, userId);
@@ -1399,6 +1407,11 @@ public final class GameManagerService extends IGameManagerService.Stub {
        Slog.i(TAG, "Updated custom game mode config for package: " + packageName
                + " with FPS=" + internalConfig.getFps() + ";Scaling="
                + internalConfig.getScaling() + " under user " + userId);

        sendUserMessage(userId, WRITE_SETTINGS, EVENT_UPDATE_CUSTOM_GAME_MODE_CONFIG,
                WRITE_DELAY_MILLIS);
        sendUserMessage(userId, WRITE_GAME_MODE_INTERVENTION_LIST_FILE,
                EVENT_UPDATE_CUSTOM_GAME_MODE_CONFIG, WRITE_DELAY_MILLIS /*delayMillis*/);
    }

    /**
@@ -1473,9 +1486,10 @@ public final class GameManagerService extends IGameManagerService.Stub {
                        for (Map.Entry<Integer, GameManagerSettings> entry : mSettings.entrySet()) {
                            final int userId = entry.getKey();
                            sendUserMessage(userId, WRITE_SETTINGS,
                                    Intent.ACTION_SHUTDOWN, 0 /*delayMillis*/);
                                    EVENT_RECEIVE_SHUTDOWN_INDENT, 0 /*delayMillis*/);
                            sendUserMessage(userId,
                                    WRITE_GAME_MODE_INTERVENTION_LIST_FILE, Intent.ACTION_SHUTDOWN,
                                    WRITE_GAME_MODE_INTERVENTION_LIST_FILE,
                                    EVENT_RECEIVE_SHUTDOWN_INDENT,
                                    0 /*delayMillis*/);
                        }
                    }
@@ -1500,7 +1514,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
                userSettings.readPersistentDataLocked();
            }
        }
        sendUserMessage(userId, POPULATE_GAME_MODE_SETTINGS, "ON_USER_STARTING", 0 /*delayMillis*/);
        sendUserMessage(userId, POPULATE_GAME_MODE_SETTINGS, EVENT_ON_USER_STARTING,
                0 /*delayMillis*/);

        if (mGameServiceController != null) {
            mGameServiceController.notifyUserStarted(user);
@@ -1520,7 +1535,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
            if (!mSettings.containsKey(userId)) {
                return;
            }
            sendUserMessage(userId, REMOVE_SETTINGS, "ON_USER_STOPPING", 0 /*delayMillis*/);
            sendUserMessage(userId, REMOVE_SETTINGS, EVENT_ON_USER_STOPPING, 0 /*delayMillis*/);
        }

        if (mGameServiceController != null) {
@@ -1533,7 +1548,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
        // we want to re-populate the setting when switching user as the device config may have
        // changed, which will only update for the previous user, see
        // DeviceConfigListener#onPropertiesChanged.
        sendUserMessage(toUserId, POPULATE_GAME_MODE_SETTINGS, "ON_USER_SWITCHING",
        sendUserMessage(toUserId, POPULATE_GAME_MODE_SETTINGS, EVENT_ON_USER_SWITCHING,
                0 /*delayMillis*/);

        if (mGameServiceController != null) {
@@ -1617,6 +1632,34 @@ public final class GameManagerService extends IGameManagerService.Stub {
    public void setGameModeConfigOverride(String packageName, @UserIdInt int userId,
            @GameMode int gameMode, String fpsStr, String scaling) throws SecurityException {
        checkPermission(Manifest.permission.MANAGE_GAME_MODE);
        int gameUid = -1;
        try {
            gameUid = mPackageManager.getPackageUidAsUser(packageName, userId);
        } catch (NameNotFoundException ex) {
            Slog.d(TAG, "Cannot find the UID for package " + packageName + " under user " + userId);
        }
        GamePackageConfiguration pkgConfig = getConfig(packageName, userId);
        if (pkgConfig != null && pkgConfig.getGameModeConfiguration(gameMode) != null) {
            final GamePackageConfiguration.GameModeConfiguration currentModeConfig =
                    pkgConfig.getGameModeConfiguration(gameMode);
            FrameworkStatsLog.write(FrameworkStatsLog.GAME_MODE_CONFIGURATION_CHANGED, gameUid,
                    Binder.getCallingUid(), gameModeToStatsdGameMode(gameMode),
                    currentModeConfig.getScaling() /* fromScaling */,
                    scaling == null ? currentModeConfig.getScaling()
                            : Float.parseFloat(scaling) /* toScaling */,
                    currentModeConfig.getFps() /* fromFps */,
                    fpsStr == null ? currentModeConfig.getFps()
                            : Integer.parseInt(fpsStr)) /* toFps */;
        } else {
            FrameworkStatsLog.write(FrameworkStatsLog.GAME_MODE_CONFIGURATION_CHANGED, gameUid,
                    Binder.getCallingUid(), gameModeToStatsdGameMode(gameMode),
                    GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING /* fromScaling*/,
                    scaling == null ? GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING
                            : Float.parseFloat(scaling) /* toScaling */,
                    0 /* fromFps */,
                    fpsStr == null ? 0 : Integer.parseInt(fpsStr) /* toFps */);
        }

        // Adding game mode config override of the given package name
        GamePackageConfiguration configOverride;
        synchronized (mLock) {
+17 −13
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.app;
import android.app.GameManager;
import android.os.FileUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
@@ -37,7 +38,6 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;

/**
 * Persists all GameService related settings.
@@ -49,7 +49,11 @@ public class GameManagerSettings {
    // The XML file follows the below format:
    // <?xml>
    // <packages>
    //     <package></package>
    //     <package name="" gameMode="">
    //       <gameModeConfig gameMode="" fps="" scaling="" useAngle="" loadingBoost="">
    //       </gameModeConfig>
    //       ...
    //     </package>
    //     ...
    // </packages>
    private static final String GAME_SERVICE_FILE_NAME = "game-manager-service.xml";
@@ -155,11 +159,14 @@ public class GameManagerSettings {
            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);

            serializer.startTag(null, TAG_PACKAGES);
            for (Map.Entry<String, Integer> entry : mGameModes.entrySet()) {
                String packageName = entry.getKey();
            final ArraySet<String> packageNames = new ArraySet<>(mGameModes.keySet());
            packageNames.addAll(mConfigOverrides.keySet());
            for (String packageName : packageNames) {
                serializer.startTag(null, TAG_PACKAGE);
                serializer.attribute(null, ATTR_NAME, packageName);
                serializer.attributeInt(null, ATTR_GAME_MODE, entry.getValue());
                if (mGameModes.containsKey(packageName)) {
                    serializer.attributeInt(null, ATTR_GAME_MODE, mGameModes.get(packageName));
                }
                writeGameModeConfigTags(serializer, mConfigOverrides.get(packageName));
                serializer.endTag(null, TAG_PACKAGE);
            }
@@ -224,7 +231,7 @@ public class GameManagerSettings {
                // Do nothing
            }
            if (type != XmlPullParser.START_TAG) {
                Slog.wtf(TAG, "No start tag found in package manager settings");
                Slog.wtf(TAG, "No start tag found in game manager settings");
                return false;
            }

@@ -245,7 +252,7 @@ public class GameManagerSettings {
                }
            }
        } catch (XmlPullParserException | java.io.IOException e) {
            Slog.wtf(TAG, "Error reading package manager settings", e);
            Slog.wtf(TAG, "Error reading game manager settings", e);
            return false;
        }
        return true;
@@ -260,15 +267,12 @@ public class GameManagerSettings {
            XmlUtils.skipCurrentTag(parser);
            return;
        }
        int gameMode;
        try {
            gameMode = parser.getAttributeInt(null, ATTR_GAME_MODE);
            final int gameMode = parser.getAttributeInt(null, ATTR_GAME_MODE);
            mGameModes.put(name, gameMode);
        } catch (XmlPullParserException e) {
            Slog.wtf(TAG, "Invalid game mode in package tag: "
                    + parser.getAttributeValue(null, ATTR_GAME_MODE), e);
            return;
            Slog.v(TAG, "No game mode selected by user for package" + name);
        }
        mGameModes.put(name, gameMode);
        final int packageTagDepth = parser.getDepth();
        int type;
        final GamePackageConfiguration config = new GamePackageConfiguration(name);
+109 −75
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.ShellCommand;

import java.io.PrintWriter;
import java.util.Locale;
import java.util.StringJoiner;

/**
 * ShellCommands for GameManagerService.
@@ -34,8 +35,20 @@ import java.util.Locale;
 * Use with {@code adb shell cmd game ...}.
 */
public class GameManagerShellCommand extends ShellCommand {
    private static final String STANDARD_MODE_STR = "standard";
    private static final String STANDARD_MODE_NUM = "1";
    private static final String PERFORMANCE_MODE_STR = "performance";
    private static final String PERFORMANCE_MODE_NUM = "2";
    private static final String BATTERY_MODE_STR = "battery";
    private static final String BATTERY_MODE_NUM = "3";
    private static final String CUSTOM_MODE_STR = "custom";
    private static final String CUSTOM_MODE_NUM = "4";
    private static final String UNSUPPORTED_MODE_STR = "unsupported";
    private static final String UNSUPPORTED_MODE_NUM = String.valueOf(
            GameManager.GAME_MODE_UNSUPPORTED);

    public GameManagerShellCommand() {}
    public GameManagerShellCommand() {
    }

    @Override
    public int onCommand(String cmd) {
@@ -46,10 +59,10 @@ public class GameManagerShellCommand extends ShellCommand {
        try {
            switch (cmd) {
                case "set": {
                    return runSetGameMode(pw);
                    return runSetGameModeConfig(pw);
                }
                case "reset": {
                    return runResetGameMode(pw);
                    return runResetGameModeConfig(pw);
                }
                case "mode": {
                    /** The "mode" command allows setting a package's current game mode outside of
@@ -61,10 +74,13 @@ public class GameManagerShellCommand extends ShellCommand {
                     *          <PACKAGE_NAME> <CONFIG_STRING>`
                     * see: {@link GameManagerServiceTests#mockDeviceConfigAll()}
                     */
                    return runGameMode(pw);
                    return runSetGameMode(pw);
                }
                case "list-modes": {
                    return runListGameModes(pw);
                }
                case "list": {
                    return runGameList(pw);
                case "list-configs": {
                    return runListGameModeConfigs(pw);
                }
                default:
                    return handleDefaultCommands(cmd);
@@ -75,7 +91,21 @@ public class GameManagerShellCommand extends ShellCommand {
        return -1;
    }

    private int runGameList(PrintWriter pw) throws ServiceNotFoundException, RemoteException {
    private int runListGameModes(PrintWriter pw) throws ServiceNotFoundException, RemoteException {
        final String packageName = getNextArgRequired();
        final GameManagerService gameManagerService = (GameManagerService)
                ServiceManager.getService(Context.GAME_SERVICE);
        final StringJoiner sj = new StringJoiner(",");
        for (int mode : gameManagerService.getAvailableGameModes(packageName,
                ActivityManager.getCurrentUser())) {
            sj.add(gameModeIntToString(mode));
        }
        pw.println(packageName + " has available game modes: [" + sj + "]");
        return 0;
    }

    private int runListGameModeConfigs(PrintWriter pw)
            throws ServiceNotFoundException, RemoteException {
        final String packageName = getNextArgRequired();

        final GameManagerService gameManagerService = (GameManagerService)
@@ -92,7 +122,7 @@ public class GameManagerShellCommand extends ShellCommand {
        return 0;
    }

    private int runGameMode(PrintWriter pw) throws ServiceNotFoundException, RemoteException {
    private int runSetGameMode(PrintWriter pw) throws ServiceNotFoundException, RemoteException {
        final String option = getNextOption();
        String userIdStr = null;
        if (option != null && option.equals("--user")) {
@@ -116,34 +146,46 @@ public class GameManagerShellCommand extends ShellCommand {
            }
        }
        switch (gameMode.toLowerCase()) {
            case "1":
            case "standard":
            case STANDARD_MODE_NUM:
            case STANDARD_MODE_STR:
                // Standard mode can be used to specify loading ANGLE as the default OpenGL ES
                // driver, so it should always be available.
                service.setGameMode(packageName, GameManager.GAME_MODE_STANDARD, userId);
                pw.println("Set game mode to `STANDARD` for user `" + userId + "` in game `"
                        + packageName + "`");
                break;
            case "2":
            case "performance":
            case PERFORMANCE_MODE_NUM:
            case PERFORMANCE_MODE_STR:
                if (perfModeSupported) {
                    service.setGameMode(packageName, GameManager.GAME_MODE_PERFORMANCE,
                            userId);
                    pw.println("Set game mode to `PERFORMANCE` for user `" + userId + "` in game `"
                            + packageName + "`");
                } else {
                    pw.println("Game mode: " + gameMode + " not supported by "
                            + packageName);
                    return -1;
                }
                break;
            case "3":
            case "battery":
            case BATTERY_MODE_NUM:
            case BATTERY_MODE_STR:
                if (batteryModeSupported) {
                    service.setGameMode(packageName, GameManager.GAME_MODE_BATTERY,
                            userId);
                    pw.println("Set game mode to `BATTERY` for user `" + userId + "` in game `"
                            + packageName + "`");
                } else {
                    pw.println("Game mode: " + gameMode + " not supported by "
                            + packageName);
                    return -1;
                }
                break;
            case CUSTOM_MODE_NUM:
            case CUSTOM_MODE_STR:
                service.setGameMode(packageName, GameManager.GAME_MODE_CUSTOM, userId);
                pw.println("Set game mode to `CUSTOM` for user `" + userId + "` in game `"
                        + packageName + "`");
                break;
            default:
                pw.println("Invalid game mode: " + gameMode);
                return -1;
@@ -151,15 +193,9 @@ public class GameManagerShellCommand extends ShellCommand {
        return 0;
    }

    private int runSetGameMode(PrintWriter pw) throws ServiceNotFoundException, RemoteException {
        String option = getNextArgRequired();
        if (!option.equals("--mode")) {
            pw.println("Invalid option '" + option + "'");
            return -1;
        }

        final String gameMode = getNextArgRequired();

    private int runSetGameModeConfig(PrintWriter pw)
            throws ServiceNotFoundException, RemoteException {
        String option;
        /**
         * handling optional input
         * "--user", "--downscale" and "--fps" can come in any order
@@ -167,8 +203,12 @@ public class GameManagerShellCommand extends ShellCommand {
        String userIdStr = null;
        String fpsStr = null;
        String downscaleRatio = null;
        int gameMode = GameManager.GAME_MODE_CUSTOM;
        while ((option = getNextOption()) != null) {
            switch (option) {
                case "--mode":
                    gameMode = Integer.parseInt(getNextArgRequired());
                    break;
                case "--user":
                    if (userIdStr == null) {
                        userIdStr = getNextArgRequired();
@@ -220,50 +260,21 @@ public class GameManagerShellCommand extends ShellCommand {

        final GameManagerService gameManagerService = (GameManagerService)
                ServiceManager.getService(Context.GAME_SERVICE);

        boolean batteryModeSupported = false;
        boolean perfModeSupported = false;
        int [] modes = gameManagerService.getAvailableGameModes(packageName, userId);

        for (int mode : modes) {
            if (mode == GameManager.GAME_MODE_PERFORMANCE) {
                perfModeSupported = true;
            } else if (mode == GameManager.GAME_MODE_BATTERY) {
                batteryModeSupported = true;
            }
        }

        switch (gameMode.toLowerCase(Locale.getDefault())) {
            case "2":
            case "performance":
                if (perfModeSupported) {
                    gameManagerService.setGameModeConfigOverride(packageName, userId,
                            GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
                } else {
                    pw.println("Game mode: " + gameMode + " not supported by "
                            + packageName);
                    return -1;
                }
                break;
            case "3":
            case "battery":
                if (batteryModeSupported) {
                    gameManagerService.setGameModeConfigOverride(packageName, userId,
                            GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
                } else {
                    pw.println("Game mode: " + gameMode + " not supported by "
                            + packageName);
                    return -1;
                }
                break;
            default:
                pw.println("Invalid game mode: " + gameMode);
        if (gameManagerService == null) {
            pw.println("Failed to find GameManagerService on device");
            return -1;
        }
        gameManagerService.setGameModeConfigOverride(packageName, userId, gameMode,
                fpsStr, downscaleRatio);
        pw.println("Set custom mode intervention config for user `" + userId + "` in game `"
                + packageName + "` as: `"
                + "downscaling-ratio: " + downscaleRatio + ";"
                + "fps-override: " + fpsStr + "`");
        return 0;
    }

    private int runResetGameMode(PrintWriter pw) throws ServiceNotFoundException, RemoteException {
    private int runResetGameModeConfig(PrintWriter pw)
            throws ServiceNotFoundException, RemoteException {
        String option = null;
        String gameMode = null;
        String userIdStr = null;
@@ -305,13 +316,13 @@ public class GameManagerShellCommand extends ShellCommand {
        }

        switch (gameMode.toLowerCase(Locale.getDefault())) {
            case "2":
            case "performance":
            case PERFORMANCE_MODE_NUM:
            case PERFORMANCE_MODE_STR:
                gameManagerService.resetGameModeConfigOverride(packageName, userId,
                        GameManager.GAME_MODE_PERFORMANCE);
                break;
            case "3":
            case "battery":
            case BATTERY_MODE_NUM:
            case BATTERY_MODE_STR:
                gameManagerService.resetGameModeConfigOverride(packageName, userId,
                        GameManager.GAME_MODE_BATTERY);
                break;
@@ -322,6 +333,22 @@ public class GameManagerShellCommand extends ShellCommand {
        return 0;
    }

    private static String gameModeIntToString(@GameManager.GameMode int gameMode) {
        switch (gameMode) {
            case GameManager.GAME_MODE_BATTERY:
                return BATTERY_MODE_STR;
            case GameManager.GAME_MODE_PERFORMANCE:
                return PERFORMANCE_MODE_STR;
            case GameManager.GAME_MODE_CUSTOM:
                return CUSTOM_MODE_STR;
            case GameManager.GAME_MODE_STANDARD:
                return STANDARD_MODE_STR;
            case GameManager.GAME_MODE_UNSUPPORTED:
                return UNSUPPORTED_MODE_STR;
        }
        return "";
    }

    @Override
    public void onHelp() {
        PrintWriter pw = getOutPrintWriter();
@@ -329,21 +356,28 @@ public class GameManagerShellCommand extends ShellCommand {
        pw.println("  help");
        pw.println("      Print this help text.");
        pw.println("  downscale");
        pw.println("      Deprecated. Please use `set` command.");
        pw.println("  mode [--user <USER_ID>] [1|2|3|standard|performance|battery] <PACKAGE_NAME>");
        pw.println("      Deprecated. Please use `custom` command.");
        pw.println("  list-configs <PACKAGE_NAME>");
        pw.println("      Lists the current intervention configs of an app.");
        pw.println("  list-modes <PACKAGE_NAME>");
        pw.println("      Lists the current available game modes of an app.");
        pw.println("  mode [--user <USER_ID>] [1|2|3|4|standard|performance|battery|custom] "
                + "<PACKAGE_NAME>");
        pw.println("      Set app to run in the specified game mode, if supported.");
        pw.println("      --user <USER_ID>: apply for the given user,");
        pw.println("                        the current user is used when unspecified.");
        pw.println("  set --mode [2|3|performance|battery] [intervention configs] <PACKAGE_NAME>");
        pw.println("      Set app to run at given game mode with configs, if supported.");
        pw.println("  set [intervention configs] <PACKAGE_NAME>");
        pw.println("      Set app to run at custom mode using provided intervention configs");
        pw.println("      Intervention configs consists of:");
        pw.println("      --downscale [0.3|0.35|0.4|0.45|0.5|0.55|0.6|0.65");
        pw.println("                  |0.7|0.75|0.8|0.85|0.9|disable]");
        pw.println("      Set app to run at the specified scaling ratio.");
        pw.println("      --fps [30|45|60|90|120|disable]");
        pw.println("      Set app to run at the specified fps, if supported.");
        pw.println("                  |0.7|0.75|0.8|0.85|0.9|disable]: Set app to run at the");
        pw.println("                                                   specified scaling ratio.");
        pw.println("      --fps [30|45|60|90|120|disable]: Set app to run at the specified fps,");
        pw.println("                                       if supported.");
        pw.println("  reset [--mode [2|3|performance|battery] --user <USER_ID>] <PACKAGE_NAME>");
        pw.println("      Resets the game mode of the app to device configuration.");
        pw.println("      This should only be used to reset any override to non custom game mode");
        pw.println("      applied using the deprecated `set` command");
        pw.println("      --mode [2|3|performance|battery]: apply for the given mode,");
        pw.println("                                        resets all modes when unspecified.");
        pw.println("      --user <USER_ID>: apply for the given user,");
+46 −6

File changed.

Preview size limit exceeded, changes collapsed.

+57 −13

File changed.

Preview size limit exceeded, changes collapsed.