1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.gamemanager.cts;
18 
19 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
20 
21 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assume.assumeFalse;
28 import static org.junit.Assume.assumeTrue;
29 
30 import android.app.GameManager;
31 import android.app.GameModeConfiguration;
32 import android.app.GameModeInfo;
33 import android.app.GameState;
34 import android.app.Instrumentation;
35 import android.content.Context;
36 import android.content.pm.PackageManager;
37 import android.os.Build;
38 import android.platform.test.annotations.AppModeFull;
39 import android.platform.test.annotations.RequiresFlagsEnabled;
40 import android.platform.test.flag.junit.CheckFlagsRule;
41 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
42 import android.support.test.uiautomator.UiDevice;
43 
44 import androidx.test.ext.junit.rules.ActivityScenarioRule;
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import com.android.compatibility.common.util.ShellIdentityUtils;
48 
49 import org.junit.After;
50 import org.junit.Before;
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 
55 import java.io.IOException;
56 import java.util.Arrays;
57 import java.util.regex.Matcher;
58 import java.util.regex.Pattern;
59 
60 @RunWith(AndroidJUnit4.class)
61 public class GameManagerTest {
62     private static final String TAG = "GameManagerTest";
63     private static final String POWER_DUMPSYS_CMD = "dumpsys android.hardware.power.IPower/default";
64     private static final Pattern GAME_LOADING_REGEX =
65             Pattern.compile("^GAME_LOADING\\t(\\d*)\\t\\d*$", Pattern.MULTILINE);
66     private static final String APK_DIRECTORY = "/data/local/tmp/cts/gamemanager/test/apps/";
67 
68     private static final String NOT_GAME_TEST_APP_APK_PATH =
69             APK_DIRECTORY + "CtsNotGameTestApp.apk";
70     private static final String NOT_GAME_TEST_APP_PACKAGE_NAME =
71             "android.gamemanager.cts.app.notgametestapp";
72 
73     private static final String GAME_TEST_APP_APK_PATH =
74             APK_DIRECTORY + "CtsGameTestApp.apk";
75     private static final String GAME_TEST_APP_PACKAGE_NAME =
76             "android.gamemanager.cts.app.gametestapp";
77 
78     private static final String GAME_TEST_APP_WITH_BATTERY_APK_PATH =
79             APK_DIRECTORY + "CtsGameTestAppWithBatteryMode.apk";
80     private static final String GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME =
81             "android.gamemanager.cts.app.gametestapp.battery";
82 
83     private static final String GAME_TEST_APP_WITH_PERFORMANCE_APK_PATH =
84             APK_DIRECTORY + "CtsGameTestAppWithPerformanceMode.apk";
85     private static final String GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME =
86             "android.gamemanager.cts.app.gametestapp.performance";
87 
88     private static final String GAME_TEST_APP_WITH_TIRAMISU_TARGET_APK_PATH =
89             APK_DIRECTORY + "CtsGameTestAppWithTiramisuTarget.apk";
90     private static final String GAME_TEST_APP_WITH_TIRAMISU_TARGET_PACKAGE_NAME =
91             "android.gamemanager.cts.app.gametestapp.tiramisu";
92 
93     private static final String GAME_TEST_APP_ACTIVITY_NAME = ".GameTestAppMainActivity";
94 
95     private static final String PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE =
96             "ro.surface_flinger.game_default_frame_rate_override";
97 
98     private static final String PROPERTY_RO_VENDOR_API_LEVEL = "ro.vendor.api_level";
99 
100     private static final int TEST_LABEL = 1;
101     private static final int TEST_QUALITY = 2;
102 
103     private GameManagerCtsActivity mActivity;
104     private Context mContext;
105     private GameManager mGameManager;
106     private UiDevice mUiDevice;
107 
108     @Rule
109     public final CheckFlagsRule mCheckFlagsRule =
110             DeviceFlagsValueProvider.createCheckFlagsRule();
111 
112     @Rule
113     public ActivityScenarioRule<GameManagerCtsActivity> mActivityRule =
114             new ActivityScenarioRule<>(GameManagerCtsActivity.class);
115 
116     @Before
setUp()117     public void setUp() {
118         TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
119         TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
120         TestUtil.uninstallPackage(GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME);
121         TestUtil.uninstallPackage(GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME);
122         TestUtil.uninstallPackage(GAME_TEST_APP_WITH_TIRAMISU_TARGET_PACKAGE_NAME);
123 
124         mActivityRule.getScenario().onActivity(activity -> {
125             mActivity = activity;
126         });
127 
128         final Instrumentation instrumentation = getInstrumentation();
129         mContext = instrumentation.getContext();
130         mGameManager = mContext.getSystemService(GameManager.class);
131         mUiDevice = UiDevice.getInstance(instrumentation);
132     }
133 
134     @After
tearDown()135     public void tearDown() throws Exception {
136         TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
137         TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
138         TestUtil.uninstallPackage(GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME);
139         TestUtil.uninstallPackage(GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME);
140         TestUtil.uninstallPackage(GAME_TEST_APP_WITH_TIRAMISU_TARGET_PACKAGE_NAME);
141     }
142 
assumeMobileDeviceFormFactor()143     protected void assumeMobileDeviceFormFactor() {
144         final PackageManager pm = mContext.getPackageManager();
145         assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
146         assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK)); // TVs
147         assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_WATCH));
148         assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_EMBEDDED));
149     }
150 
assumeAndroidApiLevel(int androidApiLevel)151     protected void assumeAndroidApiLevel(int androidApiLevel) {
152         final int apiLevel =
153                 Integer.parseInt(runShellCommand("getprop " + PROPERTY_RO_VENDOR_API_LEVEL));
154         assumeTrue(apiLevel >= androidApiLevel);
155     }
156 
157     @Test
158     @RequiresFlagsEnabled({android.server.app.Flags.FLAG_GAME_DEFAULT_FRAME_RATE,
159             com.android.graphics.surfaceflinger.flags.Flags.FLAG_GAME_DEFAULT_FRAME_RATE})
testIsGameDefaultFrameRatePropSet()160     public void testIsGameDefaultFrameRatePropSet() throws NumberFormatException {
161         // Verify that "ro.surface_flinger.game_default_frame_rate_override"
162         // is set with a positive integer.
163 
164         // This test only aims for mobile devices after Android T
165         assumeMobileDeviceFormFactor();
166         assumeAndroidApiLevel(Build.VERSION_CODES.TIRAMISU);
167         Integer gameDefaultFrameRate = Integer.valueOf(runShellCommand("getprop "
168                 + PROPERTY_RO_SURFACEFLINGER_GAME_DEFAULT_FRAME_RATE));
169         assertNotNull(gameDefaultFrameRate);
170         assertTrue(gameDefaultFrameRate >= 0);
171     }
172 
173     @Test
testIsAngleEnabled()174     public void testIsAngleEnabled() throws Exception {
175         final String packageName = GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME;
176         TestUtil.installPackage(GAME_TEST_APP_WITH_PERFORMANCE_APK_PATH);
177         Thread.sleep(1000);
178 
179         // enable Angle for BATTERY mode.
180         runShellCommand("device_config put game_overlay " + packageName
181                 + " mode=3,useAngle=true");
182         Thread.sleep(1000);
183 
184         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
185                 (gameManager) -> gameManager.setGameMode(packageName,
186                         GameManager.GAME_MODE_BATTERY), "android.permission.MANAGE_GAME_MODE");
187         assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
188                 (gameManager) -> gameManager.isAngleEnabled(packageName),
189                 "android.permission.MANAGE_GAME_MODE"));
190         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
191                 (gameManager) -> gameManager.setGameMode(packageName,
192                         GameManager.GAME_MODE_PERFORMANCE), "android.permission.MANAGE_GAME_MODE");
193         assertFalse(ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
194                 (gameManager) -> gameManager.isAngleEnabled(packageName),
195                 "android.permission.MANAGE_GAME_MODE"));
196 
197         TestUtil.uninstallPackage(packageName);
198     }
199 
200     /**
201      * Test that GameManager::getGameMode() returns the UNSUPPORTED when an app is not a game.
202      */
203     @Test
testGetGameModeUnsupportedOnNotGame()204     public void testGetGameModeUnsupportedOnNotGame() throws InterruptedException {
205         TestUtil.installPackage(NOT_GAME_TEST_APP_APK_PATH);
206         Thread.sleep(1000);
207 
208         int gameMode =
209                 ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
210                         (gameManager) -> gameManager.getGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME),
211                         "android.permission.MANAGE_GAME_MODE");
212 
213         assertEquals("Game Manager returned incorrect value for "
214                 + NOT_GAME_TEST_APP_PACKAGE_NAME, GameManager.GAME_MODE_UNSUPPORTED, gameMode);
215 
216         // Attempt to set the game mode to standard.
217         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
218                 (gameManager) -> gameManager.setGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME,
219                         GameManager.GAME_MODE_STANDARD));
220         gameMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
221                 (gameManager) -> gameManager.getGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME),
222                 "android.permission.MANAGE_GAME_MODE");
223         assertEquals("Game Manager returned incorrect value for "
224                         + NOT_GAME_TEST_APP_PACKAGE_NAME,
225                 GameManager.GAME_MODE_UNSUPPORTED, gameMode);
226 
227         // Attempt to set the game mode to performance.
228         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
229                 (gameManager) -> gameManager.setGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME,
230                         GameManager.GAME_MODE_PERFORMANCE));
231         gameMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
232                 (gameManager) -> gameManager.getGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME),
233                 "android.permission.MANAGE_GAME_MODE");
234         assertEquals("Game Manager returned incorrect value for "
235                         + NOT_GAME_TEST_APP_PACKAGE_NAME,
236                 GameManager.GAME_MODE_UNSUPPORTED, gameMode);
237 
238         // Attempt to set the game mode to battery.
239         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
240                 (gameManager) -> gameManager.setGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME,
241                         GameManager.GAME_MODE_BATTERY));
242         gameMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
243                 (gameManager) -> gameManager.getGameMode(NOT_GAME_TEST_APP_PACKAGE_NAME),
244                 "android.permission.MANAGE_GAME_MODE");
245         assertEquals("Game Manager returned incorrect value for "
246                         + NOT_GAME_TEST_APP_PACKAGE_NAME,
247                 GameManager.GAME_MODE_UNSUPPORTED, gameMode);
248 
249         TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
250     }
251 
252     /**
253      * Test that GAME_MODE_UNSUPPORTED is not forcible for game.
254      */
255     @Test
testGetGameModeUnsupported()256     public void testGetGameModeUnsupported() {
257         int expectedGameMode = mActivity.getGameMode();
258         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
259                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
260                         GameManager.GAME_MODE_UNSUPPORTED));
261 
262         int newGameMode = mActivity.getGameMode();
263 
264         assertEquals("Game mode is not expected to change after trying to set UNSUPPORTED",
265                 expectedGameMode, newGameMode);
266     }
267 
268     /**
269      * Test that GameManager::getGameMode() returns the correct value when forcing the Game Mode to
270      * GAME_MODE_STANDARD.
271      */
272     @Test
testGetGameModeStandard()273     public void testGetGameModeStandard() {
274         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
275                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
276                         GameManager.GAME_MODE_STANDARD));
277 
278         int gameMode = mActivity.getGameMode();
279 
280         assertEquals("Game Manager returned incorrect value.",
281                 GameManager.GAME_MODE_STANDARD, gameMode);
282     }
283 
284     /**
285      * Test that GameManager::getGameMode() returns the correct value when forcing the Game Mode to
286      * GAME_MODE_PERFORMANCE.
287      */
288     @Test
testGetGameModePerformance()289     public void testGetGameModePerformance() {
290         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
291                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
292                         GameManager.GAME_MODE_PERFORMANCE));
293 
294         int gameMode = mActivity.getGameMode();
295 
296         assertEquals("Game Manager returned incorrect value.",
297                 GameManager.GAME_MODE_PERFORMANCE, gameMode);
298     }
299 
300     /**
301      * Test that GameManager::getGameMode() returns the correct value when forcing the Game Mode to
302      * GAME_MODE_BATTERY.
303      */
304     @Test
testGetGameModeBattery()305     public void testGetGameModeBattery() {
306         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
307                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
308                         GameManager.GAME_MODE_BATTERY));
309 
310         int gameMode = mActivity.getGameMode();
311 
312         assertEquals("Game Manager returned incorrect value.",
313                 GameManager.GAME_MODE_BATTERY, gameMode);
314     }
315 
getGameLoadingCount()316     private int getGameLoadingCount() throws IOException {
317         final Matcher matcher =
318                 GAME_LOADING_REGEX.matcher(mUiDevice.executeShellCommand(POWER_DUMPSYS_CMD));
319         assumeTrue(matcher.find());
320         return Integer.parseInt(matcher.group(1));
321     }
322 
323     /**
324      * Test that GameManager::setGameState() with an 'isLoading' state does not invokes the mode
325      * on the PowerHAL when performance mode is not invoked.
326      */
327     @Test
testSetGameStateStandardMode()328     public void testSetGameStateStandardMode() throws IOException, InterruptedException {
329         final int gameLoadingCountBefore = getGameLoadingCount();
330         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
331                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
332                 GameManager.GAME_MODE_STANDARD));
333         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager, (gameManager) ->
334                 gameManager.setGameState(new GameState(true, GameState.MODE_NONE)));
335         Thread.sleep(1000);  // Wait for change to take effect.
336         assertEquals(gameLoadingCountBefore, getGameLoadingCount());
337     }
338 
339     /**
340      * Test that GameManager::setGameState() with an 'isLoading' state actually invokes the mode
341      * on the PowerHAL when performance mode is invoked.
342      */
343     @Test
testSetGameStatePerformanceMode()344     public void testSetGameStatePerformanceMode() throws IOException, InterruptedException {
345         final int gameLoadingCountBefore = getGameLoadingCount();
346         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
347                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
348                 GameManager.GAME_MODE_PERFORMANCE));
349         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager, (gameManager) ->
350                 gameManager.setGameState(new GameState(true, GameState.MODE_NONE)));
351         Thread.sleep(1000);  // Wait for change to take effect.
352         assertEquals(gameLoadingCountBefore + 1, getGameLoadingCount());
353     }
354 
355     /**
356      * Test that GameManager::setGameState() with an 'isLoading' state and labels
357      * actually invokes the mode on the PowerHAL when performance mode is invoked.
358      */
359     @Test
testSetGameStatePerformanceMode_withParams()360     public void testSetGameStatePerformanceMode_withParams()
361             throws IOException, InterruptedException {
362         final int gameLoadingCountBefore = getGameLoadingCount();
363         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
364                 (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
365                         GameManager.GAME_MODE_PERFORMANCE));
366         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager, (gameManager) ->
367                 gameManager.setGameState(
368                         new GameState(true, GameState.MODE_NONE, TEST_LABEL, TEST_QUALITY)));
369         Thread.sleep(1000);  // Wait for change to take effect.
370         assertEquals(gameLoadingCountBefore + 1, getGameLoadingCount());
371     }
372 
373     /**
374      * Test that GameManager::getGameModeInfo() returns correct values for a game.
375      */
376     @Test
testGetGameModeInfoWithTwoGameModes()377     public void testGetGameModeInfoWithTwoGameModes() throws InterruptedException {
378         TestUtil.installPackage(GAME_TEST_APP_APK_PATH);
379         // When an app is installed, some propagation work for the configuration will
380         // be set up asynchronously, hence wait for 1000ms here.
381         Thread.sleep(1000);
382 
383         GameModeInfo gameModeInfo =
384                 ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
385                         (gameManager) -> gameManager.getGameModeInfo(GAME_TEST_APP_PACKAGE_NAME),
386                         "android.permission.MANAGE_GAME_MODE");
387         assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
388                 4, gameModeInfo.getAvailableGameModes().length);
389         assertTrue("GameManager#getGameModeInfo returned incorrect overridden game modes.",
390                 Arrays.asList(GameManager.GAME_MODE_PERFORMANCE,
391                         GameManager.GAME_MODE_BATTERY).containsAll(Arrays.stream(
392                         gameModeInfo.getOverriddenGameModes()).boxed().toList()));
393         assertTrue("GameManager#getGameModeInfo returned incorrect downscaling opt-in value.",
394                 gameModeInfo.isDownscalingAllowed());
395         assertTrue("GameManager#getGameModeInfo returned incorrect FPS override opt-in value.",
396                 gameModeInfo.isFpsOverrideAllowed());
397         assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
398                 GameManager.GAME_MODE_STANDARD, gameModeInfo.getActiveGameMode());
399 
400         // Attempt to set the game mode to standard.
401         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
402                 (gameManager) -> gameManager.setGameMode(GAME_TEST_APP_PACKAGE_NAME,
403                         GameManager.GAME_MODE_STANDARD));
404         gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
405                 (gameManager) -> gameManager.getGameModeInfo(GAME_TEST_APP_PACKAGE_NAME),
406                 "android.permission.MANAGE_GAME_MODE");
407         assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
408                 4, gameModeInfo.getAvailableGameModes().length);
409         assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
410                 GameManager.GAME_MODE_STANDARD, gameModeInfo.getActiveGameMode());
411 
412         // Attempt to set the game mode to performance.
413         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
414                 (gameManager) -> gameManager.setGameMode(GAME_TEST_APP_PACKAGE_NAME,
415                         GameManager.GAME_MODE_PERFORMANCE));
416         gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
417                 (gameManager) -> gameManager.getGameModeInfo(GAME_TEST_APP_PACKAGE_NAME),
418                 "android.permission.MANAGE_GAME_MODE");
419         assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
420                 4, gameModeInfo.getAvailableGameModes().length);
421         assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
422                 GameManager.GAME_MODE_PERFORMANCE, gameModeInfo.getActiveGameMode());
423 
424         // Attempt to set the game mode to battery.
425         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
426                 (gameManager) -> gameManager.setGameMode(GAME_TEST_APP_PACKAGE_NAME,
427                         GameManager.GAME_MODE_BATTERY));
428         gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
429                 (gameManager) -> gameManager.getGameModeInfo(GAME_TEST_APP_PACKAGE_NAME),
430                 "android.permission.MANAGE_GAME_MODE");
431         assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
432                 4, gameModeInfo.getAvailableGameModes().length);
433         assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
434                 GameManager.GAME_MODE_BATTERY, gameModeInfo.getActiveGameMode());
435 
436         TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
437     }
438 
439     /**
440      * Test that GameManager::getGameModeInfo() returns correct values for a game when it only
441      * supports battery mode.
442      */
443     @Test
testGetGameModeInfoWithBatteryMode()444     public void testGetGameModeInfoWithBatteryMode() throws InterruptedException {
445         final String packageName = GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME;
446         TestUtil.installPackage(GAME_TEST_APP_WITH_BATTERY_APK_PATH);
447         // When an app is installed, some propagation work for the configuration will
448         // be set up asynchronously, hence wait for 1000ms here.
449         Thread.sleep(1000);
450 
451         GameModeInfo gameModeInfo =
452                 ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
453                         (gameManager) -> gameManager.getGameModeInfo(packageName),
454                         "android.permission.MANAGE_GAME_MODE");
455         assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
456                 3, gameModeInfo.getAvailableGameModes().length);
457         assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
458                 GameManager.GAME_MODE_STANDARD, gameModeInfo.getActiveGameMode());
459 
460         // Attempt to set the game mode to battery.
461         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
462                 (gameManager) -> gameManager.setGameMode(packageName,
463                         GameManager.GAME_MODE_BATTERY));
464         gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
465                 (gameManager) -> gameManager.getGameModeInfo(packageName),
466                 "android.permission.MANAGE_GAME_MODE");
467         assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
468                 3, gameModeInfo.getAvailableGameModes().length);
469         assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
470                 GameManager.GAME_MODE_BATTERY, gameModeInfo.getActiveGameMode());
471 
472         TestUtil.uninstallPackage(packageName);
473     }
474 
475     @Test
476     @AppModeFull
testCustomGameMode()477     public void testCustomGameMode() throws Exception {
478         final String packageName = GAME_TEST_APP_PACKAGE_NAME;
479         TestUtil.installPackage(GAME_TEST_APP_APK_PATH);
480         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
481                 (gameManager) -> gameManager.setGameMode(packageName,
482                         GameManager.GAME_MODE_CUSTOM));
483 
484         final int gameMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
485                 (gameManager) -> gameManager.getGameMode(packageName),
486                 "android.permission.MANAGE_GAME_MODE");
487         assertEquals("Game Manager returned incorrect value.",
488                 GameManager.GAME_MODE_CUSTOM, gameMode);
489 
490         runShellCommand("am start -n " + GAME_TEST_APP_PACKAGE_NAME
491                 + "/" + GAME_TEST_APP_ACTIVITY_NAME);
492         assertEquals(GameManager.GAME_MODE_CUSTOM,
493                 mActivity.getLastReceivedGameMode(GAME_TEST_APP_PACKAGE_NAME,
494                         10000 /* timeoutMillis */));
495     }
496 
497     @Test
498     @AppModeFull
testCustomGameModeBackwardCompatibility()499     public void testCustomGameModeBackwardCompatibility() throws Exception {
500         final String packageName = GAME_TEST_APP_WITH_TIRAMISU_TARGET_PACKAGE_NAME;
501         TestUtil.installPackage(GAME_TEST_APP_WITH_TIRAMISU_TARGET_APK_PATH);
502         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
503                 (gameManager) -> gameManager.setGameMode(packageName,
504                         GameManager.GAME_MODE_CUSTOM));
505 
506         final int gameMode = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
507                 (gameManager) -> gameManager.getGameMode(packageName),
508                 "android.permission.MANAGE_GAME_MODE");
509         assertEquals("Game Manager returned incorrect value.",
510                 GameManager.GAME_MODE_STANDARD, gameMode);
511 
512         runShellCommand("am start -n " + GAME_TEST_APP_WITH_TIRAMISU_TARGET_PACKAGE_NAME
513                 + "/" + GAME_TEST_APP_ACTIVITY_NAME);
514         assertEquals(GameManager.GAME_MODE_STANDARD,
515                 mActivity.getLastReceivedGameMode(GAME_TEST_APP_WITH_TIRAMISU_TARGET_PACKAGE_NAME,
516                         10000 /* timeoutMillis */));
517     }
518 
519     @Test
testUpdateCustomGameModeConfiguration()520     public void testUpdateCustomGameModeConfiguration() throws Exception {
521         final String packageName = GAME_TEST_APP_PACKAGE_NAME;
522         TestUtil.installPackage(GAME_TEST_APP_APK_PATH);
523         final GameModeConfiguration gameModeConfiguration = new GameModeConfiguration.Builder()
524                 .setFpsOverride(60)
525                 .setScalingFactor(0.8f).build();
526         ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
527                 (gameManager) -> gameManager.updateCustomGameModeConfiguration(packageName,
528                         gameModeConfiguration),
529                 "android.permission.MANAGE_GAME_MODE");
530         final GameModeInfo gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(
531                 mGameManager,
532                 (gameManager) -> gameManager.getGameModeInfo(packageName),
533                 "android.permission.MANAGE_GAME_MODE");
534         assertEquals(new GameModeConfiguration.Builder(gameModeConfiguration).build(),
535                 gameModeInfo.getGameModeConfiguration(GameManager.GAME_MODE_CUSTOM));
536     }
537 }
538