Merge changes I4adae903,I17f973dd
* changes: Update `set` and add `list-modes` adb shell game commands Persist custom game mode configuration in settings
This commit is contained in:
@@ -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<Integer, GameManagerSettings> 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) {
|
||||
|
||||
@@ -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:
|
||||
// <?xml>
|
||||
// <packages>
|
||||
// <package></package>
|
||||
// <package name="" gameMode="">
|
||||
// <gameModeConfig gameMode="" fps="" scaling="" useAngle="" loadingBoost="">
|
||||
// </gameModeConfig>
|
||||
// ...
|
||||
// </package>
|
||||
// ...
|
||||
// </packages>
|
||||
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<String, Integer> entry : mGameModes.entrySet()) {
|
||||
String packageName = entry.getKey();
|
||||
final ArraySet<String> 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);
|
||||
|
||||
@@ -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 {
|
||||
* <PACKAGE_NAME> <CONFIG_STRING>`
|
||||
* 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 <USER_ID>] [1|2|3|standard|performance|battery] <PACKAGE_NAME>");
|
||||
pw.println(" Deprecated. Please use `custom` command.");
|
||||
pw.println(" list-configs <PACKAGE_NAME>");
|
||||
pw.println(" Lists the current intervention configs of an app.");
|
||||
pw.println(" list-modes <PACKAGE_NAME>");
|
||||
pw.println(" Lists the current available game modes of an app.");
|
||||
pw.println(" mode [--user <USER_ID>] [1|2|3|4|standard|performance|battery|custom] "
|
||||
+ "<PACKAGE_NAME>");
|
||||
pw.println(" Set app to run in the specified game mode, if supported.");
|
||||
pw.println(" --user <USER_ID>: apply for the given user,");
|
||||
pw.println(" the current user is used when unspecified.");
|
||||
pw.println(" set --mode [2|3|performance|battery] [intervention configs] <PACKAGE_NAME>");
|
||||
pw.println(" Set app to run at given game mode with configs, if supported.");
|
||||
pw.println(" set [intervention configs] <PACKAGE_NAME>");
|
||||
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 <USER_ID>] <PACKAGE_NAME>");
|
||||
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 <USER_ID>: apply for the given user,");
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"),
|
||||
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<packages>\n"
|
||||
+ " <package name=\"com.android.app1\" gameMode=\"1\">\n"
|
||||
+ " </package>\n"
|
||||
+ "<packages>"
|
||||
+ "\n" // app1: no package config setting
|
||||
+ "\n" // app2: performance mode is selected with override
|
||||
+ " <package name=\"com.android.app2\" gameMode=\"2\">\n"
|
||||
+ " <gameModeConfig gameMode=\"2\" scaling=\"0.99\" "
|
||||
+ "useAngle=\"true\" fps=\"90\" loadingBoost=\"123\"></gameModeConfig>\n"
|
||||
+ " <gameModeConfig gameMode=\"3\"></gameModeConfig>\n"
|
||||
+ " </package>\n"
|
||||
+ " </package>"
|
||||
+ "\n" // app3: only battery mode is selected
|
||||
+ " <package name=\"com.android.app3\" gameMode=\"3\">\n"
|
||||
+ " </package>\n"
|
||||
+ " </package>"
|
||||
+ "\n" // app4: no game mode selected but custom game mode config
|
||||
+ " <package name=\"com.android.app4\">\n"
|
||||
+ " <gameModeConfig gameMode=\"4\" scaling=\"0.4\" "
|
||||
+ "fps=\"30\"></gameModeConfig>\n"
|
||||
+ " </package>"
|
||||
+ "\n"
|
||||
+ "</packages>\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"),
|
||||
("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
|
||||
+ "<packages>\n"
|
||||
+ "<packages>"
|
||||
+ "\n" // missing package name
|
||||
+ " <package gameMode=\"1\">\n"
|
||||
+ " </package>\n"
|
||||
+ " </package>"
|
||||
+ "\n" // app2 with unknown sub element
|
||||
+ " <package name=\"com.android.app2\" gameMode=\"2\">\n"
|
||||
+ " <unknown></unknown>"
|
||||
+ " <gameModeConfig gameMode=\"3\" fps=\"90\"></gameModeConfig>\n"
|
||||
+ " foo bar"
|
||||
+ " </package>\n"
|
||||
+ " </package>"
|
||||
+ "\n" // unknown package element
|
||||
+ " <unknownTag></unknownTag>\n"
|
||||
+ " foo bar\n"
|
||||
+ " foo bar"
|
||||
+ "\n" // app3 after unknown element
|
||||
+ " <package name=\"com.android.app3\" gameMode=\"3\">\n"
|
||||
+ " </package>\n"
|
||||
+ "</packages>\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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user