summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/GameManagerInternal.java30
-rw-r--r--core/java/android/app/IGameManagerService.aidl2
-rw-r--r--services/core/java/com/android/server/app/GameManagerService.java292
-rw-r--r--services/core/java/com/android/server/app/GameManagerShellCommand.java79
-rw-r--r--services/core/java/com/android/server/wm/CompatModePackages.java15
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java129
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java95
7 files changed, 378 insertions, 264 deletions
diff --git a/core/java/android/app/GameManagerInternal.java b/core/java/android/app/GameManagerInternal.java
new file mode 100644
index 000000000000..c8ff2a84a536
--- /dev/null
+++ b/core/java/android/app/GameManagerInternal.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+/**
+ * Game manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+
+public abstract class GameManagerInternal {
+ /**
+ * Used by the CompatModePackages to read game's compat scaling override.
+ */
+ public abstract float getResolutionScalingFactor(String packageName, int userId);
+}
diff --git a/core/java/android/app/IGameManagerService.aidl b/core/java/android/app/IGameManagerService.aidl
index e60a74acdc1c..481e7b0050ab 100644
--- a/core/java/android/app/IGameManagerService.aidl
+++ b/core/java/android/app/IGameManagerService.aidl
@@ -31,4 +31,6 @@ interface IGameManagerService {
void setGameState(String packageName, in GameState gameState, int userId);
GameModeInfo getGameModeInfo(String packageName, int userId);
void setGameServiceProvider(String packageName);
+ void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor, int userId);
+ float getResolutionScalingFactor(String packageName, int gameMode, int userId);
}
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index d5e893984bf3..854b818c095f 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -25,20 +25,6 @@ import static com.android.internal.R.styleable.GameModeConfig_allowGameDownscali
import static com.android.internal.R.styleable.GameModeConfig_allowGameFpsOverride;
import static com.android.internal.R.styleable.GameModeConfig_supportsBatteryGameMode;
import static com.android.internal.R.styleable.GameModeConfig_supportsPerformanceGameMode;
-import static com.android.server.wm.CompatModePackages.DOWNSCALED;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;
import android.Manifest;
import android.annotation.NonNull;
@@ -48,10 +34,10 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.GameManager;
import android.app.GameManager.GameMode;
+import android.app.GameManagerInternal;
import android.app.GameModeInfo;
import android.app.GameState;
import android.app.IGameManagerService;
-import android.app.compat.PackageOverride;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -75,9 +61,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManagerInternal;
import android.os.Process;
-import android.os.RemoteException;
import android.os.ResultReceiver;
-import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.UserManager;
import android.provider.DeviceConfig;
@@ -92,8 +76,6 @@ import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.compat.CompatibilityOverrideConfig;
-import com.android.internal.compat.IPlatformCompat;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
@@ -140,10 +122,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
static final int WRITE_SETTINGS_DELAY = 10 * 1000; // 10 seconds
static final int LOADING_BOOST_MAX_DURATION = 5 * 1000; // 5 seconds
- static final PackageOverride COMPAT_ENABLED = new PackageOverride.Builder().setEnabled(true)
- .build();
- static final PackageOverride COMPAT_DISABLED = new PackageOverride.Builder().setEnabled(false)
- .build();
private static final String PACKAGE_NAME_MSG_KEY = "packageName";
private static final String USER_ID_MSG_KEY = "userId";
private static final String GAME_MODE_INTERVENTION_LIST_FILE_NAME =
@@ -156,7 +134,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
private final Handler mHandler;
private final PackageManager mPackageManager;
private final UserManager mUserManager;
- private final IPlatformCompat mPlatformCompat;
private final PowerManagerInternal mPowerManagerInternal;
private final File mSystemDir;
@VisibleForTesting
@@ -180,8 +157,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
mHandler = new SettingsHandler(looper);
mPackageManager = mContext.getPackageManager();
mUserManager = mContext.getSystemService(UserManager.class);
- mPlatformCompat = IPlatformCompat.Stub.asInterface(
- ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mSystemDir = new File(Environment.getDataDirectory(), "system");
mSystemDir.mkdirs();
@@ -212,8 +187,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
mHandler = new SettingsHandler(looper);
mPackageManager = mContext.getPackageManager();
mUserManager = mContext.getSystemService(UserManager.class);
- mPlatformCompat = IPlatformCompat.Stub.asInterface(
- ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
@@ -326,10 +299,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
break;
}
case POPULATE_GAME_MODE_SETTINGS: {
- // Scan all game packages and re-enforce the configured compat mode overrides
- // as the DeviceConfig may have be wiped/since last reboot and we can't risk
- // having overrides configured for packages that no longer have any DeviceConfig
- // and thus any way to escape compat mode.
removeMessages(POPULATE_GAME_MODE_SETTINGS, msg.obj);
final int userId = (int) msg.obj;
final String[] packageNames = getInstalledGamePackageNames(userId);
@@ -412,39 +381,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
}
- // Turn the raw string to the corresponding CompatChange id.
- static long getCompatChangeId(String raw) {
- switch (raw) {
- case "0.3":
- return DOWNSCALE_30;
- case "0.35":
- return DOWNSCALE_35;
- case "0.4":
- return DOWNSCALE_40;
- case "0.45":
- return DOWNSCALE_45;
- case "0.5":
- return DOWNSCALE_50;
- case "0.55":
- return DOWNSCALE_55;
- case "0.6":
- return DOWNSCALE_60;
- case "0.65":
- return DOWNSCALE_65;
- case "0.7":
- return DOWNSCALE_70;
- case "0.75":
- return DOWNSCALE_75;
- case "0.8":
- return DOWNSCALE_80;
- case "0.85":
- return DOWNSCALE_85;
- case "0.9":
- return DOWNSCALE_90;
- }
- return 0;
- }
-
public enum FrameRate {
FPS_DEFAULT(0),
FPS_30(30),
@@ -649,6 +585,13 @@ public final class GameManagerService extends IGameManagerService.Stub {
return xmlFound;
}
+ GameModeConfiguration getOrAddDefaultGameModeConfiguration(int gameMode) {
+ synchronized (mModeConfigLock) {
+ mModeConfigs.putIfAbsent(gameMode, new GameModeConfiguration(gameMode));
+ return mModeConfigs.get(gameMode);
+ }
+ }
+
/**
* GameModeConfiguration contains all the values for all the interventions associated with
* a game mode.
@@ -659,17 +602,26 @@ public final class GameManagerService extends IGameManagerService.Stub {
public static final String MODE_KEY = "mode";
public static final String SCALING_KEY = "downscaleFactor";
public static final String FPS_KEY = "fps";
- public static final String DEFAULT_SCALING = "1.0";
- public static final String DEFAULT_FPS = "";
public static final String ANGLE_KEY = "useAngle";
public static final String LOADING_BOOST_KEY = "loadingBoost";
+ public static final float DEFAULT_SCALING = -1f;
+ public static final String DEFAULT_FPS = "";
+ public static final boolean DEFAULT_USE_ANGLE = false;
+ public static final int DEFAULT_LOADING_BOOST_DURATION = -1;
+
private final @GameMode int mGameMode;
- private String mScaling;
- private String mFps;
+ private float mScaling = DEFAULT_SCALING;
+ private String mFps = DEFAULT_FPS;
private final boolean mUseAngle;
private final int mLoadingBoostDuration;
+ GameModeConfiguration(int gameMode) {
+ mGameMode = gameMode;
+ mUseAngle = DEFAULT_USE_ANGLE;
+ mLoadingBoostDuration = DEFAULT_LOADING_BOOST_DURATION;
+ }
+
GameModeConfiguration(KeyValueListParser parser) {
mGameMode = parser.getInt(MODE_KEY, GameManager.GAME_MODE_UNSUPPORTED);
// isGameModeOptedIn() returns if an app will handle all of the changes necessary
@@ -677,7 +629,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
// GameManagerService) will not do anything for the app (like window scaling or
// using ANGLE).
mScaling = !mAllowDownscale || willGamePerformOptimizations(mGameMode)
- ? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING);
+ ? DEFAULT_SCALING : parser.getFloat(SCALING_KEY, DEFAULT_SCALING);
mFps = mAllowFpsOverride && !willGamePerformOptimizations(mGameMode)
? parser.getString(FPS_KEY, DEFAULT_FPS) : DEFAULT_FPS;
@@ -686,17 +638,18 @@ public final class GameManagerService extends IGameManagerService.Stub {
// - The app has not opted in to performing the work itself AND
// - The Phenotype config has enabled it.
mUseAngle = mAllowAngle && !willGamePerformOptimizations(mGameMode)
- && parser.getBoolean(ANGLE_KEY, false);
+ && parser.getBoolean(ANGLE_KEY, DEFAULT_USE_ANGLE);
- mLoadingBoostDuration = willGamePerformOptimizations(mGameMode) ? -1
- : parser.getInt(LOADING_BOOST_KEY, -1);
+ mLoadingBoostDuration = willGamePerformOptimizations(mGameMode)
+ ? DEFAULT_LOADING_BOOST_DURATION
+ : parser.getInt(LOADING_BOOST_KEY, DEFAULT_LOADING_BOOST_DURATION);
}
public int getGameMode() {
return mGameMode;
}
- public synchronized String getScaling() {
+ public synchronized float getScaling() {
return mScaling;
}
@@ -712,7 +665,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
return mLoadingBoostDuration;
}
- public synchronized void setScaling(String scaling) {
+ public synchronized void setScaling(float scaling) {
mScaling = scaling;
}
@@ -735,13 +688,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
+ mUseAngle + ",Fps:" + mFps + ",Loading Boost Duration:"
+ mLoadingBoostDuration + "]";
}
-
- /**
- * Get the corresponding compat change id for the current scaling string.
- */
- public long getCompatChangeId() {
- return GameManagerService.getCompatChangeId(mScaling);
- }
}
public String getPackageName() {
@@ -813,7 +759,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
/**
- * Insert a new GameModeConfiguration
+ * Inserts a new GameModeConfiguration
*/
public void addModeConfig(GameModeConfiguration config) {
if (config.isActive()) {
@@ -839,6 +785,14 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
}
+ private final class LocalService extends GameManagerInternal {
+ @Override
+ public float getResolutionScalingFactor(String packageName, int userId) {
+ final int gameMode = getGameModeFromSettings(packageName, userId);
+ return getResolutionScalingFactorInternal(packageName, gameMode, userId);
+ }
+ }
+
/**
* SystemService lifecycle for GameService.
*
@@ -849,13 +803,13 @@ public final class GameManagerService extends IGameManagerService.Stub {
public Lifecycle(Context context) {
super(context);
+ mService = new GameManagerService(context);
}
@Override
public void onStart() {
- final Context context = getContext();
- mService = new GameManagerService(context);
publishBinderService(Context.GAME_SERVICE, mService);
+ mService.publishLocalService();
mService.registerDeviceConfigListener();
mService.registerPackageReceiver();
}
@@ -937,8 +891,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
private @GameMode int getGameModeFromSettings(String packageName, @UserIdInt int userId) {
synchronized (mLock) {
if (!mSettings.containsKey(userId)) {
- Slog.w(TAG, "User ID '" + userId + "' does not have a Game Mode"
- + " selected for package: '" + packageName + "'");
+ Slog.d(TAG, "User ID '" + userId + "' does not have a Game Mode"
+ + " selected for package: '" + packageName + "'");
return GameManager.GAME_MODE_UNSUPPORTED;
}
@@ -1163,6 +1117,66 @@ public final class GameManagerService extends IGameManagerService.Stub {
mGameServiceController.setGameServiceProvider(packageName);
}
+
+ /**
+ * Updates the resolution scaling factor for the package's target game mode and activates it.
+ *
+ * @param scalingFactor enable scaling override over any other compat scaling if positive,
+ * or disable the override otherwise
+ * @throws SecurityException if caller doesn't have
+ * {@link android.Manifest.permission#MANAGE_GAME_MODE}
+ * permission.
+ * @throws IllegalArgumentException if the user ID provided doesn't exist.
+ */
+ @Override
+ @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
+ public void updateResolutionScalingFactor(String packageName, int gameMode, float scalingFactor,
+ int userId) throws SecurityException, IllegalArgumentException {
+ checkPermission(Manifest.permission.MANAGE_GAME_MODE);
+ synchronized (mLock) {
+ if (!mSettings.containsKey(userId)) {
+ throw new IllegalArgumentException("User " + userId + " wasn't started");
+ }
+ }
+ setGameModeConfigOverride(packageName, userId, gameMode, null /*fpsStr*/,
+ Float.toString(scalingFactor));
+ }
+
+ /**
+ * Gets the resolution scaling factor for the package's target game mode.
+ *
+ * @return scaling factor for the game mode if exists or negative value otherwise.
+ * @throws SecurityException if caller doesn't have
+ * {@link android.Manifest.permission#MANAGE_GAME_MODE}
+ * permission.
+ * @throws IllegalArgumentException if the user ID provided doesn't exist.
+ */
+ @Override
+ @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
+ public float getResolutionScalingFactor(String packageName, int gameMode, int userId)
+ throws SecurityException, IllegalArgumentException {
+ checkPermission(Manifest.permission.MANAGE_GAME_MODE);
+ synchronized (mLock) {
+ if (!mSettings.containsKey(userId)) {
+ throw new IllegalArgumentException("User " + userId + " wasn't started");
+ }
+ }
+ return getResolutionScalingFactorInternal(packageName, gameMode, userId);
+ }
+
+ float getResolutionScalingFactorInternal(String packageName, int gameMode, int userId) {
+ final GamePackageConfiguration packageConfig = getConfig(packageName);
+ if (packageConfig == null) {
+ return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
+ }
+ final GamePackageConfiguration.GameModeConfiguration modeConfig =
+ packageConfig.getGameModeConfiguration(gameMode);
+ if (modeConfig != null) {
+ return modeConfig.getScaling();
+ }
+ return GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING;
+ }
+
/**
* Notified when boot is completed.
*/
@@ -1239,28 +1253,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
/**
- * @hide
- */
- @VisibleForTesting
- public void disableCompatScale(String packageName) {
- final long uid = Binder.clearCallingIdentity();
- try {
- Slog.i(TAG, "Disabling downscale for " + packageName);
- final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
- overrides.put(DOWNSCALED, COMPAT_DISABLED);
- final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
- overrides);
- try {
- mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
- }
- } finally {
- Binder.restoreCallingIdentity(uid);
- }
- }
-
- /**
* Remove frame rate override due to mode switch
*/
private void resetFps(String packageName, @UserIdInt int userId) {
@@ -1273,60 +1265,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
}
- private void enableCompatScale(String packageName, long scaleId) {
- final long uid = Binder.clearCallingIdentity();
- try {
- Slog.i(TAG, "Enabling downscale: " + scaleId + " for " + packageName);
- final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
- overrides.put(DOWNSCALED, COMPAT_ENABLED);
- overrides.put(DOWNSCALE_30, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_35, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_40, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_45, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_50, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_55, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_60, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_65, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_70, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_75, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_80, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_85, COMPAT_DISABLED);
- overrides.put(DOWNSCALE_90, COMPAT_DISABLED);
- overrides.put(scaleId, COMPAT_ENABLED);
- final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
- overrides);
- try {
- mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
- }
- } finally {
- Binder.restoreCallingIdentity(uid);
- }
- }
-
- private void updateCompatModeDownscale(GamePackageConfiguration packageConfig,
- String packageName, @GameMode int gameMode) {
-
- if (DEBUG) {
- Slog.v(TAG, dumpDeviceConfigs());
- }
- final GamePackageConfiguration.GameModeConfiguration modeConfig =
- packageConfig.getGameModeConfiguration(gameMode);
- if (modeConfig == null) {
- Slog.i(TAG, "Game mode " + gameMode + " not found for " + packageName);
- return;
- }
- long scaleId = modeConfig.getCompatChangeId();
- if (scaleId == 0) {
- Slog.w(TAG, "Invalid downscaling change id " + scaleId + " for "
- + packageName);
- return;
- }
-
- enableCompatScale(packageName, scaleId);
- }
-
private int modeToBitmask(@GameMode int gameMode) {
return (1 << gameMode);
}
@@ -1364,20 +1302,17 @@ public final class GameManagerService extends IGameManagerService.Stub {
@GameMode int gameMode, @UserIdInt int userId) {
if (gameMode == GameManager.GAME_MODE_STANDARD
|| gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
- disableCompatScale(packageName);
resetFps(packageName, userId);
return;
}
final GamePackageConfiguration packageConfig = getConfig(packageName);
if (packageConfig == null) {
- disableCompatScale(packageName);
Slog.v(TAG, "Package configuration not found for " + packageName);
return;
}
if (packageConfig.willGamePerformOptimizations(gameMode)) {
return;
}
- updateCompatModeDownscale(packageConfig, packageName, gameMode);
updateFps(packageConfig, packageName, gameMode, userId);
updateUseAngle(packageName, gameMode);
}
@@ -1408,7 +1343,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
// modify GameModeConfiguration intervention settings
GamePackageConfiguration.GameModeConfiguration overrideModeConfig =
- overrideConfig.getGameModeConfiguration(gameMode);
+ overrideConfig.getOrAddDefaultGameModeConfiguration(gameMode);
if (fpsStr != null) {
overrideModeConfig.setFpsStr(fpsStr);
@@ -1417,10 +1352,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
GamePackageConfiguration.GameModeConfiguration.DEFAULT_FPS);
}
if (scaling != null) {
- overrideModeConfig.setScaling(scaling);
- } else {
- overrideModeConfig.setScaling(
- GamePackageConfiguration.GameModeConfiguration.DEFAULT_SCALING);
+ overrideModeConfig.setScaling(Float.parseFloat(scaling));
}
Slog.i(TAG, "Package Name: " + packageName
+ " FPS: " + String.valueOf(overrideModeConfig.getFps())
@@ -1470,7 +1402,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
// If the game mode to reset is the only mode other than standard mode,
- // The override config is removed.
+ // the override config is removed.
if (modes.length <= 2) {
synchronized (mOverrideConfigLock) {
mOverrideConfigs.remove(packageName);
@@ -1595,7 +1527,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
}
}
} catch (Exception e) {
- Slog.e(TAG, "Failed to update compat modes for user " + userId + ": " + e);
+ Slog.e(TAG, "Failed to update configs for user " + userId + ": " + e);
}
final Message msg = mHandler.obtainMessage(WRITE_GAME_MODE_INTERVENTION_LIST_FILE);
@@ -1646,7 +1578,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
final int useAngle = gameModeConfiguration.getUseAngle() ? 1 : 0;
sb.append(TextUtils.formatSimple("angle=%d", useAngle));
sb.append(",");
- final String scaling = gameModeConfiguration.getScaling();
+ final float scaling = gameModeConfiguration.getScaling();
sb.append("scaling=");
sb.append(scaling);
sb.append(",");
@@ -1746,14 +1678,6 @@ public final class GameManagerService extends IGameManagerService.Stub {
updateConfigsForUser(userId, true /*checkGamePackage*/, packageName);
break;
case ACTION_PACKAGE_REMOVED:
- disableCompatScale(packageName);
- // If EXTRA_REPLACING is true, it means there will be an
- // ACTION_PACKAGE_ADDED triggered after this because this
- // is an updated package that gets installed. Hence, disable
- // resolution downscaling effort but avoid removing the server
- // or commandline overriding configurations because those will
- // not change but the package game mode configurations may change
- // which may opt in and/or opt out some game mode configurations.
if (!intent.getBooleanExtra(EXTRA_REPLACING, false)) {
synchronized (mOverrideConfigLock) {
mOverrideConfigs.remove(packageName);
@@ -1785,6 +1709,10 @@ public final class GameManagerService extends IGameManagerService.Stub {
mDeviceConfigListener = new DeviceConfigListener();
}
+ private void publishLocalService() {
+ LocalServices.addService(GameManagerInternal.class, new LocalService());
+ }
+
private String dumpDeviceConfigs() {
StringBuilder out = new StringBuilder();
for (String key : mConfigs.keySet()) {
diff --git a/services/core/java/com/android/server/app/GameManagerShellCommand.java b/services/core/java/com/android/server/app/GameManagerShellCommand.java
index 470c320dbd7d..487d19aa6aba 100644
--- a/services/core/java/com/android/server/app/GameManagerShellCommand.java
+++ b/services/core/java/com/android/server/app/GameManagerShellCommand.java
@@ -16,21 +16,6 @@
package com.android.server.app;
-import static com.android.server.wm.CompatModePackages.DOWNSCALED;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_30;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_35;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_40;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_45;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_50;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_55;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_60;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_65;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_70;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_75;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_80;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_85;
-import static com.android.server.wm.CompatModePackages.DOWNSCALE_90;
-
import android.app.ActivityManager;
import android.app.GameManager;
import android.app.IGameManagerService;
@@ -39,7 +24,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.ShellCommand;
-import android.util.ArraySet;
import java.io.PrintWriter;
import java.util.Locale;
@@ -53,23 +37,6 @@ public class GameManagerShellCommand extends ShellCommand {
public GameManagerShellCommand() {}
- private static final ArraySet<Long> DOWNSCALE_CHANGE_IDS = new ArraySet<>(new Long[]{
- DOWNSCALED,
- DOWNSCALE_90,
- DOWNSCALE_85,
- DOWNSCALE_80,
- DOWNSCALE_75,
- DOWNSCALE_70,
- DOWNSCALE_65,
- DOWNSCALE_60,
- DOWNSCALE_55,
- DOWNSCALE_50,
- DOWNSCALE_45,
- DOWNSCALE_40,
- DOWNSCALE_35,
- DOWNSCALE_30,
- });
-
@Override
public int onCommand(String cmd) {
if (cmd == null) {
@@ -212,11 +179,15 @@ public class GameManagerShellCommand extends ShellCommand {
case "--downscale":
if (downscaleRatio == null) {
downscaleRatio = getNextArgRequired();
- if (downscaleRatio != null
- && GameManagerService.getCompatChangeId(downscaleRatio) == 0
- && !downscaleRatio.equals("disable")) {
- pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
- return -1;
+ if ("disable".equals(downscaleRatio)) {
+ downscaleRatio = "-1";
+ } else {
+ try {
+ Float.parseFloat(downscaleRatio);
+ } catch (NumberFormatException e) {
+ pw.println("Invalid scaling ratio '" + downscaleRatio + "'");
+ return -1;
+ }
}
} else {
pw.println("Duplicate option '" + option + "'");
@@ -249,40 +220,16 @@ public class GameManagerShellCommand extends ShellCommand {
final GameManagerService gameManagerService = (GameManagerService)
ServiceManager.getService(Context.GAME_SERVICE);
- boolean batteryModeSupported = false;
- boolean perfModeSupported = false;
- int [] modes = gameManagerService.getAvailableGameModes(packageName);
-
- for (int mode : modes) {
- if (mode == GameManager.GAME_MODE_PERFORMANCE) {
- perfModeSupported = true;
- } else if (mode == GameManager.GAME_MODE_BATTERY) {
- batteryModeSupported = true;
- }
- }
-
switch (gameMode.toLowerCase(Locale.getDefault())) {
case "2":
case "performance":
- if (perfModeSupported) {
- gameManagerService.setGameModeConfigOverride(packageName, userId,
- GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
- } else {
- pw.println("Game mode: " + gameMode + " not supported by "
- + packageName);
- return -1;
- }
+ gameManagerService.setGameModeConfigOverride(packageName, userId,
+ GameManager.GAME_MODE_PERFORMANCE, fpsStr, downscaleRatio);
break;
case "3":
case "battery":
- if (batteryModeSupported) {
- gameManagerService.setGameModeConfigOverride(packageName, userId,
- GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
- } else {
- pw.println("Game mode: " + gameMode + " not supported by "
- + packageName);
- return -1;
- }
+ gameManagerService.setGameModeConfigOverride(packageName, userId,
+ GameManager.GAME_MODE_BATTERY, fpsStr, downscaleRatio);
break;
default:
pw.println("Invalid game mode: " + gameMode);
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index 2ea043a5c623..6f1945033af9 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -24,6 +24,7 @@ import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import android.app.ActivityManager;
import android.app.AppGlobals;
+import android.app.GameManagerInternal;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
@@ -48,6 +49,7 @@ import android.util.TypedXmlSerializer;
import android.util.Xml;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.server.LocalServices;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -64,6 +66,7 @@ public final class CompatModePackages {
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private final ActivityTaskManagerService mService;
+ private GameManagerInternal mGameManager;
private final AtomicFile mFile;
// Compatibility state: no longer ask user to select the mode.
@@ -375,6 +378,18 @@ public final class CompatModePackages {
float getCompatScale(String packageName, int uid) {
final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
+ if (mGameManager == null) {
+ mGameManager = LocalServices.getService(GameManagerInternal.class);
+ }
+ if (mGameManager != null) {
+ final int userId = userHandle.getIdentifier();
+ final float scalingFactor = mGameManager.getResolutionScalingFactor(packageName,
+ userId);
+ if (scalingFactor > 0) {
+ return 1f / scalingFactor;
+ }
+ }
+
if (CompatChanges.isChangeEnabled(DOWNSCALED, packageName, userHandle)) {
if (CompatChanges.isChangeEnabled(DOWNSCALE_90, packageName, userHandle)) {
return 1f / 0.9f;
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 d325e47f7687..b53a2c69708d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -201,7 +201,6 @@ public class GameManagerServiceTests {
public void tearDown() throws Exception {
LocalServices.removeServiceForTest(PowerManagerInternal.class);
GameManagerService gameManagerService = new GameManagerService(mMockContext);
- gameManagerService.disableCompatScale(mPackageName);
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
@@ -578,7 +577,7 @@ public class GameManagerServiceTests {
}
private void checkDownscaling(GameManagerService gameManagerService,
- int gameMode, String scaling) {
+ int gameMode, float scaling) {
if (gameManagerService == null) {
gameManagerService = new GameManagerService(mMockContext, mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
@@ -586,7 +585,7 @@ public class GameManagerServiceTests {
}
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
- assertEquals(config.getGameModeConfiguration(gameMode).getScaling(), scaling);
+ assertEquals(scaling, config.getGameModeConfiguration(gameMode).getScaling(), 0.01f);
}
private void checkAngleEnabled(GameManagerService gameManagerService, int gameMode,
@@ -715,7 +714,7 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
}
@@ -735,7 +734,7 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
}
@@ -757,9 +756,9 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
}
@@ -782,7 +781,7 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
}
@@ -805,7 +804,7 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_BATTERY,
GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
}
@@ -829,9 +828,9 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
}
@@ -858,9 +857,9 @@ public class GameManagerServiceTests {
checkReportedModes(gameManagerService, GameManager.GAME_MODE_PERFORMANCE,
GameManager.GAME_MODE_BATTERY, GameManager.GAME_MODE_STANDARD);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, "0.3");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.3f);
checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 120);
- checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, "0.7");
+ checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.7f);
checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
}
@@ -933,7 +932,7 @@ public class GameManagerServiceTests {
public void testInterventionAllowScalingDefault() throws Exception {
mockDeviceConfigPerformance();
mockModifyGameModeGranted();
- checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
}
/**
@@ -944,7 +943,7 @@ public class GameManagerServiceTests {
mockDeviceConfigPerformance();
mockInterventionAllowDownscaleFalse();
mockModifyGameModeGranted();
- checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "1.0");
+ checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, -1.0f);
}
/**
@@ -956,7 +955,7 @@ public class GameManagerServiceTests {
mockDeviceConfigPerformance();
mockInterventionAllowDownscaleTrue();
mockModifyGameModeGranted();
- checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, "0.5");
+ checkDownscaling(null, GameManager.GAME_MODE_PERFORMANCE, 0.5f);
}
/**
@@ -1404,4 +1403,102 @@ public class GameManagerServiceTests {
assertEquals(splitLine[6], "angle=0,scaling=0.7,fps=30");
}
+
+ @Test
+ public void testUpdateResolutionScalingFactor() {
+ mockModifyGameModeGranted();
+ mockDeviceConfigBattery();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ float scalingFactor = 0.123f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ scalingFactor = 0.321f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ }
+
+ @Test
+ public void testUpdateResolutionScalingFactor_noDeviceConfig() {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ float scalingFactor = 0.123f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ scalingFactor = 0.321f;
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ assertEquals(scalingFactor, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY,
+ USER_ID_1), 0.001f);
+ }
+
+ @Test
+ public void testUpdateResolutionScalingFactor_permissionDenied() {
+ mockModifyGameModeDenied();
+ mockDeviceConfigAll();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ float scalingFactor = 0.123f;
+ assertThrows(SecurityException.class, () -> {
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ });
+ mockModifyGameModeGranted();
+ assertEquals(0.7f, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ }
+
+ @Test
+ public void testUpdateResolutionScalingFactor_noUserId() {
+ mockModifyGameModeGranted();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_2);
+ final float scalingFactor = 0.123f;
+ assertThrows(IllegalArgumentException.class, () -> {
+ gameManagerService.updateResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, scalingFactor,
+ USER_ID_1);
+ });
+ }
+
+ @Test
+ public void testGetResolutionScalingFactor_permissionDenied() {
+ mockModifyGameModeDenied();
+ mockDeviceConfigAll();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_1);
+ assertThrows(SecurityException.class, () -> {
+ gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1);
+ });
+ }
+
+ @Test
+ public void testGetResolutionScalingFactor_noUserId() {
+ mockModifyGameModeDenied();
+ mockDeviceConfigAll();
+ GameManagerService gameManagerService =
+ new GameManagerService(mMockContext, mTestLooper.getLooper());
+ startUser(gameManagerService, USER_ID_2);
+ assertEquals(-1f, gameManagerService.getResolutionScalingFactor(mPackageName,
+ GameManager.GAME_MODE_BATTERY, USER_ID_1), 0.001f);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java
new file mode 100644
index 000000000000..1f7b65e8b701
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+
+import android.app.GameManagerInternal;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Tests for the {@link CompatModePackages} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:CompatModePackagesTests
+ */
+@SmallTest
+@Presubmit
+public class CompatModePackagesTests extends SystemServiceTestsBase {
+ ActivityTaskManagerService mAtm;
+ GameManagerInternal mGm;
+ static final String TEST_PACKAGE = "compat.mode.packages";
+ static final int TEST_USER_ID = 1;
+
+ @Before
+ public void setUp() {
+ mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
+ mGm = mock(GameManagerInternal.class);
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(GameManagerInternal.class);
+ }
+
+ @Test
+ public void testGetCompatScale_gameManagerReturnsPositive() {
+ LocalServices.addService(GameManagerInternal.class, mGm);
+ float scale = 0.25f;
+ doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1 / scale,
+ 0.01f);
+ }
+
+ @Test
+ public void testGetCompatScale_gameManagerReturnsZero() {
+ LocalServices.addService(GameManagerInternal.class, mGm);
+ float scale = 0f;
+ doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+ 0.01f);
+ }
+
+ @Test
+ public void testGetCompatScale_gameManagerReturnsNegative() {
+ LocalServices.addService(GameManagerInternal.class, mGm);
+ float scale = -1f;
+ doReturn(scale).when(mGm).getResolutionScalingFactor(anyString(), anyInt());
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+ 0.01f);
+ }
+
+ @Test
+ public void testGetCompatScale_noGameManager() {
+ assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f,
+ 0.01f);
+ }
+
+}