Loading core/java/android/app/GameManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ public final class GameManager { @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) public @GameMode int[] getAvailableGameModes(@NonNull String packageName) { try { return mService.getAvailableGameModes(packageName); return mService.getAvailableGameModes(packageName, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading core/java/android/app/IGameManagerService.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ interface IGameManagerService { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") void setGameMode(String packageName, int gameMode, int userId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") int[] getAvailableGameModes(String packageName); int[] getAvailableGameModes(String packageName, int userId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") boolean isAngleEnabled(String packageName, int userId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") Loading services/core/java/com/android/server/app/GameManagerService.java +24 −17 Original line number Diff line number Diff line Loading @@ -452,6 +452,7 @@ public final class GameManagerService extends IGameManagerService.Stub { public void setGameState(String packageName, @NonNull GameState gameState, @UserIdInt int userId) { if (!isPackageGame(packageName, userId)) { Slog.d(TAG, "No-op for attempt to set game state for non-game app: " + packageName); // Restrict to games only. return; } Loading Loading @@ -979,11 +980,8 @@ public final class GameManagerService extends IGameManagerService.Stub { } } private @GameMode int[] getAvailableGameModesUnchecked(String packageName) { final GamePackageConfiguration config; synchronized (mDeviceConfigLock) { config = mConfigs.get(packageName); } private @GameMode int[] getAvailableGameModesUnchecked(String packageName, int userId) { final GamePackageConfiguration config = getConfig(packageName, userId); if (config == null) { return new int[]{GameManager.GAME_MODE_STANDARD, GameManager.GAME_MODE_CUSTOM}; } Loading @@ -1006,9 +1004,13 @@ public final class GameManagerService extends IGameManagerService.Stub { */ @Override @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) public @GameMode int[] getAvailableGameModes(String packageName) throws SecurityException { public @GameMode int[] getAvailableGameModes(String packageName, int userId) throws SecurityException { checkPermission(Manifest.permission.MANAGE_GAME_MODE); return getAvailableGameModesUnchecked(packageName); if (!isPackageGame(packageName, userId)) { return new int[]{}; } return getAvailableGameModesUnchecked(packageName, userId); } private @GameMode int getGameModeFromSettingsUnchecked(String packageName, Loading Loading @@ -1075,7 +1077,6 @@ public final class GameManagerService extends IGameManagerService.Stub { // Check the caller has the necessary permission. checkPermission(Manifest.permission.MANAGE_GAME_MODE); // Restrict to games only. if (!isPackageGame(packageName, userId)) { return null; } Loading Loading @@ -1105,7 +1106,7 @@ public final class GameManagerService extends IGameManagerService.Stub { } else { return new GameModeInfo.Builder() .setActiveGameMode(activeGameMode) .setAvailableGameModes(getAvailableGameModesUnchecked(packageName)) .setAvailableGameModes(getAvailableGameModesUnchecked(packageName, userId)) .build(); } } Loading @@ -1119,9 +1120,11 @@ public final class GameManagerService extends IGameManagerService.Stub { public void setGameMode(String packageName, @GameMode int gameMode, int userId) throws SecurityException { checkPermission(Manifest.permission.MANAGE_GAME_MODE); if (!isPackageGame(packageName, userId) || gameMode == GameManager.GAME_MODE_UNSUPPORTED) { // Restrict to games and valid game modes only. if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) { Slog.d(TAG, "No-op for attempt to set UNSUPPORTED mode for app: " + packageName); return; } else if (!isPackageGame(packageName, userId)) { Slog.d(TAG, "No-op for attempt to set game mode for non-game app: " + packageName); return; } int fromGameMode; Loading Loading @@ -1229,17 +1232,16 @@ public final class GameManagerService extends IGameManagerService.Stub { Binder.getCallingUid(), userId, false, true, "notifyGraphicsEnvironmentSetup", "com.android.server.app.GameManagerService"); // Restrict to games only. if (!isPackageGame(packageName, userId)) { return; } if (!isValidPackageName(packageName, userId)) { Slog.d(TAG, "No-op for attempt to notify graphics env setup for different package" + "than caller with uid: " + Binder.getCallingUid()); return; } final int gameMode = getGameMode(packageName, userId); if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) { Slog.d(TAG, "No-op for attempt to notify graphics env setup for non-game app: " + packageName); return; } int loadingBoostDuration = getLoadingBoostDuration(packageName, userId); Loading Loading @@ -1354,6 +1356,11 @@ public final class GameManagerService extends IGameManagerService.Stub { GameModeConfiguration gameModeConfig, int userId) throws SecurityException, IllegalArgumentException { checkPermission(Manifest.permission.MANAGE_GAME_MODE); if (!isPackageGame(packageName, userId)) { Slog.d(TAG, "No-op for attempt to update custom game mode for non-game app: " + packageName); return; } synchronized (mLock) { if (!mSettings.containsKey(userId)) { throw new IllegalArgumentException("User " + userId + " wasn't started"); Loading services/core/java/com/android/server/app/GameManagerShellCommand.java +4 −4 Original line number Diff line number Diff line Loading @@ -105,7 +105,9 @@ public class GameManagerShellCommand extends ShellCommand { ServiceManager.getServiceOrThrow(Context.GAME_SERVICE)); boolean batteryModeSupported = false; boolean perfModeSupported = false; int[] modes = service.getAvailableGameModes(packageName); int userId = userIdStr != null ? Integer.parseInt(userIdStr) : ActivityManager.getCurrentUser(); int[] modes = service.getAvailableGameModes(packageName, userId); for (int mode : modes) { if (mode == GameManager.GAME_MODE_PERFORMANCE) { perfModeSupported = true; Loading @@ -113,8 +115,6 @@ public class GameManagerShellCommand extends ShellCommand { batteryModeSupported = true; } } int userId = userIdStr != null ? Integer.parseInt(userIdStr) : ActivityManager.getCurrentUser(); switch (gameMode.toLowerCase()) { case "1": case "standard": Loading Loading @@ -223,7 +223,7 @@ public class GameManagerShellCommand extends ShellCommand { boolean batteryModeSupported = false; boolean perfModeSupported = false; int [] modes = gameManagerService.getAvailableGameModes(packageName); int [] modes = gameManagerService.getAvailableGameModes(packageName, userId); for (int mode : modes) { if (mode == GameManager.GAME_MODE_PERFORMANCE) { Loading services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +189 −32 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.server.app; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 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_SETTINGS; import static org.junit.Assert.assertArrayEquals; Loading Loading @@ -59,6 +61,7 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.hardware.power.Mode; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.PowerManagerInternal; Loading Loading @@ -104,7 +107,8 @@ public class GameManagerServiceTests { private static final String PACKAGE_NAME_INVALID = "com.android.app"; private static final int USER_ID_1 = 1001; private static final int USER_ID_2 = 1002; private static final int DEFAULT_PACKAGE_UID = 12345; // to pass the valid package check in some of the server methods private static final int DEFAULT_PACKAGE_UID = Binder.getCallingUid(); private MockitoSession mMockingSession; private String mPackageName; Loading Loading @@ -205,28 +209,33 @@ public class GameManagerServiceTests { .startMocking(); mMockContext = new MockContext(InstrumentationRegistry.getContext()); mPackageName = mMockContext.getPackageName(); final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.category = ApplicationInfo.CATEGORY_GAME; applicationInfo.packageName = mPackageName; final PackageInfo pi = new PackageInfo(); pi.packageName = mPackageName; pi.applicationInfo = applicationInfo; final List<PackageInfo> packages = new ArrayList<>(); packages.add(pi); mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_GAME); final Resources resources = InstrumentationRegistry.getInstrumentation().getContext().getResources(); when(mMockPackageManager.getResourcesForApplication(anyString())) .thenReturn(resources); when(mMockPackageManager.getInstalledPackagesAsUser(anyInt(), anyInt())) .thenReturn(packages); when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) .thenReturn(applicationInfo); when(mMockPackageManager.getPackageUidAsUser(mPackageName, USER_ID_1)).thenReturn( DEFAULT_PACKAGE_UID); LocalServices.addService(PowerManagerInternal.class, mMockPowerManager); } private void mockAppCategory(String packageName, @ApplicationInfo.Category int category) throws Exception { reset(mMockPackageManager); final ApplicationInfo gameApplicationInfo = new ApplicationInfo(); gameApplicationInfo.category = category; gameApplicationInfo.packageName = packageName; final PackageInfo pi = new PackageInfo(); pi.packageName = packageName; pi.applicationInfo = gameApplicationInfo; final List<PackageInfo> packages = new ArrayList<>(); packages.add(pi); when(mMockPackageManager.getInstalledPackagesAsUser(anyInt(), anyInt())) .thenReturn(packages); when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) .thenReturn(gameApplicationInfo); } @After public void tearDown() throws Exception { LocalServices.removeServiceForTest(PowerManagerInternal.class); Loading Loading @@ -457,17 +466,22 @@ public class GameManagerServiceTests { * By default game mode is set to STANDARD */ @Test public void testGameModeDefaultValue() { GameManagerService gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper()); startUser(gameManagerService, USER_ID_1); public void testGetGameMode_defaultValue() { GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); mockModifyGameModeGranted(); assertEquals(GameManager.GAME_MODE_STANDARD, gameManagerService.getGameMode(mPackageName, USER_ID_1)); } @Test public void testGetGameMode_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); mockModifyGameModeGranted(); assertEquals(GameManager.GAME_MODE_UNSUPPORTED, gameManagerService.getGameMode(mPackageName, USER_ID_1)); } /** * Test the default behaviour for a nonexistent user. */ Loading Loading @@ -614,17 +628,22 @@ public class GameManagerServiceTests { int... requiredAvailableModes) { Arrays.sort(requiredAvailableModes); // check getAvailableGameModes int[] reportedAvailableModes = gameManagerService.getAvailableGameModes(mPackageName); int[] reportedAvailableModes = gameManagerService.getAvailableGameModes(mPackageName, USER_ID_1); Arrays.sort(reportedAvailableModes); assertArrayEquals(requiredAvailableModes, reportedAvailableModes); // check GetModeInfo.getAvailableGameModes GameModeInfo info = gameManagerService.getGameModeInfo(mPackageName, USER_ID_1); if (requiredAvailableModes.length == 0) { assertNull(info); } else { assertNotNull(info); reportedAvailableModes = info.getAvailableGameModes(); Arrays.sort(reportedAvailableModes); assertArrayEquals(requiredAvailableModes, reportedAvailableModes); } } private void checkReportedOptedInGameModes(GameManagerService gameManagerService, int... requiredOptedInModes) { Loading Loading @@ -726,6 +745,14 @@ public class GameManagerServiceTests { GameManager.GAME_MODE_STANDARD, GameManager.GAME_MODE_CUSTOM); } @Test public void testDeviceConfig_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO); mockDeviceConfigAll(); mockModifyGameModeGranted(); checkReportedAvailableGameModes(createServiceAndStartUser(USER_ID_1)); } /** * Override device config for performance mode exists and is valid. */ Loading Loading @@ -1443,12 +1470,10 @@ public class GameManagerServiceTests { } @Test public void testGameStateLoadingRequiresPerformanceMode() { public void testSetGameState_loadingRequiresPerformanceMode() { mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper()); startUser(gameManagerService, USER_ID_1); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); GameState gameState = new GameState(true, GameState.MODE_NONE); gameManagerService.setGameState(mPackageName, gameState, USER_ID_1); mTestLooper.dispatchAll(); Loading Loading @@ -1509,9 +1534,7 @@ public class GameManagerServiceTests { public void testSetGameStateNotLoading() { mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper()); startUser(gameManagerService, USER_ID_1); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode( mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); int testMode = GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE; Loading @@ -1523,12 +1546,24 @@ public class GameManagerServiceTests { assertEquals(testLabel, gameState.getLabel()); assertEquals(testQuality, gameState.getQuality()); gameManagerService.setGameState(mPackageName, gameState, USER_ID_1); assertTrue(gameManagerService.mHandler.hasEqualMessages(SET_GAME_STATE, gameState)); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); assertFalse( gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testSetGameState_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO); mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); GameState gameState = new GameState(true, GameState.MODE_NONE); gameManagerService.setGameState(mPackageName, gameState, USER_ID_1); assertFalse(gameManagerService.mHandler.hasMessages(SET_GAME_STATE)); } private List<String> readGameModeInterventionList() throws Exception { final File interventionFile = new File(InstrumentationRegistry.getContext().getFilesDir(), "system/game_mode_intervention.list"); Loading Loading @@ -1823,6 +1858,21 @@ public class GameManagerServiceTests { }); } @Test public void testUpdateCustomGameModeConfiguration_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_IMAGE); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.updateCustomGameModeConfiguration(mPackageName, new GameModeConfiguration.Builder().setScalingFactor(0.35f).setFpsOverride( 60).build(), USER_ID_1); assertFalse(gameManagerService.mHandler.hasMessages(WRITE_SETTINGS)); GameManagerService.GamePackageConfiguration pkgConfig = gameManagerService.getConfig( mPackageName, USER_ID_1); assertNull(pkgConfig); } @Test public void testWritingSettingFile_onShutdown() throws InterruptedException { mockModifyGameModeGranted(); Loading Loading @@ -1983,4 +2033,111 @@ public class GameManagerServiceTests { } folder.delete(); } @Test public void testNotifyGraphicsEnvironmentSetup() { String configString = "mode=2,loadingBoost=2000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, true); reset(mMockPowerManager); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(2000); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); } @Test public void testNotifyGraphicsEnvironmentSetup_outOfBoundBoostValue() { String configString = "mode=2,loadingBoost=0:mode=3,loadingBoost=7000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, true); reset(mMockPowerManager); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(100); mTestLooper.dispatchAll(); // 0 loading boost value should still trigger max timeout verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(LOADING_BOOST_MAX_DURATION); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); reset(mMockPowerManager); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); // 7000 loading boost value should exceed the max timeout of 5s and be bounded gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, true); reset(mMockPowerManager); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(LOADING_BOOST_MAX_DURATION); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_noDeviceConfig() { mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_noLoadingBoostValue() { mockDeviceConfigAll(); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_nonGame() throws Exception { String configString = "mode=2,loadingBoost=2000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_IMAGE); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); assertEquals(GameManager.GAME_MODE_UNSUPPORTED, gameManagerService.getGameMode(mPackageName, USER_ID_1)); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_differentApp() throws Exception { String configString = "mode=2,loadingBoost=2000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); String someGamePkg = "some.game"; mockAppCategory(someGamePkg, ApplicationInfo.CATEGORY_GAME); when(mMockPackageManager.getPackageUidAsUser(someGamePkg, USER_ID_1)).thenReturn( DEFAULT_PACKAGE_UID + 1); gameManagerService.setGameMode(someGamePkg, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); assertEquals(GameManager.GAME_MODE_PERFORMANCE, gameManagerService.getGameMode(someGamePkg, USER_ID_1)); gameManagerService.notifyGraphicsEnvironmentSetup(someGamePkg, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } } Loading
core/java/android/app/GameManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ public final class GameManager { @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) public @GameMode int[] getAvailableGameModes(@NonNull String packageName) { try { return mService.getAvailableGameModes(packageName); return mService.getAvailableGameModes(packageName, mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } Loading
core/java/android/app/IGameManagerService.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ interface IGameManagerService { @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") void setGameMode(String packageName, int gameMode, int userId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") int[] getAvailableGameModes(String packageName); int[] getAvailableGameModes(String packageName, int userId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") boolean isAngleEnabled(String packageName, int userId); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_GAME_MODE)") Loading
services/core/java/com/android/server/app/GameManagerService.java +24 −17 Original line number Diff line number Diff line Loading @@ -452,6 +452,7 @@ public final class GameManagerService extends IGameManagerService.Stub { public void setGameState(String packageName, @NonNull GameState gameState, @UserIdInt int userId) { if (!isPackageGame(packageName, userId)) { Slog.d(TAG, "No-op for attempt to set game state for non-game app: " + packageName); // Restrict to games only. return; } Loading Loading @@ -979,11 +980,8 @@ public final class GameManagerService extends IGameManagerService.Stub { } } private @GameMode int[] getAvailableGameModesUnchecked(String packageName) { final GamePackageConfiguration config; synchronized (mDeviceConfigLock) { config = mConfigs.get(packageName); } private @GameMode int[] getAvailableGameModesUnchecked(String packageName, int userId) { final GamePackageConfiguration config = getConfig(packageName, userId); if (config == null) { return new int[]{GameManager.GAME_MODE_STANDARD, GameManager.GAME_MODE_CUSTOM}; } Loading @@ -1006,9 +1004,13 @@ public final class GameManagerService extends IGameManagerService.Stub { */ @Override @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE) public @GameMode int[] getAvailableGameModes(String packageName) throws SecurityException { public @GameMode int[] getAvailableGameModes(String packageName, int userId) throws SecurityException { checkPermission(Manifest.permission.MANAGE_GAME_MODE); return getAvailableGameModesUnchecked(packageName); if (!isPackageGame(packageName, userId)) { return new int[]{}; } return getAvailableGameModesUnchecked(packageName, userId); } private @GameMode int getGameModeFromSettingsUnchecked(String packageName, Loading Loading @@ -1075,7 +1077,6 @@ public final class GameManagerService extends IGameManagerService.Stub { // Check the caller has the necessary permission. checkPermission(Manifest.permission.MANAGE_GAME_MODE); // Restrict to games only. if (!isPackageGame(packageName, userId)) { return null; } Loading Loading @@ -1105,7 +1106,7 @@ public final class GameManagerService extends IGameManagerService.Stub { } else { return new GameModeInfo.Builder() .setActiveGameMode(activeGameMode) .setAvailableGameModes(getAvailableGameModesUnchecked(packageName)) .setAvailableGameModes(getAvailableGameModesUnchecked(packageName, userId)) .build(); } } Loading @@ -1119,9 +1120,11 @@ public final class GameManagerService extends IGameManagerService.Stub { public void setGameMode(String packageName, @GameMode int gameMode, int userId) throws SecurityException { checkPermission(Manifest.permission.MANAGE_GAME_MODE); if (!isPackageGame(packageName, userId) || gameMode == GameManager.GAME_MODE_UNSUPPORTED) { // Restrict to games and valid game modes only. if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) { Slog.d(TAG, "No-op for attempt to set UNSUPPORTED mode for app: " + packageName); return; } else if (!isPackageGame(packageName, userId)) { Slog.d(TAG, "No-op for attempt to set game mode for non-game app: " + packageName); return; } int fromGameMode; Loading Loading @@ -1229,17 +1232,16 @@ public final class GameManagerService extends IGameManagerService.Stub { Binder.getCallingUid(), userId, false, true, "notifyGraphicsEnvironmentSetup", "com.android.server.app.GameManagerService"); // Restrict to games only. if (!isPackageGame(packageName, userId)) { return; } if (!isValidPackageName(packageName, userId)) { Slog.d(TAG, "No-op for attempt to notify graphics env setup for different package" + "than caller with uid: " + Binder.getCallingUid()); return; } final int gameMode = getGameMode(packageName, userId); if (gameMode == GameManager.GAME_MODE_UNSUPPORTED) { Slog.d(TAG, "No-op for attempt to notify graphics env setup for non-game app: " + packageName); return; } int loadingBoostDuration = getLoadingBoostDuration(packageName, userId); Loading Loading @@ -1354,6 +1356,11 @@ public final class GameManagerService extends IGameManagerService.Stub { GameModeConfiguration gameModeConfig, int userId) throws SecurityException, IllegalArgumentException { checkPermission(Manifest.permission.MANAGE_GAME_MODE); if (!isPackageGame(packageName, userId)) { Slog.d(TAG, "No-op for attempt to update custom game mode for non-game app: " + packageName); return; } synchronized (mLock) { if (!mSettings.containsKey(userId)) { throw new IllegalArgumentException("User " + userId + " wasn't started"); Loading
services/core/java/com/android/server/app/GameManagerShellCommand.java +4 −4 Original line number Diff line number Diff line Loading @@ -105,7 +105,9 @@ public class GameManagerShellCommand extends ShellCommand { ServiceManager.getServiceOrThrow(Context.GAME_SERVICE)); boolean batteryModeSupported = false; boolean perfModeSupported = false; int[] modes = service.getAvailableGameModes(packageName); int userId = userIdStr != null ? Integer.parseInt(userIdStr) : ActivityManager.getCurrentUser(); int[] modes = service.getAvailableGameModes(packageName, userId); for (int mode : modes) { if (mode == GameManager.GAME_MODE_PERFORMANCE) { perfModeSupported = true; Loading @@ -113,8 +115,6 @@ public class GameManagerShellCommand extends ShellCommand { batteryModeSupported = true; } } int userId = userIdStr != null ? Integer.parseInt(userIdStr) : ActivityManager.getCurrentUser(); switch (gameMode.toLowerCase()) { case "1": case "standard": Loading Loading @@ -223,7 +223,7 @@ public class GameManagerShellCommand extends ShellCommand { boolean batteryModeSupported = false; boolean perfModeSupported = false; int [] modes = gameManagerService.getAvailableGameModes(packageName); int [] modes = gameManagerService.getAvailableGameModes(packageName, userId); for (int mode : modes) { if (mode == GameManager.GAME_MODE_PERFORMANCE) { Loading
services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java +189 −32 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.server.app; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 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_SETTINGS; import static org.junit.Assert.assertArrayEquals; Loading Loading @@ -59,6 +61,7 @@ import android.content.res.AssetManager; import android.content.res.Resources; import android.content.res.XmlResourceParser; import android.hardware.power.Mode; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.PowerManagerInternal; Loading Loading @@ -104,7 +107,8 @@ public class GameManagerServiceTests { private static final String PACKAGE_NAME_INVALID = "com.android.app"; private static final int USER_ID_1 = 1001; private static final int USER_ID_2 = 1002; private static final int DEFAULT_PACKAGE_UID = 12345; // to pass the valid package check in some of the server methods private static final int DEFAULT_PACKAGE_UID = Binder.getCallingUid(); private MockitoSession mMockingSession; private String mPackageName; Loading Loading @@ -205,28 +209,33 @@ public class GameManagerServiceTests { .startMocking(); mMockContext = new MockContext(InstrumentationRegistry.getContext()); mPackageName = mMockContext.getPackageName(); final ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.category = ApplicationInfo.CATEGORY_GAME; applicationInfo.packageName = mPackageName; final PackageInfo pi = new PackageInfo(); pi.packageName = mPackageName; pi.applicationInfo = applicationInfo; final List<PackageInfo> packages = new ArrayList<>(); packages.add(pi); mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_GAME); final Resources resources = InstrumentationRegistry.getInstrumentation().getContext().getResources(); when(mMockPackageManager.getResourcesForApplication(anyString())) .thenReturn(resources); when(mMockPackageManager.getInstalledPackagesAsUser(anyInt(), anyInt())) .thenReturn(packages); when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) .thenReturn(applicationInfo); when(mMockPackageManager.getPackageUidAsUser(mPackageName, USER_ID_1)).thenReturn( DEFAULT_PACKAGE_UID); LocalServices.addService(PowerManagerInternal.class, mMockPowerManager); } private void mockAppCategory(String packageName, @ApplicationInfo.Category int category) throws Exception { reset(mMockPackageManager); final ApplicationInfo gameApplicationInfo = new ApplicationInfo(); gameApplicationInfo.category = category; gameApplicationInfo.packageName = packageName; final PackageInfo pi = new PackageInfo(); pi.packageName = packageName; pi.applicationInfo = gameApplicationInfo; final List<PackageInfo> packages = new ArrayList<>(); packages.add(pi); when(mMockPackageManager.getInstalledPackagesAsUser(anyInt(), anyInt())) .thenReturn(packages); when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) .thenReturn(gameApplicationInfo); } @After public void tearDown() throws Exception { LocalServices.removeServiceForTest(PowerManagerInternal.class); Loading Loading @@ -457,17 +466,22 @@ public class GameManagerServiceTests { * By default game mode is set to STANDARD */ @Test public void testGameModeDefaultValue() { GameManagerService gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper()); startUser(gameManagerService, USER_ID_1); public void testGetGameMode_defaultValue() { GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); mockModifyGameModeGranted(); assertEquals(GameManager.GAME_MODE_STANDARD, gameManagerService.getGameMode(mPackageName, USER_ID_1)); } @Test public void testGetGameMode_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); mockModifyGameModeGranted(); assertEquals(GameManager.GAME_MODE_UNSUPPORTED, gameManagerService.getGameMode(mPackageName, USER_ID_1)); } /** * Test the default behaviour for a nonexistent user. */ Loading Loading @@ -614,17 +628,22 @@ public class GameManagerServiceTests { int... requiredAvailableModes) { Arrays.sort(requiredAvailableModes); // check getAvailableGameModes int[] reportedAvailableModes = gameManagerService.getAvailableGameModes(mPackageName); int[] reportedAvailableModes = gameManagerService.getAvailableGameModes(mPackageName, USER_ID_1); Arrays.sort(reportedAvailableModes); assertArrayEquals(requiredAvailableModes, reportedAvailableModes); // check GetModeInfo.getAvailableGameModes GameModeInfo info = gameManagerService.getGameModeInfo(mPackageName, USER_ID_1); if (requiredAvailableModes.length == 0) { assertNull(info); } else { assertNotNull(info); reportedAvailableModes = info.getAvailableGameModes(); Arrays.sort(reportedAvailableModes); assertArrayEquals(requiredAvailableModes, reportedAvailableModes); } } private void checkReportedOptedInGameModes(GameManagerService gameManagerService, int... requiredOptedInModes) { Loading Loading @@ -726,6 +745,14 @@ public class GameManagerServiceTests { GameManager.GAME_MODE_STANDARD, GameManager.GAME_MODE_CUSTOM); } @Test public void testDeviceConfig_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO); mockDeviceConfigAll(); mockModifyGameModeGranted(); checkReportedAvailableGameModes(createServiceAndStartUser(USER_ID_1)); } /** * Override device config for performance mode exists and is valid. */ Loading Loading @@ -1443,12 +1470,10 @@ public class GameManagerServiceTests { } @Test public void testGameStateLoadingRequiresPerformanceMode() { public void testSetGameState_loadingRequiresPerformanceMode() { mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper()); startUser(gameManagerService, USER_ID_1); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); GameState gameState = new GameState(true, GameState.MODE_NONE); gameManagerService.setGameState(mPackageName, gameState, USER_ID_1); mTestLooper.dispatchAll(); Loading Loading @@ -1509,9 +1534,7 @@ public class GameManagerServiceTests { public void testSetGameStateNotLoading() { mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper()); startUser(gameManagerService, USER_ID_1); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode( mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); int testMode = GameState.MODE_GAMEPLAY_UNINTERRUPTIBLE; Loading @@ -1523,12 +1546,24 @@ public class GameManagerServiceTests { assertEquals(testLabel, gameState.getLabel()); assertEquals(testQuality, gameState.getQuality()); gameManagerService.setGameState(mPackageName, gameState, USER_ID_1); assertTrue(gameManagerService.mHandler.hasEqualMessages(SET_GAME_STATE, gameState)); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); assertFalse( gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testSetGameState_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_AUDIO); mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); GameState gameState = new GameState(true, GameState.MODE_NONE); gameManagerService.setGameState(mPackageName, gameState, USER_ID_1); assertFalse(gameManagerService.mHandler.hasMessages(SET_GAME_STATE)); } private List<String> readGameModeInterventionList() throws Exception { final File interventionFile = new File(InstrumentationRegistry.getContext().getFilesDir(), "system/game_mode_intervention.list"); Loading Loading @@ -1823,6 +1858,21 @@ public class GameManagerServiceTests { }); } @Test public void testUpdateCustomGameModeConfiguration_nonGame() throws Exception { mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_IMAGE); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.updateCustomGameModeConfiguration(mPackageName, new GameModeConfiguration.Builder().setScalingFactor(0.35f).setFpsOverride( 60).build(), USER_ID_1); assertFalse(gameManagerService.mHandler.hasMessages(WRITE_SETTINGS)); GameManagerService.GamePackageConfiguration pkgConfig = gameManagerService.getConfig( mPackageName, USER_ID_1); assertNull(pkgConfig); } @Test public void testWritingSettingFile_onShutdown() throws InterruptedException { mockModifyGameModeGranted(); Loading Loading @@ -1983,4 +2033,111 @@ public class GameManagerServiceTests { } folder.delete(); } @Test public void testNotifyGraphicsEnvironmentSetup() { String configString = "mode=2,loadingBoost=2000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, true); reset(mMockPowerManager); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(2000); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); } @Test public void testNotifyGraphicsEnvironmentSetup_outOfBoundBoostValue() { String configString = "mode=2,loadingBoost=0:mode=3,loadingBoost=7000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, true); reset(mMockPowerManager); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(100); mTestLooper.dispatchAll(); // 0 loading boost value should still trigger max timeout verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(LOADING_BOOST_MAX_DURATION); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); reset(mMockPowerManager); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); // 7000 loading boost value should exceed the max timeout of 5s and be bounded gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, true); reset(mMockPowerManager); assertTrue(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); mTestLooper.moveTimeForward(LOADING_BOOST_MAX_DURATION); mTestLooper.dispatchAll(); verify(mMockPowerManager, times(1)).setPowerMode(Mode.GAME_LOADING, false); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_noDeviceConfig() { mockDeviceConfigNone(); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_noLoadingBoostValue() { mockDeviceConfigAll(); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_nonGame() throws Exception { String configString = "mode=2,loadingBoost=2000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); mockAppCategory(mPackageName, ApplicationInfo.CATEGORY_IMAGE); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); assertEquals(GameManager.GAME_MODE_UNSUPPORTED, gameManagerService.getGameMode(mPackageName, USER_ID_1)); gameManagerService.notifyGraphicsEnvironmentSetup(mPackageName, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } @Test public void testNotifyGraphicsEnvironmentSetup_differentApp() throws Exception { String configString = "mode=2,loadingBoost=2000"; when(DeviceConfig.getProperty(anyString(), anyString())) .thenReturn(configString); mockModifyGameModeGranted(); GameManagerService gameManagerService = createServiceAndStartUser(USER_ID_1); String someGamePkg = "some.game"; mockAppCategory(someGamePkg, ApplicationInfo.CATEGORY_GAME); when(mMockPackageManager.getPackageUidAsUser(someGamePkg, USER_ID_1)).thenReturn( DEFAULT_PACKAGE_UID + 1); gameManagerService.setGameMode(someGamePkg, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1); assertEquals(GameManager.GAME_MODE_PERFORMANCE, gameManagerService.getGameMode(someGamePkg, USER_ID_1)); gameManagerService.notifyGraphicsEnvironmentSetup(someGamePkg, USER_ID_1); verify(mMockPowerManager, never()).setPowerMode(anyInt(), anyBoolean()); assertFalse(gameManagerService.mHandler.hasMessages(CANCEL_GAME_LOADING_MODE)); } }