diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java index f650255d75eac..cda18b07c02e7 100644 --- a/services/core/java/com/android/server/app/GameManagerService.java +++ b/services/core/java/com/android/server/app/GameManagerService.java @@ -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 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) { diff --git a/services/core/java/com/android/server/app/GameManagerSettings.java b/services/core/java/com/android/server/app/GameManagerSettings.java index 638bc4e7a0700..5189017f5bf0a 100644 --- a/services/core/java/com/android/server/app/GameManagerSettings.java +++ b/services/core/java/com/android/server/app/GameManagerSettings.java @@ -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: // // - // + // + // + // + // ... + // // ... // 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 entry : mGameModes.entrySet()) { - String packageName = entry.getKey(); + final ArraySet 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); diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java index aa9b77c42e09c..abab0e7ae3b9b 100644 --- a/services/core/java/com/android/server/app/GameManagerShellCommand.java +++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java @@ -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 { * ` * see: {@link GameManagerServiceTests#mockDeviceConfigAll()} */ - return runGameMode(pw); + return runSetGameMode(pw); } - case "list": { - return runGameList(pw); + case "list-modes": { + return runListGameModes(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); - return -1; + 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 ] [1|2|3|standard|performance|battery] "); + pw.println(" Deprecated. Please use `custom` command."); + pw.println(" list-configs "); + pw.println(" Lists the current intervention configs of an app."); + pw.println(" list-modes "); + pw.println(" Lists the current available game modes of an app."); + pw.println(" mode [--user ] [1|2|3|4|standard|performance|battery|custom] " + + ""); pw.println(" Set app to run in the specified game mode, if supported."); pw.println(" --user : apply for the given user,"); pw.println(" the current user is used when unspecified."); - pw.println(" set --mode [2|3|performance|battery] [intervention configs] "); - pw.println(" Set app to run at given game mode with configs, if supported."); + pw.println(" set [intervention configs] "); + 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 ] "); 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 : apply for the given user,"); 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 9f0d759da1213..a8d894511213b 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java @@ -20,6 +20,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSess import static com.android.server.app.GameManagerService.CANCEL_GAME_LOADING_MODE; import static com.android.server.app.GameManagerService.LOADING_BOOST_MAX_DURATION; import static com.android.server.app.GameManagerService.SET_GAME_STATE; +import static com.android.server.app.GameManagerService.WRITE_DELAY_MILLIS; +import static com.android.server.app.GameManagerService.WRITE_GAME_MODE_INTERVENTION_LIST_FILE; import static com.android.server.app.GameManagerService.WRITE_SETTINGS; import static org.junit.Assert.assertArrayEquals; @@ -1835,9 +1837,7 @@ public class GameManagerServiceTests { public void testUpdateCustomGameModeConfiguration_permissionDenied() { mockModifyGameModeDenied(); mockDeviceConfigAll(); - GameManagerService gameManagerService = - new GameManagerService(mMockContext, mTestLooper.getLooper()); - startUser(gameManagerService, USER_ID_1); + GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); assertThrows(SecurityException.class, () -> { gameManagerService.updateCustomGameModeConfiguration(mPackageName, new GameModeConfiguration.Builder().setScalingFactor(0.5f).build(), @@ -1848,9 +1848,7 @@ public class GameManagerServiceTests { @Test public void testUpdateCustomGameModeConfiguration_noUserId() { mockModifyGameModeGranted(); - GameManagerService gameManagerService = - new GameManagerService(mMockContext, mTestLooper.getLooper()); - startUser(gameManagerService, USER_ID_2); + GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_2); assertThrows(IllegalArgumentException.class, () -> { gameManagerService.updateCustomGameModeConfiguration(mPackageName, new GameModeConfiguration.Builder().setScalingFactor(0.5f).build(), @@ -1873,6 +1871,48 @@ public class GameManagerServiceTests { assertNull(pkgConfig); } + @Test + public void testUpdateCustomGameModeConfiguration() throws InterruptedException { + mockModifyGameModeGranted(); + GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); + gameManagerService.updateCustomGameModeConfiguration(mPackageName, + new GameModeConfiguration.Builder().setScalingFactor(0.35f).setFpsOverride( + 60).build(), + USER_ID_1); + + assertTrue(gameManagerService.mHandler.hasEqualMessages(WRITE_SETTINGS, USER_ID_1)); + assertTrue( + gameManagerService.mHandler.hasEqualMessages(WRITE_GAME_MODE_INTERVENTION_LIST_FILE, + USER_ID_1)); + + GameManagerService.GamePackageConfiguration pkgConfig = gameManagerService.getConfig( + mPackageName, USER_ID_1); + assertNotNull(pkgConfig); + GameManagerService.GamePackageConfiguration.GameModeConfiguration modeConfig = + pkgConfig.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM); + assertNotNull(modeConfig); + assertEquals(modeConfig.getScaling(), 0.35f, 0.01f); + assertEquals(modeConfig.getFps(), 60); + // creates a new service to check that no data has been stored + mTestLooper.dispatchAll(); + gameManagerService = createServiceAndStartUser(USER_ID_1); + pkgConfig = gameManagerService.getConfig(mPackageName, USER_ID_1); + assertNull(pkgConfig); + + mTestLooper.moveTimeForward(WRITE_DELAY_MILLIS + 500); + mTestLooper.dispatchAll(); + // creates a new service to check that data is persisted after delay + gameManagerService = createServiceAndStartUser(USER_ID_1); + assertEquals(GameManager.GAME_MODE_STANDARD, + gameManagerService.getGameMode(mPackageName, USER_ID_1)); + pkgConfig = gameManagerService.getConfig(mPackageName, USER_ID_1); + assertNotNull(pkgConfig); + modeConfig = pkgConfig.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM); + assertNotNull(modeConfig); + assertEquals(modeConfig.getScaling(), 0.35f, 0.01f); + assertEquals(modeConfig.getFps(), 60); + } + @Test public void testWritingSettingFile_onShutdown() throws InterruptedException { mockModifyGameModeGranted(); diff --git a/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java b/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java index 582c78bce54c7..fde3422b1ff36 100644 --- a/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/app/GameManagerServiceSettingsTests.java @@ -52,6 +52,8 @@ public class GameManagerServiceSettingsTests { private static final String PACKAGE_NAME_1 = "com.android.app1"; private static final String PACKAGE_NAME_2 = "com.android.app2"; private static final String PACKAGE_NAME_3 = "com.android.app3"; + private static final String PACKAGE_NAME_4 = "com.android.app4"; + private void writeFile(File file, byte[] data) { file.mkdirs(); @@ -69,16 +71,23 @@ public class GameManagerServiceSettingsTests { writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/game-manager-service.xml"), ("" - + "\n" - + " \n" - + " \n" + + "" + + "\n" // app1: no package config setting + + "\n" // app2: performance mode is selected with override + " \n" + " \n" + " \n" - + " \n" + + " " + + "\n" // app3: only battery mode is selected + " \n" - + " \n" + + " " + + "\n" // app4: no game mode selected but custom game mode config + + " \n" + + " \n" + + " " + + "\n" + "\n").getBytes()); } @@ -115,14 +124,15 @@ public class GameManagerServiceSettingsTests { assertTrue(settings.readPersistentDataLocked()); // test game modes - assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_1)); - assertEquals(2, settings.getGameModeLocked(PACKAGE_NAME_2)); - assertEquals(3, settings.getGameModeLocked(PACKAGE_NAME_3)); + assertEquals(GameManager.GAME_MODE_STANDARD, settings.getGameModeLocked(PACKAGE_NAME_1)); + assertEquals(GameManager.GAME_MODE_PERFORMANCE, settings.getGameModeLocked(PACKAGE_NAME_2)); + assertEquals(GameManager.GAME_MODE_BATTERY, settings.getGameModeLocked(PACKAGE_NAME_3)); + assertEquals(GameManager.GAME_MODE_STANDARD, settings.getGameModeLocked(PACKAGE_NAME_4)); // test game mode configs assertNull(settings.getConfigOverride(PACKAGE_NAME_1)); assertNull(settings.getConfigOverride(PACKAGE_NAME_3)); - final GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_2); + GamePackageConfiguration config = settings.getConfigOverride(PACKAGE_NAME_2); assertNotNull(config); assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_STANDARD)); @@ -141,6 +151,14 @@ public class GameManagerServiceSettingsTests { GameModeConfiguration.DEFAULT_LOADING_BOOST_DURATION); assertEquals(batteryConfig.getFpsStr(), GameModeConfiguration.DEFAULT_FPS); assertFalse(batteryConfig.getUseAngle()); + + config = settings.getConfigOverride(PACKAGE_NAME_4); + assertNotNull(config); + GameModeConfiguration customConfig = config.getGameModeConfiguration( + GameManager.GAME_MODE_CUSTOM); + assertNotNull(customConfig); + assertEquals(customConfig.getScaling(), 0.4f, 0.1f); + assertEquals(customConfig.getFps(), 30); } @Test @@ -176,16 +194,20 @@ public class GameManagerServiceSettingsTests { writeFile(new File(InstrumentationRegistry.getContext().getFilesDir(), "system/game-manager-service.xml"), ("" - + "\n" + + "" + + "\n" // missing package name + " \n" - + " \n" + + " " + + "\n" // app2 with unknown sub element + " \n" + " " + " \n" + " foo bar" - + " \n" + + " " + + "\n" // unknown package element + " \n" - + " foo bar\n" + + " foo bar" + + "\n" // app3 after unknown element + " \n" + " \n" + "\n").getBytes()); @@ -214,6 +236,8 @@ public class GameManagerServiceSettingsTests { settings.setGameModeLocked(PACKAGE_NAME_1, GameManager.GAME_MODE_BATTERY); settings.setGameModeLocked(PACKAGE_NAME_2, GameManager.GAME_MODE_PERFORMANCE); settings.setGameModeLocked(PACKAGE_NAME_3, GameManager.GAME_MODE_STANDARD); + + // set config for app2 GamePackageConfiguration config = new GamePackageConfiguration(PACKAGE_NAME_2); GameModeConfiguration performanceConfig = config.getOrAddDefaultGameModeConfiguration( GameManager.GAME_MODE_PERFORMANCE); @@ -225,18 +249,29 @@ public class GameManagerServiceSettingsTests { GameManager.GAME_MODE_BATTERY); batteryConfig.setScaling(0.77f); settings.setConfigOverride(PACKAGE_NAME_2, config); + + // set config for app4 + config = new GamePackageConfiguration(PACKAGE_NAME_4); + GameModeConfiguration customConfig = config.getOrAddDefaultGameModeConfiguration( + GameManager.GAME_MODE_CUSTOM); + customConfig.setScaling(0.4f); + customConfig.setFpsStr("30"); + settings.setConfigOverride(PACKAGE_NAME_4, config); + settings.writePersistentDataLocked(); // clear the settings in memory settings.removeGame(PACKAGE_NAME_1); settings.removeGame(PACKAGE_NAME_2); settings.removeGame(PACKAGE_NAME_3); + settings.removeGame(PACKAGE_NAME_4); // read back in and verify assertTrue(settings.readPersistentDataLocked()); assertEquals(3, settings.getGameModeLocked(PACKAGE_NAME_1)); assertEquals(2, settings.getGameModeLocked(PACKAGE_NAME_2)); assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_3)); + assertEquals(1, settings.getGameModeLocked(PACKAGE_NAME_4)); config = settings.getConfigOverride(PACKAGE_NAME_1); assertNull(config); @@ -256,5 +291,14 @@ public class GameManagerServiceSettingsTests { assertEquals(performanceConfig.getLoadingBoostDuration(), 321); assertEquals(performanceConfig.getFpsStr(), "60"); assertTrue(performanceConfig.getUseAngle()); + + config = settings.getConfigOverride(PACKAGE_NAME_4); + assertNotNull(config); + customConfig = config.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM); + assertNotNull(customConfig); + assertEquals(customConfig.getScaling(), 0.4f, 0.1f); + assertEquals(customConfig.getFps(), 30); + assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE)); + assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_BATTERY)); } }