Add allowGameFpsOverride intervention flag

Similar to Angle intervention, to turn off FPS overriding, the app
needs to have this flag disabled.

Bug: 214448560
Test: atest GameManagerServicesTest
Change-Id: I228beb39e9ba2649ee09fe165c0ff0c3bc7f1887
This commit is contained in:
Xiang Wang
2022-01-20 22:12:30 +00:00
parent 7998c248cc
commit 8f43fdf19b
7 changed files with 111 additions and 2 deletions

View File

@@ -328,6 +328,7 @@ package android {
field public static final int allowEmbedded = 16843765; // 0x10103f5
field public static final int allowGameAngleDriver;
field public static final int allowGameDownscaling;
field public static final int allowGameFpsOverride;
field public static final int allowNativeHeapPointerTagging = 16844306; // 0x1010612
field public static final int allowParallelSyncs = 16843570; // 0x1010332
field public static final int allowSingleTap = 16843353; // 0x1010259

View File

@@ -8887,6 +8887,8 @@
<attr name="allowGameAngleDriver" format="boolean" />
<!-- Set true to allow resolution downscaling intervention. -->
<attr name="allowGameDownscaling" format="boolean" />
<!-- Set true to allow FPS override intervention. -->
<attr name="allowGameFpsOverride" format="boolean" />
</declare-styleable>
<!-- Use <code>voice-enrollment-application</code>

View File

@@ -3259,6 +3259,7 @@
<public name="supportsPerformanceGameMode" />
<public name="allowGameAngleDriver" />
<public name="allowGameDownscaling" />
<public name="allowGameFpsOverride" />
<public name="localeConfig" />
<public name="showBackground" />
<public name="inheritKeyStoreKeys" />

View File

@@ -22,6 +22,7 @@ import static android.content.Intent.ACTION_PACKAGE_REMOVED;
import static com.android.internal.R.styleable.GameModeConfig_allowGameAngleDriver;
import static com.android.internal.R.styleable.GameModeConfig_allowGameDownscaling;
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;
@@ -452,6 +453,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
private boolean mBatteryModeOptedIn;
private boolean mAllowDownscale;
private boolean mAllowAngle;
private boolean mAllowFpsOverride;
GamePackageConfiguration(String packageName, int userId) {
mPackageName = packageName;
@@ -470,6 +472,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
mBatteryModeOptedIn = false;
mAllowDownscale = true;
mAllowAngle = true;
mAllowFpsOverride = true;
}
}
} catch (NameNotFoundException e) {
@@ -527,6 +530,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
mAllowDownscale = array.getBoolean(GameModeConfig_allowGameDownscaling,
true);
mAllowAngle = array.getBoolean(GameModeConfig_allowGameAngleDriver, true);
mAllowFpsOverride = array.getBoolean(GameModeConfig_allowGameFpsOverride,
true);
array.recycle();
}
}
@@ -565,7 +570,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
mScaling = !mAllowDownscale || willGamePerformOptimizations(mGameMode)
? DEFAULT_SCALING : parser.getString(SCALING_KEY, DEFAULT_SCALING);
mFps = parser.getString(FPS_KEY, DEFAULT_FPS);
mFps = mAllowFpsOverride && !willGamePerformOptimizations(mGameMode)
? parser.getString(FPS_KEY, DEFAULT_FPS) : DEFAULT_FPS;
// We only want to use ANGLE if:
// - We're allowed to use ANGLE (the app hasn't opted out via the manifest) AND
// - The app has not opted in to performing the work itself AND

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<game-mode-config
xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsPerformanceGameMode="false"
android:supportsBatteryGameMode="false"
android:allowGameAngleDriver="false"
android:allowGameDownscaling="false"
android:allowGameFpsOverride="false"
/>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<game-mode-config
xmlns:android="http://schemas.android.com/apk/res/android"
android:supportsPerformanceGameMode="false"
android:supportsBatteryGameMode="false"
android:allowGameAngleDriver="true"
android:allowGameDownscaling="true"
android:allowGameFpsOverride="true"
/>

View File

@@ -26,6 +26,8 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -41,6 +43,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.hardware.power.Mode;
import android.os.Bundle;
import android.os.PowerManagerInternal;
@@ -159,11 +164,17 @@ public class GameManagerServiceTests {
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);
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()))
@@ -322,6 +333,46 @@ public class GameManagerServiceTests {
.thenReturn(applicationInfo);
}
private void mockInterventionsEnabledFromXml() throws Exception {
final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser(
mPackageName, PackageManager.GET_META_DATA, USER_ID_1);
Bundle metaDataBundle = new Bundle();
final int resId = 123;
metaDataBundle.putInt(
GameManagerService.GamePackageConfiguration.METADATA_GAME_MODE_CONFIG, resId);
applicationInfo.metaData = metaDataBundle;
when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
.thenReturn(applicationInfo);
seedGameManagerServiceMetaDataFromFile(mPackageName, resId,
"res/xml/gama_manager_service_metadata_config_enabled.xml");
}
private void mockInterventionsDisabledFromXml() throws Exception {
final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser(
mPackageName, PackageManager.GET_META_DATA, USER_ID_1);
Bundle metaDataBundle = new Bundle();
final int resId = 123;
metaDataBundle.putInt(
GameManagerService.GamePackageConfiguration.METADATA_GAME_MODE_CONFIG, resId);
applicationInfo.metaData = metaDataBundle;
when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
.thenReturn(applicationInfo);
seedGameManagerServiceMetaDataFromFile(mPackageName, resId,
"res/xml/gama_manager_service_metadata_config_disabled.xml");
}
private void seedGameManagerServiceMetaDataFromFile(String packageName, int resId,
String fileName)
throws Exception {
AssetManager assetManager =
InstrumentationRegistry.getInstrumentation().getContext().getAssets();
XmlResourceParser xmlResourceParser =
assetManager.openXmlResourceParser(fileName);
when(mMockPackageManager.getXml(eq(packageName), eq(resId), any()))
.thenReturn(xmlResourceParser);
}
/**
* By default game mode is not supported.
*/
@@ -523,7 +574,7 @@ public class GameManagerServiceTests {
}
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
assertEquals(config.getGameModeConfiguration(gameMode).getFps(), fps);
assertEquals(fps, config.getGameModeConfiguration(gameMode).getFps());
}
/**
@@ -904,6 +955,36 @@ public class GameManagerServiceTests {
checkAngleEnabled(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, true);
}
@Test
public void testGameModeConfigAllowFpsTrue() throws Exception {
mockDeviceConfigAll();
mockModifyGameModeGranted();
mockInterventionsEnabledFromXml();
GameManagerService gameManagerService = new GameManagerService(mMockContext,
mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
assertEquals(90,
config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE).getFps());
assertEquals(30, config.getGameModeConfiguration(GameManager.GAME_MODE_BATTERY).getFps());
}
@Test
public void testGameModeConfigAllowFpsFalse() throws Exception {
mockDeviceConfigAll();
mockModifyGameModeGranted();
mockInterventionsDisabledFromXml();
GameManagerService gameManagerService = new GameManagerService(mMockContext,
mTestLooper.getLooper());
startUser(gameManagerService, USER_ID_1);
GameManagerService.GamePackageConfiguration config =
gameManagerService.getConfig(mPackageName);
assertEquals(0,
config.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE).getFps());
assertEquals(0, config.getGameModeConfiguration(GameManager.GAME_MODE_BATTERY).getFps());
}
@Test
public void testInterventionFps() throws Exception {
mockDeviceConfigAll();