Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ed2898d authored by Xiang Wang's avatar Xiang Wang Committed by Android (Google) Code Review
Browse files

Merge "Add custom game mode"

parents 4717ae71 f2579028
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5612,6 +5612,7 @@ package android.app {
    method public int getGameMode();
    method public void setGameState(@NonNull android.app.GameState);
    field public static final int GAME_MODE_BATTERY = 3; // 0x3
    field public static final int GAME_MODE_CUSTOM = 4; // 0x4
    field public static final int GAME_MODE_PERFORMANCE = 2; // 0x2
    field public static final int GAME_MODE_STANDARD = 1; // 0x1
    field public static final int GAME_MODE_UNSUPPORTED = 0; // 0x0
+44 −6
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@ import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UserHandleAware;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -51,6 +54,7 @@ public final class GameManager {
            GAME_MODE_STANDARD, // 1
            GAME_MODE_PERFORMANCE, // 2
            GAME_MODE_BATTERY, // 3
            GAME_MODE_CUSTOM, // 4
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface GameMode {
@@ -79,6 +83,15 @@ public final class GameManager {
     */
    public static final int GAME_MODE_BATTERY = 3;

    /**
     * Custom game mode that has user-provided configuration overrides.
     * <p>
     * Custom game mode is expected to be handled only by the platform using users'
     * preferred config. It is currently not allowed to opt in custom mode in game mode XML file nor
     * expected to perform app-based optimizations when activated.
     */
    public static final int GAME_MODE_CUSTOM = 4;

    GameManager(Context context, Handler handler) throws ServiceNotFoundException {
        mContext = context;
        mService = IGameManagerService.Stub.asInterface(
@@ -93,19 +106,23 @@ public final class GameManager {
     * application is not a game, always return {@link #GAME_MODE_UNSUPPORTED}.
     * <p>
     * Developers should call this API every time the application is resumed.
     * <p>
     * If a game's <code>targetSdkVersion</code> is {@link android.os.Build.VERSION_CODES#TIRAMISU}
     * or lower, and when the game mode is set to {@link #GAME_MODE_CUSTOM} which is available in
     * {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE} or newer, this API will return
     * {@link #GAME_MODE_STANDARD} instead for backward compatibility.
     */
    public @GameMode int getGameMode() {
        try {
            return mService.getGameMode(mContext.getPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return getGameModeImpl(mContext.getPackageName(),
                mContext.getApplicationInfo().targetSdkVersion);
    }

    /**
     * Gets the game mode for the given package.
     * <p>
     * The caller must have {@link android.Manifest.permission#MANAGE_GAME_MODE}.
     * <p>
     * Also see {@link #getGameMode()} on how it handles SDK version compatibility.
     *
     * @hide
     */
@@ -113,11 +130,32 @@ public final class GameManager {
    @UserHandleAware
    @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
    public @GameMode int getGameMode(@NonNull String packageName) {
        final int targetSdkVersion;
        try {
            return mService.getGameMode(packageName, mContext.getUserId());
            final ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(
                    packageName, PackageManager.ApplicationInfoFlags.of(0));
            targetSdkVersion = applicationInfo.targetSdkVersion;
        } catch (PackageManager.NameNotFoundException ex) {
            return GAME_MODE_UNSUPPORTED;
        }
        return getGameModeImpl(packageName, targetSdkVersion);
    }

    // This target SDK version check can be performed against any game by a privileged app, and
    // we don't want a binder call each time to check on behalf of an app using CompatChange.
    @SuppressWarnings("AndroidFrameworkCompatChange")
    private @GameMode int getGameModeImpl(@NonNull String packageName, int targetSdkVersion) {
        final int gameMode;
        try {
            gameMode = mService.getGameMode(packageName,
                    mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        if (gameMode == GAME_MODE_CUSTOM && targetSdkVersion <= Build.VERSION_CODES.TIRAMISU) {
            return GAME_MODE_STANDARD;
        }
        return gameMode;
    }

    /**
+8 −0
Original line number Diff line number Diff line
@@ -63,6 +63,10 @@ public final class GameManagerTests {
        mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE);
        assertEquals(GameManager.GAME_MODE_PERFORMANCE,
                mGameManager.getGameMode());

        mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_CUSTOM);
        assertEquals(GameManager.GAME_MODE_CUSTOM,
                mGameManager.getGameMode());
    }

    @Test
@@ -77,5 +81,9 @@ public final class GameManagerTests {
        mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_PERFORMANCE);
        assertEquals(GameManager.GAME_MODE_PERFORMANCE,
                mGameManager.getGameMode(mPackageName));

        mGameManager.setGameMode(mPackageName, GameManager.GAME_MODE_CUSTOM);
        assertEquals(GameManager.GAME_MODE_CUSTOM,
                mGameManager.getGameMode(mPackageName));
    }
}