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

Commit f823057f authored by Xiang Wang's avatar Xiang Wang
Browse files

Add new GameManagerService methods to update and get scaling factor

Change the scaling field type from string to boolean and use default
value -1f instead of "1" or null to indicate that scaling is inactive

Bug: b/240335717
Test: atest GameManagerServiceTests
Change-Id: Ie29ac45d35baa11c5f1ae04b795a8832c51866cd
parent 606cdeba
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -31,4 +31,6 @@ interface IGameManagerService {
    void setGameState(String packageName, in GameState gameState, int userId);
    GameModeInfo getGameModeInfo(String packageName, int userId);
    void setGameServiceProvider(String packageName);
    void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor, int userId);
    float getResolutionScalingFactor(String packageName, int gameMode, int userId);
}
+95 −20
Original line number Diff line number Diff line
@@ -649,6 +649,13 @@ public final class GameManagerService extends IGameManagerService.Stub {
            return xmlFound;
        }

        GameModeConfiguration getOrAddDefaultGameModeConfiguration(int gameMode) {
            synchronized (mModeConfigLock) {
                mModeConfigs.putIfAbsent(gameMode, new GameModeConfiguration(gameMode));
                return mModeConfigs.get(gameMode);
            }
        }

        /**
         * GameModeConfiguration contains all the values for all the interventions associated with
         * a game mode.
@@ -659,17 +666,26 @@ public final class GameManagerService extends IGameManagerService.Stub {
            public static final String MODE_KEY = "mode";
            public static final String SCALING_KEY = "downscaleFactor";
            public static final String FPS_KEY = "fps";
            public static final String DEFAULT_SCALING = "1.0";
            public static final String DEFAULT_FPS = "";
            public static final String ANGLE_KEY = "useAngle";
            public static final String LOADING_BOOST_KEY = "loadingBoost";

            public static final float DEFAULT_SCALING = -1f;
            public static final String DEFAULT_FPS = "";
            public static final boolean DEFAULT_USE_ANGLE = false;
            public static final int DEFAULT_LOADING_BOOST_DURATION = -1;

            private final @GameMode int mGameMode;
            private String mScaling;
            private String mFps;
            private float mScaling = DEFAULT_SCALING;
            private String mFps = DEFAULT_FPS;
            private final boolean mUseAngle;
            private final int mLoadingBoostDuration;

            GameModeConfiguration(int gameMode) {
                mGameMode = gameMode;
                mUseAngle = DEFAULT_USE_ANGLE;
                mLoadingBoostDuration = DEFAULT_LOADING_BOOST_DURATION;
            }

            GameModeConfiguration(KeyValueListParser parser) {
                mGameMode = parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED);
                // isGameModeOptedIn() returns if an app will handle all of the changes necessary
@@ -677,7 +693,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
                // GameManagerService) will not do anything for the app (like window scaling or
                // using ANGLE).
                mScaling = !mAllowDownscale || willGamePerformOptimizations(mGameMode)
                        ? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING);
                        ? DEFAULT_SCALING : parser.getFloat(SCALING_KEY, DEFAULT_SCALING);

                mFps = mAllowFpsOverride && !willGamePerformOptimizations(mGameMode)
                        ? parser.getString(FPS_KEY, DEFAULT_FPS) : DEFAULT_FPS;
@@ -686,17 +702,18 @@ public final class GameManagerService extends IGameManagerService.Stub {
                // - The app has not opted in to performing the work itself AND
                // - The Phenotype config has enabled it.
                mUseAngle = mAllowAngle && !willGamePerformOptimizations(mGameMode)
                        && parser.getBoolean(ANGLE_KEY, false);
                        && parser.getBoolean(ANGLE_KEY, DEFAULT_USE_ANGLE);

                mLoadingBoostDuration = willGamePerformOptimizations(mGameMode) ? -1
                        : parser.getInt(LOADING_BOOST_KEY, -1);
                mLoadingBoostDuration = willGamePerformOptimizations(mGameMode)
                        ? DEFAULT_LOADING_BOOST_DURATION
                        : parser.getInt(LOADING_BOOST_KEY, DEFAULT_LOADING_BOOST_DURATION);
            }

            public int getGameMode() {
                return mGameMode;
            }

            public synchronized String getScaling() {
            public synchronized float getScaling() {
                return mScaling;
            }

@@ -712,7 +729,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
                return mLoadingBoostDuration;
            }

            public synchronized void setScaling(String scaling) {
            public synchronized void setScaling(float scaling) {
                mScaling = scaling;
            }

@@ -740,7 +757,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
             * Get the corresponding compat change id for the current scaling string.
             */
            public long getCompatChangeId() {
                return GameManagerService.getCompatChangeId(mScaling);
                return GameManagerService.getCompatChangeId(String.valueOf(mScaling));
            }
        }

