Merge "Ensure the game mode setting doesn't conflict with available modes" into sc-dev am: 6b843a1b8c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14457704

Change-Id: I7448d7f57921c2fe7f8c6951822712fee79fd322
This commit is contained in:
TreeHugger Robot
2021-05-19 19:43:00 +00:00
committed by Automerger Merge Worker
2 changed files with 132 additions and 21 deletions

View File

@@ -56,7 +56,6 @@ import android.os.ShellCallback;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.KeyValueListParser;
import android.util.Slog;
@@ -363,19 +362,42 @@ public final class GameManagerService extends IGameManagerService.Stub {
|| (mPerfModeOptedIn && gameMode == GameManager.GAME_MODE_PERFORMANCE);
}
public @GameMode int[] getAvailableGameModes() {
ArraySet<Integer> modeSet = new ArraySet<>(mModeConfigs.keySet());
private int getAvailableGameModesBitfield() {
int field = 0;
for (final int mode : mModeConfigs.keySet()) {
field |= modeToBitmask(mode);
}
if (mBatteryModeOptedIn) {
modeSet.add(GameManager.GAME_MODE_BATTERY);
field |= modeToBitmask(GameManager.GAME_MODE_BATTERY);
}
if (mPerfModeOptedIn) {
modeSet.add(GameManager.GAME_MODE_PERFORMANCE);
field |= modeToBitmask(GameManager.GAME_MODE_PERFORMANCE);
}
if (modeSet.size() > 0) {
modeSet.add(GameManager.GAME_MODE_STANDARD);
return modeSet.stream().mapToInt(Integer::intValue).toArray();
// The lowest bit is reserved for UNSUPPORTED, STANDARD is supported if we support any
// other mode.
if (field > 1) {
field |= modeToBitmask(GameManager.GAME_MODE_STANDARD);
} else {
field |= modeToBitmask(GameManager.GAME_MODE_UNSUPPORTED);
}
return new int[]{GameManager.GAME_MODE_UNSUPPORTED};
return field;
}
/**
* Get an array of a package's available game modes.
*/
public @GameMode int[] getAvailableGameModes() {
int modesBitfield = getAvailableGameModesBitfield();
int sigBits = Integer.bitCount(modesBitfield);
int[] modes = new int[sigBits];
int i = 0;
for (int mode = 0; mode < sigBits; ++mode) {
if (((modesBitfield >> mode) & 1) != 0) {
modes[i++] = mode;
}
}
return modes;
}
/**
@@ -696,6 +718,14 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
}
private int modeToBitmask(@GameMode int gameMode) {
return (1 << gameMode);
}
private boolean bitFieldContainsModeBitmask(int bitField, @GameMode int gameMode) {
return (bitField & modeToBitmask(gameMode)) != 0;
}
/**
* @hide
*/
@@ -703,8 +733,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
public void updateConfigsForUser(int userId, String ...packageNames) {
try {
synchronized (mDeviceConfigLock) {
for (String packageName : packageNames) {
GamePackageConfiguration config =
for (final String packageName : packageNames) {
final GamePackageConfiguration config =
new GamePackageConfiguration(packageName, userId);
if (config.isValid()) {
if (DEBUG) {
@@ -718,13 +748,42 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
}
}
for (String packageName : packageNames) {
synchronized (mLock) {
if (mSettings.containsKey(userId)) {
GameManagerSettings userSettings = mSettings.get(userId);
updateCompatModeDownscale(packageName,
userSettings.getGameModeLocked(packageName));
for (final String packageName : packageNames) {
if (mSettings.containsKey(userId)) {
int gameMode = getGameMode(packageName, userId);
int newGameMode = gameMode;
// Make sure the user settings and package configs don't conflict. I.e. the
// user setting is set to a mode that no longer available due to config/manifest
// changes. Most of the time we won't have to change anything.
GamePackageConfiguration config;
synchronized (mDeviceConfigLock) {
config = mConfigs.get(packageName);
}
if (config != null) {
int modesBitfield = config.getAvailableGameModesBitfield();
// Remove UNSUPPORTED to simplify the logic here, since we really just
// want to check if we support selectable game modes
modesBitfield &= ~modeToBitmask(GameManager.GAME_MODE_UNSUPPORTED);
if (!bitFieldContainsModeBitmask(modesBitfield, gameMode)) {
if (bitFieldContainsModeBitmask(modesBitfield,
GameManager.GAME_MODE_STANDARD)) {
// If the current set mode isn't supported, but we support STANDARD,
// then set the mode to STANDARD.
newGameMode = GameManager.GAME_MODE_STANDARD;
} else {
// If we don't support any game modes, then set to UNSUPPORTED
newGameMode = GameManager.GAME_MODE_UNSUPPORTED;
}
}
} else if (gameMode != GameManager.GAME_MODE_UNSUPPORTED) {
// If we have no config for the package, but the configured mode is not
// UNSUPPORTED, then set to UNSUPPORTED
newGameMode = GameManager.GAME_MODE_UNSUPPORTED;
}
if (newGameMode != gameMode) {
setGameMode(packageName, newGameMode, userId);
}
updateCompatModeDownscale(packageName, gameMode);
}
}
} catch (Exception e) {

View File

@@ -299,11 +299,13 @@ public class GameManagerServiceTests {
public void testGameMode() {
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
mockModifyGameModeGranted();
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
// We need to make sure the mode is supported before setting it.
mockDeviceConfigAll();
gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
@@ -370,11 +372,13 @@ public class GameManagerServiceTests {
*/
@Test
public void testGameModeMultipleUsers() {
mockModifyGameModeGranted();
mockDeviceConfigAll();
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
gameManagerService.onUserStarting(USER_ID_2);
mockModifyGameModeGranted();
gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
gameManagerService.updateConfigsForUser(USER_ID_2, mPackageName);
// Set User 1 to Standard
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_STANDARD, USER_ID_1);
@@ -603,4 +607,52 @@ public class GameManagerServiceTests {
gameManagerService.getConfig(mPackageName);
assertNull(config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE));
}
/**
* Ensure that, if a game no longer supports any game modes, we set the game mode to
* UNSUPPORTED
*/
@Test
public void testUnsetInvalidGameMode() throws Exception {
mockDeviceConfigNone();
mockModifyGameModeGranted();
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
assertEquals(GameManager.GAME_MODE_UNSUPPORTED,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
}
/**
* Ensure that, if a game no longer supports a specific game mode, but supports STANDARD, we set
* the game mode to STANDARD.
*/
@Test
public void testResetInvalidGameMode() throws Exception {
mockDeviceConfigPerformance();
mockModifyGameModeGranted();
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_BATTERY, USER_ID_1);
gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
}
/**
* Ensure that if a game supports STANDARD, but is currently set to UNSUPPORTED, we set the game
* mode to STANDARD
*/
@Test
public void testSetValidGameMode() throws Exception {
mockDeviceConfigPerformance();
mockModifyGameModeGranted();
GameManagerService gameManagerService = new GameManagerService(mMockContext);
gameManagerService.onUserStarting(USER_ID_1);
gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_UNSUPPORTED, USER_ID_1);
gameManagerService.updateConfigsForUser(USER_ID_1, mPackageName);
assertEquals(GameManager.GAME_MODE_STANDARD,
gameManagerService.getGameMode(mPackageName, USER_ID_1));
}
}