Merge changes If537a25e,Iee14d6ee

* changes:
  Reset FPS when device config resets or app opts in to a game mode
  Override config should trigger intervention ignoring opt-in info
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index e11d95a..efa2f25 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -490,6 +490,8 @@
         private final Object mModeConfigLock = new Object();
         @GuardedBy("mModeConfigLock")
         private final ArrayMap<Integer, GameModeConfiguration> mModeConfigs = new ArrayMap<>();
+        // if adding new properties or make any of the below overridable, the method
+        // copyAndApplyOverride should be updated accordingly
         private boolean mPerfModeOptedIn = false;
         private boolean mBatteryModeOptedIn = false;
         private boolean mAllowDownscale = true;
@@ -800,6 +802,42 @@
             }
         }
 
+        GamePackageConfiguration copyAndApplyOverride(GamePackageConfiguration overrideConfig) {
+            GamePackageConfiguration copy = new GamePackageConfiguration(mPackageName);
+            // if a game mode is overridden, we treat it with the highest priority and reset any
+            // opt-in game modes so that interventions are always executed.
+            copy.mPerfModeOptedIn = mPerfModeOptedIn && !(overrideConfig != null
+                    && overrideConfig.getGameModeConfiguration(GameManager.GAME_MODE_PERFORMANCE)
+                    != null);
+            copy.mBatteryModeOptedIn = mBatteryModeOptedIn && !(overrideConfig != null
+                    && overrideConfig.getGameModeConfiguration(GameManager.GAME_MODE_BATTERY)
+                    != null);
+
+            // if any game mode is overridden, we will consider all interventions forced-active,
+            // this can be done more granular by checking if a specific intervention is
+            // overridden under each game mode override, but only if necessary.
+            copy.mAllowDownscale = mAllowDownscale || overrideConfig != null;
+            copy.mAllowAngle = mAllowAngle || overrideConfig != null;
+            copy.mAllowFpsOverride = mAllowFpsOverride || overrideConfig != null;
+            if (overrideConfig != null) {
+                synchronized (copy.mModeConfigLock) {
+                    synchronized (mModeConfigLock) {
+                        for (Map.Entry<Integer, GameModeConfiguration> entry :
+                                mModeConfigs.entrySet()) {
+                            copy.mModeConfigs.put(entry.getKey(), entry.getValue());
+                        }
+                    }
+                    synchronized (overrideConfig.mModeConfigLock) {
+                        for (Map.Entry<Integer, GameModeConfiguration> entry :
+                                overrideConfig.mModeConfigs.entrySet()) {
+                            copy.mModeConfigs.put(entry.getKey(), entry.getValue());
+                        }
+                    }
+                }
+            }
+            return copy;
+        }
+
         public String toString() {
             synchronized (mModeConfigLock) {
                 return "[Name:" + mPackageName + " Modes: " + mModeConfigs.toString() + "]";
@@ -1298,7 +1336,7 @@
         try {
             final float fps = 0.0f;
             final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
-            nativeSetOverrideFrameRate(uid, fps);
+            setOverrideFrameRate(uid, fps);
         } catch (PackageManager.NameNotFoundException e) {
             return;
         }
@@ -1330,7 +1368,7 @@
         try {
             final float fps = modeConfig.getFps();
             final int uid = mPackageManager.getPackageUidAsUser(packageName, userId);
-            nativeSetOverrideFrameRate(uid, fps);
+            setOverrideFrameRate(uid, fps);
         } catch (PackageManager.NameNotFoundException e) {
             return;
         }
@@ -1339,18 +1377,18 @@
 
     private void updateInterventions(String packageName,
             @GameMode int gameMode, @UserIdInt int userId) {
-        if (gameMode == GameManager.GAME_MODE_STANDARD
-                || gameMode == GameManager.GAME_MODE_UNSUPPORTED) {
-            resetFps(packageName, userId);
-            return;
-        }
         final GamePackageConfiguration packageConfig = getConfig(packageName, userId);
-        if (packageConfig == null) {
-            Slog.v(TAG, "Package configuration not found for " + packageName);
-            return;
-        }
-        if (packageConfig.willGamePerformOptimizations(gameMode)) {
-            return;
+        if (gameMode == GameManager.GAME_MODE_STANDARD
+                || gameMode == GameManager.GAME_MODE_UNSUPPORTED || packageConfig == null
+                || packageConfig.willGamePerformOptimizations(gameMode)) {
+            resetFps(packageName, userId);
+            // resolution scaling does not need to be reset as it's now read dynamically on game
+            // restart, see #getResolutionScalingFactor and CompatModePackages#getCompatScale.
+            // TODO: reset Angle intervention here once implemented
+            if (packageConfig == null) {
+                Slog.v(TAG, "Package configuration not found for " + packageName);
+                return;
+            }
         }
         updateFps(packageConfig, packageName, gameMode, userId);
         updateUseAngle(packageName, gameMode);
@@ -1375,7 +1413,7 @@
             // look for the existing GamePackageConfiguration override
             configOverride = settings.getConfigOverride(packageName);
             if (configOverride == null) {
-                configOverride = new GamePackageConfiguration(mPackageManager, packageName, userId);
+                configOverride = new GamePackageConfiguration(packageName);
                 settings.setConfigOverride(packageName, configOverride);
             }
         }
@@ -1430,18 +1468,12 @@
                     return;
                 }
                 // if the game mode to reset is the only mode other than standard mode or there
-                // is device config, the config override is removed.
+                // is device config, the entire package config override is removed.
                 if (Integer.bitCount(modesBitfield) <= 2 || deviceConfig == null) {
                     settings.removeConfigOverride(packageName);
                 } else {
-                    final GamePackageConfiguration.GameModeConfiguration defaultModeConfig =
-                            deviceConfig.getGameModeConfiguration(gameModeToReset);
-                    // otherwise we reset the mode by copying the original config.
-                    if (defaultModeConfig == null) {
-                        configOverride.removeModeConfig(gameModeToReset);
-                    } else {
-                        configOverride.addModeConfig(defaultModeConfig);
-                    }
+                    // otherwise we reset the mode by removing the game mode config override
+                    configOverride.removeModeConfig(gameModeToReset);
                 }
             } else {
                 settings.removeConfigOverride(packageName);
@@ -1661,18 +1693,21 @@
      * @hide
      */
     public GamePackageConfiguration getConfig(String packageName, int userId) {
-        GamePackageConfiguration packageConfig = null;
+        GamePackageConfiguration overrideConfig = null;
+        GamePackageConfiguration config;
+        synchronized (mDeviceConfigLock) {
+            config = mConfigs.get(packageName);
+        }
+
         synchronized (mLock) {
             if (mSettings.containsKey(userId)) {
-                packageConfig = mSettings.get(userId).getConfigOverride(packageName);
+                overrideConfig = mSettings.get(userId).getConfigOverride(packageName);
             }
         }
-        if (packageConfig == null) {
-            synchronized (mDeviceConfigLock) {
-                packageConfig = mConfigs.get(packageName);
-            }
+        if (overrideConfig == null || config == null) {
+            return overrideConfig == null ? config : overrideConfig;
         }
-        return packageConfig;
+        return config.copyAndApplyOverride(overrideConfig);
     }
 
     private void registerPackageReceiver() {
@@ -1774,6 +1809,11 @@
         return handlerThread;
     }
 
+    @VisibleForTesting
+    void setOverrideFrameRate(int uid, float frameRate) {
+        nativeSetOverrideFrameRate(uid, frameRate);
+    }
+
     /**
      * load dynamic library for frame rate overriding JNI calls
      */
diff --git a/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_disabled_all_opt_in.xml b/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_disabled_all_opt_in.xml
new file mode 100644
index 0000000..77fe786
--- /dev/null
+++ b/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_disabled_all_opt_in.xml
@@ -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="true"
+    android:supportsBatteryGameMode="true"
+    android:allowGameAngleDriver="false"
+    android:allowGameDownscaling="false"
+    android:allowGameFpsOverride="false"
+/>
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/res/xml/gama_manager_service_metadata_config_disabled.xml b/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_disabled_no_opt_in.xml
similarity index 100%
rename from services/tests/mockingservicestests/res/xml/gama_manager_service_metadata_config_disabled.xml
rename to services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_disabled_no_opt_in.xml
diff --git a/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_enabled_all_opt_in.xml b/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_enabled_all_opt_in.xml
new file mode 100644
index 0000000..96d2878
--- /dev/null
+++ b/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_enabled_all_opt_in.xml
@@ -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="true"
+    android:supportsBatteryGameMode="true"
+    android:allowGameAngleDriver="true"
+    android:allowGameDownscaling="true"
+    android:allowGameFpsOverride="true"
+/>
\ No newline at end of file
diff --git a/services/tests/mockingservicestests/res/xml/gama_manager_service_metadata_config_enabled.xml b/services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_enabled_no_opt_in.xml
similarity index 100%
rename from services/tests/mockingservicestests/res/xml/gama_manager_service_metadata_config_enabled.xml
rename to services/tests/mockingservicestests/res/xml/game_manager_service_metadata_config_interventions_enabled_no_opt_in.xml
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 9022db8..d78f6d83 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameManagerServiceTests.java
@@ -73,7 +73,9 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoSession;
 import org.mockito.quality.Strictness;
 
@@ -93,6 +95,7 @@
     private static final String PACKAGE_NAME_INVALID = "com.android.app";
     private static final int USER_ID_1 = 1001;
     private static final int USER_ID_2 = 1002;
+    private static final int DEFAULT_PACKAGE_UID = 12345;
 
     private MockitoSession mMockingSession;
     private String mPackageName;
@@ -207,6 +210,8 @@
                 .thenReturn(packages);
         when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
                 .thenReturn(applicationInfo);
+        when(mMockPackageManager.getPackageUidAsUser(mPackageName, USER_ID_1)).thenReturn(
+                DEFAULT_PACKAGE_UID);
         LocalServices.addService(PowerManagerInternal.class, mMockPowerManager);
     }
 
@@ -382,38 +387,41 @@
                 .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 mockInterventionsEnabledNoOptInFromXml() throws Exception {
+        seedGameManagerServiceMetaDataFromFile(mPackageName, 123,
+                "res/xml/game_manager_service_metadata_config_interventions_enabled_no_opt_in.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 mockInterventionsEnabledAllOptInFromXml() throws Exception {
+        seedGameManagerServiceMetaDataFromFile(mPackageName, 123,
+                "res/xml/game_manager_service_metadata_config_interventions_enabled_all_opt_in"
+                        + ".xml");
+    }
+
+    private void mockInterventionsDisabledNoOptInFromXml() throws Exception {
+        seedGameManagerServiceMetaDataFromFile(mPackageName, 123,
+                "res/xml/game_manager_service_metadata_config_interventions_disabled_no_opt_in"
+                        + ".xml");
+    }
+
+    private void mockInterventionsDisabledAllOptInFromXml() throws Exception {
+        seedGameManagerServiceMetaDataFromFile(mPackageName, 123,
+                "res/xml/game_manager_service_metadata_config_interventions_disabled_all_opt_in"
+                        + ".xml");
     }
 
 
     private void seedGameManagerServiceMetaDataFromFile(String packageName, int resId,
             String fileName)
             throws Exception {
+        final ApplicationInfo applicationInfo = mMockPackageManager.getApplicationInfoAsUser(
+                mPackageName, PackageManager.GET_META_DATA, USER_ID_1);
+        Bundle metaDataBundle = new Bundle();
+        metaDataBundle.putInt(
+                GameManagerService.GamePackageConfiguration.METADATA_GAME_MODE_CONFIG, resId);
+        applicationInfo.metaData = metaDataBundle;
+        when(mMockPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+                .thenReturn(applicationInfo);
         AssetManager assetManager =
                 InstrumentationRegistry.getInstrumentation().getContext().getAssets();
         XmlResourceParser xmlResourceParser =
@@ -641,6 +649,12 @@
         assertEquals(fps, config.getGameModeConfiguration(gameMode).getFps());
     }
 
+    private boolean checkOptedIn(GameManagerService gameManagerService, int gameMode) {
+        GameManagerService.GamePackageConfiguration config =
+                gameManagerService.getConfig(mPackageName, USER_ID_1);
+        return config.willGamePerformOptimizations(gameMode);
+    }
+
     /**
      * Phenotype device config exists, but is only propagating the default value.
      */
@@ -756,7 +770,7 @@
      * Override device configs for both battery and performance modes exists and are valid.
      */
     @Test
-    public void testSetDeviceOverrideConfigAll() {
+    public void testSetDeviceConfigOverrideAll() {
         mockDeviceConfigAll();
         mockModifyGameModeGranted();
 
@@ -776,6 +790,75 @@
         checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 60);
     }
 
+    @Test
+    public void testSetBatteryModeConfigOverride_thenUpdateAllDeviceConfig() throws Exception {
+        mockModifyGameModeGranted();
+        String configStringBefore =
+                "mode=2,downscaleFactor=1.0,fps=90:mode=3,downscaleFactor=0.1,fps=30";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringBefore);
+        mockInterventionsEnabledNoOptInFromXml();
+        GameManagerService gameManagerService = new GameManagerService(mMockContext,
+                mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_1);
+
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 1.0f);
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.1f);
+        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 30);
+
+        gameManagerService.setGameModeConfigOverride(mPackageName, USER_ID_1, 3, "40",
+                "0.2");
+
+        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 40);
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.2f);
+
+        String configStringAfter =
+                "mode=2,downscaleFactor=0.9,fps=60:mode=3,downscaleFactor=0.3,fps=50";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringAfter);
+        gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
+
+        // performance mode was not overridden thus it should be updated
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0.9f);
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 60);
+
+        // battery mode was overridden thus it should be the same as the override
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.2f);
+        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 40);
+    }
+
+    @Test
+    public void testSetBatteryModeConfigOverride_thenOptInBatteryMode() throws Exception {
+        mockModifyGameModeGranted();
+        String configStringBefore =
+                "mode=2,downscaleFactor=1.0,fps=90:mode=3,downscaleFactor=0.1,fps=30";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringBefore);
+        mockInterventionsDisabledNoOptInFromXml();
+        GameManagerService gameManagerService = new GameManagerService(mMockContext,
+                mTestLooper.getLooper());
+        startUser(gameManagerService, USER_ID_1);
+
+        assertFalse(checkOptedIn(gameManagerService, GameManager.GAME_MODE_PERFORMANCE));
+        assertFalse(checkOptedIn(gameManagerService, GameManager.GAME_MODE_BATTERY));
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0);
+
+        gameManagerService.setGameModeConfigOverride(mPackageName, USER_ID_1, 3, "40",
+                "0.2");
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0);
+        // override will enable the interventions
+        checkDownscaling(gameManagerService, GameManager.GAME_MODE_BATTERY, 0.2f);
+        checkFps(gameManagerService, GameManager.GAME_MODE_BATTERY, 40);
+
+        mockInterventionsDisabledAllOptInFromXml();
+        gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
+
+        assertTrue(checkOptedIn(gameManagerService, GameManager.GAME_MODE_PERFORMANCE));
+        // opt-in is still false for battery mode as override exists
+        assertFalse(checkOptedIn(gameManagerService, GameManager.GAME_MODE_BATTERY));
+    }
+
     /**
      * Override device config for performance mode exists and is valid.
      */