@@ -813,7 +830,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
        }

        /**
         * Insert a new GameModeConfiguration
         * Inserts a new GameModeConfiguration
         */
        public void addModeConfig(GameModeConfiguration config) {
            if (config.isActive()) {
@@ -937,7 +954,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
    private @GameMode int getGameModeFromSettings(String packageName, @UserIdInt int userId) {
        synchronized (mLock) {
            if (!mSettings.containsKey(userId)) {
                Slog.w(TAG, "User ID '" + userId + "' does not have a Game Mode"
                Slog.d(TAG, "User ID '" + userId + "' does not have a Game Mode"
                        + " selected for package: '" + packageName + "'");
                return GameManager.GAME_MODE_UNSUPPORTED;
            }
@@ -1163,6 +1180,66 @@ public final class GameManagerService extends IGameManagerService.Stub {
        mGameServiceController.setGameServiceProvider(packageName);
    }


    /**
     * Updates the resolution scaling factor for the package's target game mode and activates it.
     *
     * @param scalingFactor enable scaling override over any other compat scaling if positive,
     *                      disable otherwise
     * @throws SecurityException        if caller doesn't have
     *                                  {@link android.Manifest.permission#MANAGE_GAME_MODE}
     *                                  permission.
     * @throws IllegalArgumentException if the user ID provided doesn't exist.
     */
    @Override
    @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
    public void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor,
            int userId) throws SecurityException, IllegalArgumentException {
        checkPermission(Manifest.permission.MANAGE_GAME_MODE);
        synchronized (mLock) {
            if (!mSettings.containsKey(userId)) {
                throw new IllegalArgumentException("User " + userId + " wasn't started");
            }
        }
        setGameModeConfigOverride(packageName, userId, gameMode, null /*fpsStr*/,
                Float.toString(scalingFactor));
    }

    /**
     * Gets the resolution scaling factor for the package's target game mode.
     *
     * @return scaling factor for the game mode if exists or negative value otherwise.
     * @throws SecurityException        if caller doesn't have
     *                                  {@link android.Manifest.permission#MANAGE_GAME_MODE}
     *                                  permission.
     * @throws IllegalArgumentException if the user ID provided doesn't exist.
     */
    @Override
    @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
    public float getResolutionScalingFactor(String packageName, int gameMode, int userId)
            throws SecurityException, IllegalArgumentException {
        checkPermission(Manifest.permission.MANAGE_GAME_MODE);
        synchronized (mLock) {
            if (!mSettings.containsKey(userId)) {
                throw new IllegalArgumentException("User " + userId + " wasn't started");
            }
        }
        return getResolutionScalingFactorInternal(packageName, gameMode, userId);
    }

    float getResolutionScalingFactorInternal(String packageName, int gameMode, int userId) {
        final GamePackageConfiguration packageConfig = getConfig(packageName);
        if (packageConfig == null) {
            return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
        }
        final GamePackageConfiguration.GameModeConfiguration modeConfig =
                packageConfig.getGameModeConfiguration(gameMode);
        if (modeConfig != null) {
            return modeConfig.getScaling();
        }
        return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
    }

    /**
     * Notified when boot is completed.
     */
@@ -1319,6 +1396,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
        }
        long scaleId = modeConfig.getCompatChangeId();
        if (scaleId == 0) {
            disableCompatScale(packageName);
            Slog.w(TAG, "Invalid downscaling change id " + scaleId + " for "
                    + packageName);
            return;
@@ -1408,7 +1486,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
        }
        // modify GameModeConfiguration intervention settings
        GamePackageConfiguration.GameModeConfiguration overrideModeConfig =
                overrideConfig.getGameModeConfiguration(gameMode);
                overrideConfig.getOrAddDefaultGameModeConfiguration(gameMode);

        if (fpsStr != null) {
            overrideModeConfig.setFpsStr(fpsStr);
@@ -1417,10 +1495,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
                    GamePackageConfiguration.GameModeConfiguration.DEFAULT_FPS);
        }
        if (scaling != null) {
            overrideModeConfig.setScaling(scaling);
        } else {
            overrideModeConfig.setScaling(
                    GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING);
            overrideModeConfig.setScaling(Float.parseFloat(scaling));
        }
        Slog.i(TAG, "Package Name: " + packageName
                + " FPS: " + String.valueOf(overrideModeConfig.getFps())
@@ -1470,7 +1545,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
            }

            // If the game mode to reset is the only mode other than standard mode,
            // The override config is removed.
            // the override config is removed.
            if (modes.length <= 2) {
                synchronized (mOverrideConfigLock) {
                    mOverrideConfigs.remove(packageName);
@@ -1646,7 +1721,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
                    final int useAngle = gameModeConfiguration.getUseAngle() ? 1 : 0;
                    sb.append(TextUtils.formatSimple("angle=%d", useAngle));
                    sb.append(",");
                    final String scaling = gameModeConfiguration.getScaling();
                    final float scaling = gameModeConfiguration.getScaling();
                    sb.append("scaling=");
                    sb.append(scaling);
                    sb.append(",");
+13 −66
Original line number Diff line number Diff line
@@ -16,21 +16,6 @@

package com.android.server.app;

import static com.android.server.wm.CompatModePackages.DOWNSCALED;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;

import android.app.ActivityManager;
import android.app.GameManager;
import android.app.IGameManagerService;
@@ -39,7 +24,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.ShellCommand;
import android.util.ArraySet;

import java.io.PrintWriter;
import java.util.Locale;
@@ -53,23 +37,6 @@ public class GameManagerShellCommand extends ShellCommand {

    public GameManagerShellCommand() {}

    private static final ArraySet<Long> DOWNSCALE_CHANGE_IDS = new ArraySet<>(new Long[]{
            DOWNSCALED,
            DOWNSCALE_90,
            DOWNSCALE_85,
            DOWNSCALE_80,
            DOWNSCALE_75,
            DOWNSCALE_70,
            DOWNSCALE_65,
            DOWNSCALE_60,
            DOWNSCALE_55,
            DOWNSCALE_50,
            DOWNSCALE_45,
            DOWNSCALE_40,
            DOWNSCALE_35,
            DOWNSCALE_30,
    });

    @Override
    public int onCommand(String cmd) {
        if (cmd == null) {
@@ -212,12 +179,16 @@ public class GameManagerShellCommand extends ShellCommand {
                case "--downscale":
                    if (downscaleRatio == null) {
                        downscaleRatio = getNextArgRequired();
                        if (downscaleRatio != null
                                && GameManagerService.getCompatChangeId(downscaleRatio) == 0
                                && !downscaleRatio.equals("disable")) {
                        if ("disable".equals(downscaleRatio)) {
                            downscaleRatio = "-1";
                        } else {
                            try {
                                Float.parseFloat(downscaleRatio);
                            } catch (NumberFormatException e) {
                                pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
                                return -1;
                            }
                        }
                    } else {
                        pw.println("Duplicate option '" + option + "'");
                        return -1;
@@ -249,40 +220,16 @@ 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);

        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);
+113 −15
Original line number Diff line number Diff line
@@ -578,7 +578,7 @@ public class GameManagerServiceTests {
    }

    private void checkDownscaling(GameManagerService gameManagerService,
                int gameMode, String scaling) {
                int gameMode, float scaling) {
        if (gameManagerService == null) {
            gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
            startUser(gameManagerService, USER_ID_1);
@@ -586,7 +586,7 @@ public class GameManagerServiceTests {
        }
        GameManagerService.GamePackageConfiguration config =
                gameManagerService.getConfig(mPackageName);
        assertEquals(config.getGameModeConfiguration(gameMode).getScaling(), scaling);
        assertEquals(scaling, config.getGameModeConfiguration(gameMode).getScaling(), 0.01f);
    }

    private void checkAngleEnabled(GameManagerService gameManagerService, int gameMode,
@@ -715,7 +715,7 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
    }

@@ -735,7 +735,7 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
                GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
    }

@@ -757,9 +757,9 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
    }

@@ -782,7 +782,7 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
    }

@@ -805,7 +805,7 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
                GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
    }

@@ -829,9 +829,9 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
    }

@@ -858,9 +858,9 @@ public class GameManagerServiceTests {

        checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
                GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
    }

@@ -933,7 +933,7 @@ public class GameManagerServiceTests {
    public void testInterventionAllowScalingDefault() throws Exception {
        mockDeviceConfigPerformance();
        mockModifyGameModeGranted();
        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
    }

    /**
@@ -944,7 +944,7 @@ public class GameManagerServiceTests {
        mockDeviceConfigPerformance();
        mockInterventionAllowDownscaleFalse();
        mockModifyGameModeGranted();
        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "1.0");
        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, -1.0f);
    }

    /**
@@ -956,7 +956,7 @@ public class GameManagerServiceTests {
        mockDeviceConfigPerformance();
        mockInterventionAllowDownscaleTrue();
        mockModifyGameModeGranted();
        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
        checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
    }

    /**
@@ -1404,4 +1404,102 @@ public class GameManagerServiceTests {
        assertEquals(splitLine[6], "angle=0,scaling=0.7,fps=30");

    }

    @Test
    public void testUpdateResolutionScalingFactor() {
        mockModifyGameModeGranted();
        mockDeviceConfigBattery();
        GameManagerService gameManagerService =
                new GameManagerService(mMockContext, mTestLooper.getLooper());
        startUser(gameManagerService, USER_ID_1);
        float scalingFactor = 0.123f;
        gameManagerService.updateResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, scalingFactor,
                USER_ID_1);
        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
        scalingFactor = 0.321f;
        gameManagerService.updateResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, scalingFactor,
                USER_ID_1);
        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
    }

    @Test
    public void testUpdateResolutionScalingFactor_noDeviceConfig() {
        mockModifyGameModeGranted();
        GameManagerService gameManagerService =
                new GameManagerService(mMockContext, mTestLooper.getLooper());
        startUser(gameManagerService, USER_ID_1);
        float scalingFactor = 0.123f;
        gameManagerService.updateResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, scalingFactor,
                USER_ID_1);
        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
        scalingFactor = 0.321f;
        gameManagerService.updateResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, scalingFactor,
                USER_ID_1);
        assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY,
                USER_ID_1), 0.001f);
    }

    @Test
    public void testUpdateResolutionScalingFactor_permissionDenied() {
        mockModifyGameModeDenied();
        mockDeviceConfigAll();
        GameManagerService gameManagerService =
                new GameManagerService(mMockContext, mTestLooper.getLooper());
        startUser(gameManagerService, USER_ID_1);
        float scalingFactor = 0.123f;
        assertThrows(SecurityException.class, () -> {
            gameManagerService.updateResolutionScalingFactor(mPackageName,
                    GameManager.GAME_MODE_BATTERY, scalingFactor,
                    USER_ID_1);
        });
        mockModifyGameModeGranted();
        assertEquals(0.7f, gameManagerService.getResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
    }

    @Test
    public void testUpdateResolutionScalingFactor_noUserId() {
        mockModifyGameModeGranted();
        GameManagerService gameManagerService =
                new GameManagerService(mMockContext, mTestLooper.getLooper());
        startUser(gameManagerService, USER_ID_2);
        final float scalingFactor = 0.123f;
        assertThrows(IllegalArgumentException.class, () -> {
            gameManagerService.updateResolutionScalingFactor(mPackageName,
                    GameManager.GAME_MODE_BATTERY, scalingFactor,
                    USER_ID_1);
        });
    }

    @Test
    public void testGetResolutionScalingFactor_permissionDenied() {
        mockModifyGameModeDenied();
        mockDeviceConfigAll();
        GameManagerService gameManagerService =
                new GameManagerService(mMockContext, mTestLooper.getLooper());
        startUser(gameManagerService, USER_ID_1);
        assertThrows(SecurityException.class, () -> {
            gameManagerService.getResolutionScalingFactor(mPackageName,
                    GameManager.GAME_MODE_BATTERY, USER_ID_1);
        });
    }

    @Test
    public void testGetResolutionScalingFactor_noUserId() {
        mockModifyGameModeDenied();
        mockDeviceConfigAll();
        GameManagerService gameManagerService =
                new GameManagerService(mMockContext, mTestLooper.getLooper());
        startUser(gameManagerService, USER_ID_2);
        assertEquals(-1f, gameManagerService.getResolutionScalingFactor(mPackageName,
                GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
    }
}