1 /*
2  * Copyright (C) 2022 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.view.Display;
24 
25 import androidx.annotation.FloatRange;
26 import androidx.annotation.IntRange;
27 
28 import com.android.internal.annotations.Immutable;
29 import com.android.internal.util.Preconditions;
30 
31 /**
32  * GameModeConfiguration is the game's platform configuration for a game mode.
33  * <p>
34  * Only the game modes that are enabled by OEMs will have an active configuration, whereas game
35  * modes opted in by the game will not.
36  *
37  * @hide
38  */
39 @Immutable
40 @SystemApi
41 public final class GameModeConfiguration implements Parcelable {
42     // Default value indicating that no FPS override will be applied as game intervention, or
43     // default to the current display mode's frame rate.
44     public static final int FPS_OVERRIDE_NONE = 0;
45 
46     public static final @NonNull Creator<GameModeConfiguration> CREATOR = new Creator<>() {
47         @Override
48         public GameModeConfiguration createFromParcel(Parcel in) {
49             return new GameModeConfiguration(in);
50         }
51 
52         @Override
53         public GameModeConfiguration[] newArray(int size) {
54             return new GameModeConfiguration[size];
55         }
56     };
57 
58     /**
59      * Builder for {@link GameModeConfiguration}.
60      *
61      * @hide
62      */
63     @SystemApi
64     public static final class Builder {
65         /** Constructs a new Builder for a game mode’s configuration. */
Builder()66         public Builder() {
67         }
68 
69         /** Constructs a new builder by copying from an existing game mode configuration. */
Builder(@onNull GameModeConfiguration configuration)70         public Builder(@NonNull GameModeConfiguration configuration) {
71             mFpsOverride = configuration.mFpsOverride;
72             mScalingFactor = configuration.mScalingFactor;
73         }
74 
75         /**
76          * Sets the scaling factor used for game resolution downscaling.
77          * <br>
78          *
79          * @param scalingFactor the desired scaling factor ranged from 0.1 to 1.0 inclusively
80          * @throws IllegalArgumentException if the scaling factor is not in range of [0.1, 1.0]
81          */
82         @NonNull
setScalingFactor( @loatRangefrom = 0.1, to = 1.0) float scalingFactor)83         public GameModeConfiguration.Builder setScalingFactor(
84                 @FloatRange(from = 0.1, to = 1.0) float scalingFactor) {
85             Preconditions.checkArgument(scalingFactor >= 0.1 && scalingFactor <= 1.0,
86                     "Scaling factor should fall between 0.1 and 1.0 (inclusive)");
87             mScalingFactor = scalingFactor;
88             return this;
89         }
90 
91         /**
92          * Sets the FPS override used for game frame rate throttling.
93          * <br>
94          * The list of valid throttled frame rates can be queried by
95          * <ol>
96          * <li>Obtain display modes by calling {@link Display#getSupportedModes}
97          * <li>For each mode, get valid FPS by getting the divisor of the
98          * {@link Display.Mode#getRefreshRate()} that is >= 30,
99          * e.g. when Display.Mode#getRefreshRate() is 120 Hz, the valid FPS
100          * of this mode is 120, 60, 40, 30
101          * <li>Aggregate the valid FPS of each mode to get the full list
102          * </ol>
103          * <br>
104          *
105          * @param fpsOverride the desired non-negative FPS override value, default to
106          *                    {@link #FPS_OVERRIDE_NONE}.
107          * @throws IllegalArgumentException if the provided value is negative
108          */
109         @NonNull
setFpsOverride(@ntRangefrom = 0) int fpsOverride)110         public GameModeConfiguration.Builder setFpsOverride(@IntRange(from = 0) int fpsOverride) {
111             Preconditions.checkArgument(fpsOverride >= 0,
112                     "FPS override should be non-negative");
113             mFpsOverride = fpsOverride;
114             return this;
115         }
116 
117         /**
118          * Builds a GameModeConfiguration.
119          */
120         @NonNull
build()121         public GameModeConfiguration build() {
122             return new GameModeConfiguration(mScalingFactor, mFpsOverride);
123         }
124 
125         ;
126         private float mScalingFactor;
127         private int mFpsOverride;
128     }
129 
GameModeConfiguration(float scalingFactor, int fpsOverride)130     GameModeConfiguration(float scalingFactor, int fpsOverride) {
131         this.mScalingFactor = scalingFactor;
132         this.mFpsOverride = fpsOverride;
133     }
134 
GameModeConfiguration(Parcel in)135     GameModeConfiguration(Parcel in) {
136         this.mScalingFactor = in.readFloat();
137         this.mFpsOverride = in.readInt();
138     }
139 
140     @Override
describeContents()141     public int describeContents() {
142         return 0;
143     }
144 
145     @Override
writeToParcel(@onNull Parcel dest, int flags)146     public void writeToParcel(@NonNull Parcel dest, int flags) {
147         dest.writeFloat(mScalingFactor);
148         dest.writeInt(mFpsOverride);
149     }
150 
151     /**
152      * Gets the scaling factor used for game resolution downscaling.
153      */
getScalingFactor()154     public float getScalingFactor() {
155         return mScalingFactor;
156     }
157 
158     /**
159      * Gets the FPS override used for frame rate throttling.
160      */
getFpsOverride()161     public int getFpsOverride() {
162         return mFpsOverride;
163     }
164 
165     @Override
equals(Object obj)166     public boolean equals(Object obj) {
167         if (obj == this) {
168             return true;
169         }
170         if (!(obj instanceof GameModeConfiguration)) {
171             return false;
172         }
173         GameModeConfiguration config = (GameModeConfiguration) obj;
174         return config.mFpsOverride == this.mFpsOverride
175                 && config.mScalingFactor == this.mScalingFactor;
176     }
177 
178     @Override
hashCode()179     public int hashCode() {
180         int result = 7;
181         result = 31 * result + mFpsOverride;
182         result = 31 * result + Float.floatToIntBits(mScalingFactor);
183         return result;
184     }
185 
186     private final float mScalingFactor;
187     private final int mFpsOverride;
188 }
189