@@ -1050,7 +1133,7 @@
         gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
         assertEquals(GameManager.GAME_MODE_PERFORMANCE,
                 gameManagerService.getGameMode(mPackageName, USER_ID_1));
-        mockInterventionsEnabledFromXml();
+        mockInterventionsEnabledNoOptInFromXml();
         checkLoadingBoost(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0);
     }
 
@@ -1058,7 +1141,7 @@
     public void testGameModeConfigAllowFpsTrue() throws Exception {
         mockDeviceConfigAll();
         mockModifyGameModeGranted();
-        mockInterventionsEnabledFromXml();
+        mockInterventionsEnabledNoOptInFromXml();
         GameManagerService gameManagerService = new GameManagerService(mMockContext,
                 mTestLooper.getLooper());
         startUser(gameManagerService, USER_ID_1);
@@ -1073,7 +1156,7 @@
     public void testGameModeConfigAllowFpsFalse() throws Exception {
         mockDeviceConfigAll();
         mockModifyGameModeGranted();
-        mockInterventionsDisabledFromXml();
+        mockInterventionsDisabledNoOptInFromXml();
         GameManagerService gameManagerService = new GameManagerService(mMockContext,
                 mTestLooper.getLooper());
         startUser(gameManagerService, USER_ID_1);
@@ -1551,6 +1634,82 @@
         assertFalse(gameManagerService.mHandler.hasEqualMessages(WRITE_SETTINGS, USER_ID_1));
     }
 
+    @Test
+    public void testResetInterventions_onDeviceConfigReset() throws Exception {
+        mockModifyGameModeGranted();
+        String configStringBefore =
+                "mode=2,downscaleFactor=1.0,fps=90";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringBefore);
+        mockInterventionsEnabledNoOptInFromXml();
+        GameManagerService gameManagerService = Mockito.spy(new GameManagerService(mMockContext,
+                mTestLooper.getLooper()));
+        startUser(gameManagerService, USER_ID_1);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
+        Mockito.verify(gameManagerService).setOverrideFrameRate(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                ArgumentMatchers.eq(90.0f));
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
+
+        String configStringAfter = "";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringAfter);
+        gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
+        Mockito.verify(gameManagerService).setOverrideFrameRate(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                ArgumentMatchers.eq(0.0f));
+    }
+
+    @Test
+    public void testResetInterventions_onInterventionsDisabled() throws Exception {
+        mockModifyGameModeGranted();
+        String configStringBefore =
+                "mode=2,downscaleFactor=1.0,fps=90";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringBefore);
+        mockInterventionsEnabledNoOptInFromXml();
+        GameManagerService gameManagerService = Mockito.spy(new GameManagerService(mMockContext,
+                mTestLooper.getLooper()));
+        startUser(gameManagerService, USER_ID_1);
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
+        Mockito.verify(gameManagerService).setOverrideFrameRate(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                ArgumentMatchers.eq(90.0f));
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
+
+        mockInterventionsDisabledNoOptInFromXml();
+        gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
+        Mockito.verify(gameManagerService).setOverrideFrameRate(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                ArgumentMatchers.eq(0.0f));
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 0);
+    }
+
+    @Test
+    public void testResetInterventions_onGameModeOptedIn() throws Exception {
+        mockModifyGameModeGranted();
+        String configStringBefore =
+                "mode=2,downscaleFactor=1.0,fps=90";
+        when(DeviceConfig.getProperty(anyString(), anyString()))
+                .thenReturn(configStringBefore);
+        mockInterventionsEnabledNoOptInFromXml();
+        GameManagerService gameManagerService = Mockito.spy(new GameManagerService(mMockContext,
+                mTestLooper.getLooper()));
+        startUser(gameManagerService, USER_ID_1);
+
+        gameManagerService.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE, USER_ID_1);
+        Mockito.verify(gameManagerService).setOverrideFrameRate(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                ArgumentMatchers.eq(90.0f));
+        checkFps(gameManagerService, GameManager.GAME_MODE_PERFORMANCE, 90);
+
+        mockInterventionsEnabledAllOptInFromXml();
+        gameManagerService.updateConfigsForUser(USER_ID_1, false, mPackageName);
+        Mockito.verify(gameManagerService).setOverrideFrameRate(
+                ArgumentMatchers.eq(DEFAULT_PACKAGE_UID),
+                ArgumentMatchers.eq(0.0f));
+    }
+
     private static void deleteFolder(File folder) {
         File[] files = folder.listFiles();
         if (files != null) {