diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl index e60a74acdc1c6..481e7b0050ab2 100644 --- a/core/java/android/app/IGameManagerService.aidl +++ b/core/java/android/app/IGameManagerService.aidl @@ -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); } diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index d5e893984bf37..60de31cf8cf46 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -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(","); diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java index 470c320dbd7d2..487d19aa6aba5 100644 --- a/services/core/java/com/android/server/app/GameManagerShellCommand.java +++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java @@ -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 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,11 +179,15 @@ public class GameManagerShellCommand extends ShellCommand { case "--downscale": if (downscaleRatio == null) { downscaleRatio = getNextArgRequired(); - if (downscaleRatio != null - && GameManagerService.getCompatChangeId(downscaleRatio) == 0 - && !downscaleRatio.equals("disable")) { - pw.println("Invalid scaling ratio '" + downscaleRatio + "'"); - return -1; + 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 + "'"); @@ -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; - } + gameManagerService.setGameModeConfigOverride(packageName, userId, + GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio); 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; - } + gameManagerService.setGameModeConfigOverride(packageName, userId, + GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio); break; default: pw.println("Invalid game mode: " + gameMode); diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java index d325e47f76879..b3a7ad0486660 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java @@ -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); + } }