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.app; 18 19 import android.annotation.NonNull; 20 import android.annotation.SystemApi; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.util.ArrayMap; 24 25 import androidx.annotation.Nullable; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 29 import java.util.Arrays; 30 import java.util.Map; 31 32 /** 33 * GameModeInfo returned from {@link GameManager#getGameModeInfo(String)}. 34 * 35 * Developers can enable game modes or interventions by adding 36 * <pre>{@code 37 * <meta-data android:name="android.game_mode_intervention" 38 * android:resource="@xml/GAME_MODE_CONFIG_FILE" /> 39 * }</pre> 40 * to the <pre>{@code <application>}</pre>, where the GAME_MODE_CONFIG_FILE is an XML file that 41 * specifies the game mode enablement and intervention configuration: 42 * <pre>{@code 43 * <game-mode-config xmlns:android="http://schemas.android.com/apk/res/android" 44 * android:gameModePerformance="true" 45 * android:gameModeBattery="false" 46 * android:allowGameDownscaling="true" 47 * android:allowGameFpsOverride="false" 48 * /> 49 * }</pre> 50 * 51 * @hide 52 */ 53 @SystemApi 54 public final class GameModeInfo implements Parcelable { 55 56 public static final @NonNull Creator<GameModeInfo> CREATOR = new Creator<GameModeInfo>() { 57 @Override 58 public GameModeInfo createFromParcel(Parcel in) { 59 return new GameModeInfo(in); 60 } 61 62 @Override 63 public GameModeInfo[] newArray(int size) { 64 return new GameModeInfo[size]; 65 } 66 }; 67 68 /** 69 * Builder for {@link GameModeInfo}. 70 * 71 * @hide 72 */ 73 @SystemApi 74 public static final class Builder { 75 /** Constructs a new Builder for a game mode info. */ Builder()76 public Builder() { 77 } 78 79 /** 80 * Sets the available game modes. 81 */ 82 @NonNull setAvailableGameModes( @onNull @ameManager.GameMode int[] availableGameModes)83 public GameModeInfo.Builder setAvailableGameModes( 84 @NonNull @GameManager.GameMode int[] availableGameModes) { 85 mAvailableGameModes = availableGameModes; 86 return this; 87 } 88 89 /** 90 * Sets the overridden game modes. 91 */ 92 @NonNull setOverriddenGameModes( @onNull @ameManager.GameMode int[] overriddenGameModes)93 public GameModeInfo.Builder setOverriddenGameModes( 94 @NonNull @GameManager.GameMode int[] overriddenGameModes) { 95 mOverriddenGameModes = overriddenGameModes; 96 return this; 97 } 98 99 /** 100 * Sets the active game mode. 101 */ 102 @NonNull setActiveGameMode( @onNull @ameManager.GameMode int activeGameMode)103 public GameModeInfo.Builder setActiveGameMode( 104 @NonNull @GameManager.GameMode int activeGameMode) { 105 mActiveGameMode = activeGameMode; 106 return this; 107 } 108 109 /** 110 * Sets the downscaling intervention flag. 111 */ 112 @NonNull setDownscalingAllowed(boolean allowed)113 public GameModeInfo.Builder setDownscalingAllowed(boolean allowed) { 114 mIsDownscalingAllowed = allowed; 115 return this; 116 } 117 118 /** 119 * Sets the FPS override flag. 120 */ 121 @NonNull setFpsOverrideAllowed(boolean allowed)122 public GameModeInfo.Builder setFpsOverrideAllowed(boolean allowed) { 123 mIsFpsOverrideAllowed = allowed; 124 return this; 125 } 126 127 /** 128 * Sets the GameModeConfiguration for a game mode. 129 */ 130 @NonNull setGameModeConfiguration( @ameManager.GameMode int gameMode, @NonNull GameModeConfiguration gameModeConfiguration)131 public GameModeInfo.Builder setGameModeConfiguration( 132 @GameManager.GameMode int gameMode, 133 @NonNull GameModeConfiguration gameModeConfiguration) { 134 mConfigMap.put(gameMode, gameModeConfiguration); 135 return this; 136 } 137 138 /** 139 * Builds a GameModeInfo. 140 */ 141 @NonNull build()142 public GameModeInfo build() { 143 return new GameModeInfo(mActiveGameMode, mAvailableGameModes, mOverriddenGameModes, 144 mIsDownscalingAllowed, mIsFpsOverrideAllowed, mConfigMap); 145 } 146 147 private @GameManager.GameMode int[] mAvailableGameModes = new int[]{}; 148 private @GameManager.GameMode int[] mOverriddenGameModes = new int[]{}; 149 private @GameManager.GameMode int mActiveGameMode; 150 private boolean mIsDownscalingAllowed; 151 private boolean mIsFpsOverrideAllowed; 152 private Map<Integer, GameModeConfiguration> mConfigMap = new ArrayMap<>(); 153 } 154 155 /** 156 * Creates a game mode info. 157 * 158 * @deprecated Use the {@link Builder} instead. 159 */ GameModeInfo(@ameManager.GameMode int activeGameMode, @NonNull @GameManager.GameMode int[] availableGameModes)160 public GameModeInfo(@GameManager.GameMode int activeGameMode, 161 @NonNull @GameManager.GameMode int[] availableGameModes) { 162 this(activeGameMode, availableGameModes, new int[]{}, true, true, new ArrayMap<>()); 163 } 164 GameModeInfo(@ameManager.GameMode int activeGameMode, @NonNull @GameManager.GameMode int[] availableGameModes, @NonNull @GameManager.GameMode int[] overriddenGameModes, boolean isDownscalingAllowed, boolean isFpsOverrideAllowed, @NonNull Map<Integer, GameModeConfiguration> configMap)165 private GameModeInfo(@GameManager.GameMode int activeGameMode, 166 @NonNull @GameManager.GameMode int[] availableGameModes, 167 @NonNull @GameManager.GameMode int[] overriddenGameModes, boolean isDownscalingAllowed, 168 boolean isFpsOverrideAllowed, @NonNull Map<Integer, GameModeConfiguration> configMap) { 169 mActiveGameMode = activeGameMode; 170 mAvailableGameModes = Arrays.copyOf(availableGameModes, availableGameModes.length); 171 mOverriddenGameModes = Arrays.copyOf(overriddenGameModes, overriddenGameModes.length); 172 mIsDownscalingAllowed = isDownscalingAllowed; 173 mIsFpsOverrideAllowed = isFpsOverrideAllowed; 174 mConfigMap = configMap; 175 } 176 177 /** @hide */ 178 @VisibleForTesting GameModeInfo(Parcel in)179 public GameModeInfo(Parcel in) { 180 mActiveGameMode = in.readInt(); 181 mAvailableGameModes = in.createIntArray(); 182 mOverriddenGameModes = in.createIntArray(); 183 mIsDownscalingAllowed = in.readBoolean(); 184 mIsFpsOverrideAllowed = in.readBoolean(); 185 mConfigMap = new ArrayMap<>(); 186 in.readMap(mConfigMap, 187 getClass().getClassLoader(), Integer.class, GameModeConfiguration.class); 188 } 189 190 /** 191 * Returns the {@link GameManager.GameMode} the application is currently using. 192 */ getActiveGameMode()193 public @GameManager.GameMode int getActiveGameMode() { 194 return mActiveGameMode; 195 } 196 197 /** 198 * Gets the collection of {@link GameManager.GameMode} that can be applied to the game. 199 * <p> 200 * Available games include all game modes that are either supported by the OEM in device 201 * config, or overridden by the game developers in game mode config XML, plus the default 202 * enabled modes for any game including {@link GameManager#GAME_MODE_STANDARD} and 203 * {@link GameManager#GAME_MODE_CUSTOM}. 204 * <p> 205 * Also see {@link GameModeInfo}. 206 */ 207 @NonNull getAvailableGameModes()208 public @GameManager.GameMode int[] getAvailableGameModes() { 209 return Arrays.copyOf(mAvailableGameModes, mAvailableGameModes.length); 210 } 211 212 /** 213 * Gets the collection of {@link GameManager.GameMode} that are overridden by the game. 214 * <p> 215 * Also see {@link GameModeInfo}. 216 */ 217 @NonNull getOverriddenGameModes()218 public @GameManager.GameMode int[] getOverriddenGameModes() { 219 return Arrays.copyOf(mOverriddenGameModes, mOverriddenGameModes.length); 220 } 221 222 /** 223 * Gets the current game mode configuration of a game mode. 224 * <p> 225 * The game mode can be null if it's overridden by the game itself, or not configured in device 226 * config nor set by the user as custom game mode configuration. 227 */ getGameModeConfiguration( @ameManager.GameMode int gameMode)228 public @Nullable GameModeConfiguration getGameModeConfiguration( 229 @GameManager.GameMode int gameMode) { 230 return mConfigMap.get(gameMode); 231 } 232 233 /** 234 * Returns if downscaling is allowed (not opted out) by the game in their Game Mode config. 235 * <p> 236 * Also see {@link GameModeInfo}. 237 */ isDownscalingAllowed()238 public boolean isDownscalingAllowed() { 239 return mIsDownscalingAllowed; 240 } 241 242 /** 243 * Returns if FPS override is allowed (not opted out) by the game in their Game Mode config. 244 * <p> 245 * Also see {@link GameModeInfo}. 246 */ isFpsOverrideAllowed()247 public boolean isFpsOverrideAllowed() { 248 return mIsFpsOverrideAllowed; 249 } 250 251 252 private final @GameManager.GameMode int[] mAvailableGameModes; 253 private final @GameManager.GameMode int[] mOverriddenGameModes; 254 private final @GameManager.GameMode int mActiveGameMode; 255 private final boolean mIsDownscalingAllowed; 256 private final boolean mIsFpsOverrideAllowed; 257 private final Map<Integer, GameModeConfiguration> mConfigMap; 258 259 @Override describeContents()260 public int describeContents() { 261 return 0; 262 } 263 264 @Override writeToParcel(@onNull Parcel dest, int flags)265 public void writeToParcel(@NonNull Parcel dest, int flags) { 266 dest.writeInt(mActiveGameMode); 267 dest.writeIntArray(mAvailableGameModes); 268 dest.writeIntArray(mOverriddenGameModes); 269 dest.writeBoolean(mIsDownscalingAllowed); 270 dest.writeBoolean(mIsFpsOverrideAllowed); 271 dest.writeMap(mConfigMap); 272 } 273 } 274