Merge "Game Loading Time improvement by boosting CPU via ADPF"

This commit is contained in:
Jim Blackler
2021-12-15 16:07:37 +00:00
committed by Android (Google) Code Review
9 changed files with 295 additions and 13 deletions

View File

@@ -5443,12 +5443,30 @@ package android.app {
public final class GameManager {
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_PERFORMANCE = 2; // 0x2
field public static final int GAME_MODE_STANDARD = 1; // 0x1
field public static final int GAME_MODE_UNSUPPORTED = 0; // 0x0
}
public final class GameState implements android.os.Parcelable {
ctor public GameState(boolean, int);
ctor public GameState(boolean, int, @Nullable String, @NonNull android.os.Bundle);
method public int describeContents();
method @Nullable public String getDescription();
method @NonNull public android.os.Bundle getMetadata();
method public int getMode();
method public boolean isLoading();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.app.GameState> CREATOR;
field public static final int MODE_CONTENT = 4; // 0x4
field public static final int MODE_GAMEPLAY_INTERRUPTIBLE = 2; // 0x2
field public static final int MODE_GAMEPLAY_UNINTERRUPTIBLE = 3; // 0x3
field public static final int MODE_NONE = 1; // 0x1
field public static final int MODE_UNKNOWN = 0; // 0x0
}
public class Instrumentation {
ctor public Instrumentation();
method public android.os.TestLooperManager acquireLooperManager(android.os.Looper);

View File

@@ -167,4 +167,16 @@ public final class GameManager {
throw e.rethrowFromSystemServer();
}
}
/**
* Called by games to communicate the current state to the platform.
* @param gameState An object set to the current state.
*/
public void setGameState(@NonNull GameState gameState) {
try {
mService.setGameState(mContext.getPackageName(), gameState, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
parcelable GameState;

View File

@@ -0,0 +1,179 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* State of the game passed to the GameManager.
*
* This includes a top-level state for the game (indicating if the game can be interrupted without
* interfering with content that can't be paused). Since content can be loaded in any state, it
* includes an independent boolean flag to indicate loading status.
*
* Free-form metadata (as a Bundle) and a string description can also be specified by the
* application.
*/
public final class GameState implements Parcelable {
/**
* Default Game mode is unknown.
*/
public static final int MODE_UNKNOWN = 0;
/**
* No mode means that the game is not in active play, for example the user is using the game
* menu.
*/
public static final int MODE_NONE = 1;
/**
* Indicates if the game is in active, but interruptible, game play.
*/
public static final int MODE_GAMEPLAY_INTERRUPTIBLE = 2;
/**
* Indicates if the game is in active user play mode, which is real time and cannot be
* interrupted.
*/
public static final int MODE_GAMEPLAY_UNINTERRUPTIBLE = 3;
/**
* Indicates that the current content shown is not gameplay related. For example it can be an
* ad, a web page, a text, or a video.
*/
public static final int MODE_CONTENT = 4;
/**
* Implement the parcelable interface.
*/
public static final @NonNull Creator<GameState> CREATOR = new Creator<GameState>() {
@Override
public GameState createFromParcel(Parcel in) {
return new GameState(in);
}
@Override
public GameState[] newArray(int size) {
return new GameState[size];
}
};
// Indicates if the game is loading assets/resources/compiling/etc. This is independent of game
// mode because there could be a loading UI displayed, or there could be loading in the
// background.
private final boolean mIsLoading;
// One of the states listed above.
private final @GameStateMode int mMode;
// This is a game specific description. For example can be level or scene name.
private final @Nullable String mDescription;
// This contains any other game specific parameters not covered by the fields above. It can be
// quality parameter data, settings, or game modes.
private final @NonNull Bundle mMetaData;
/**
* Create a GameState with the specified loading status.
* @param isLoading Whether the game is in the loading state.
* @param mode The game state mode of type @GameStateMode.
*/
public GameState(boolean isLoading, @GameStateMode int mode) {
this(isLoading, mode, null, new Bundle());
}
/**
* Create a GameState with the given state variables.
* @param isLoading Whether the game is in the loading state.
* @param mode The game state mode of type @GameStateMode.
* @param description An optional description of the state.
* @param metaData Optional metadata.
*/
public GameState(boolean isLoading, @GameStateMode int mode, @Nullable String description,
@NonNull Bundle metaData) {
mIsLoading = isLoading;
mMode = mode;
mDescription = description;
mMetaData = metaData;
}
private GameState(Parcel in) {
mIsLoading = in.readBoolean();
mMode = in.readInt();
mDescription = in.readString();
mMetaData = in.readBundle();
}
/**
* @return If the game is loading assets/resources/compiling/etc.
*/
public boolean isLoading() {
return mIsLoading;
}
/**
* @return The game state mode.
*/
public @GameStateMode int getMode() {
return mMode;
}
/**
* @return The state description, or null if one is not set.
*/
public @Nullable String getDescription() {
return mDescription;
}
/**
* @return metadata associated with the state.
*/
public @NonNull Bundle getMetadata() {
return mMetaData;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel parcel, int flags) {
parcel.writeBoolean(mIsLoading);
parcel.writeInt(mMode);
parcel.writeString(mDescription);
parcel.writeBundle(mMetaData);
}
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({MODE_UNKNOWN, MODE_NONE, MODE_GAMEPLAY_INTERRUPTIBLE, MODE_GAMEPLAY_UNINTERRUPTIBLE,
MODE_CONTENT
})
@interface GameStateMode {}
}

View File

@@ -16,6 +16,8 @@
package android.app;
import android.app.GameState;
/**
* @hide
*/
@@ -24,4 +26,5 @@ interface IGameManagerService {
void setGameMode(String packageName, int gameMode, int userId);
int[] getAvailableGameModes(String packageName);
boolean getAngleEnabled(String packageName, int userId);
void setGameState(String packageName, in GameState gameState, int userId);
}

View File

@@ -31,6 +31,7 @@ per-file SystemServiceRegistry.java = file:/services/core/java/com/android/serve
per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS
per-file UiAutomation.java = file:/services/accessibility/OWNERS
per-file GameManager* = file:/GAME_MANAGER_OWNERS
per-file GameState* = file:/GAME_MANAGER_OWNERS
per-file IGameManager* = file:/GAME_MANAGER_OWNERS
# ActivityThread

View File

@@ -129,8 +129,6 @@ java_library_static {
"android.hardware.common-V2-java",
"android.hardware.light-V2.0-java",
"android.hardware.gnss-V2-java",
"android.hardware.power-V1-java",
"android.hardware.power-V1.0-java",
"android.hardware.vibrator-V2-java",
"app-compat-annotations",
"framework-tethering.stubs.module_lib",
@@ -168,6 +166,7 @@ java_library_static {
"android.hardware.rebootescrow-V1-java",
"android.hardware.soundtrigger-V2.3-java",
"android.hardware.power.stats-V1-java",
"android.hardware.power-V3-java",
"android.hidl.manager-V1.2-java",
"capture_state_listener-aidl-java",
"icu4j_calendar_astronomer",

View File

@@ -42,6 +42,7 @@ import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.GameManager;
import android.app.GameManager.GameMode;
import android.app.GameState;
import android.app.IGameManagerService;
import android.app.compat.PackageOverride;
import android.content.BroadcastReceiver;
@@ -51,12 +52,15 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.power.Mode;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -72,6 +76,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.CompatibilityOverrideConfig;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.SystemService.TargetUser;
@@ -95,11 +100,14 @@ public final class GameManagerService extends IGameManagerService.Stub {
static final int WRITE_SETTINGS = 1;
static final int REMOVE_SETTINGS = 2;
static final int POPULATE_GAME_MODE_SETTINGS = 3;
static final int SET_GAME_STATE = 4;
static final int WRITE_SETTINGS_DELAY = 10 * 1000; // 10 seconds
static final PackageOverride COMPAT_ENABLED = new PackageOverride.Builder().setEnabled(true)
.build();
static final PackageOverride COMPAT_DISABLED = new PackageOverride.Builder().setEnabled(false)
.build();
private static final String PACKAGE_NAME_MSG_KEY = "packageName";
private static final String USER_ID_MSG_KEY = "userId";
private final Context mContext;
private final Object mLock = new Object();
@@ -107,6 +115,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
private final Handler mHandler;
private final PackageManager mPackageManager;
private final IPlatformCompat mPlatformCompat;
private final PowerManagerInternal mPowerManagerInternal;
private DeviceConfigListener mDeviceConfigListener;
@GuardedBy("mLock")
private final ArrayMap<Integer, GameManagerSettings> mSettings = new ArrayMap<>();
@@ -123,6 +132,7 @@ public final class GameManagerService extends IGameManagerService.Stub {
mPackageManager = mContext.getPackageManager();
mPlatformCompat = IPlatformCompat.Stub.asInterface(
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
}
@Override
@@ -200,6 +210,19 @@ public final class GameManagerService extends IGameManagerService.Stub {
updateConfigsForUser(userId, packageNames);
break;
}
case SET_GAME_STATE: {
if (mPowerManagerInternal == null) {
final Bundle data = msg.getData();
Slog.d(TAG, "Error setting loading mode for package "
+ data.getString(PACKAGE_NAME_MSG_KEY)
+ " and userId " + data.getInt(USER_ID_MSG_KEY));
break;
}
final GameState gameState = (GameState) msg.obj;
final boolean isLoading = gameState.isLoading();
mPowerManagerInternal.setPowerMode(Mode.GAME_LOADING, isLoading);
break;
}
}
}
}
@@ -257,6 +280,32 @@ public final class GameManagerService extends IGameManagerService.Stub {
return 0;
}
/**
* Called by games to communicate the current state to the platform.
* @param packageName The client package name.
* @param gameState An object set to the current state.
* @param userId The user associated with this state.
*/
public void setGameState(String packageName, @NonNull GameState gameState, int userId) {
if (!isPackageGame(packageName, userId)) {
// Restrict to games only.
return;
}
if (getGameMode(packageName, userId) != GameManager.GAME_MODE_PERFORMANCE) {
// Requires performance mode to be enabled.
return;
}
final Message msg = mHandler.obtainMessage(SET_GAME_STATE);
final Bundle data = new Bundle();
data.putString(PACKAGE_NAME_MSG_KEY, packageName);
data.putInt(USER_ID_MSG_KEY, userId);
msg.setData(data);
msg.obj = gameState;
mHandler.sendMessage(msg);
}
/**
* GamePackageConfiguration manages all game mode config details for its associated package.
*/
@@ -639,6 +688,16 @@ public final class GameManagerService extends IGameManagerService.Stub {
return getGameModeFromSettings(packageName, userId);
}
private boolean isPackageGame(String packageName, int userId) {
try {
final ApplicationInfo applicationInfo = mPackageManager
.getApplicationInfoAsUser(packageName, PackageManager.MATCH_ALL, userId);
return applicationInfo.category == ApplicationInfo.CATEGORY_GAME;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
/**
* Sets the Game Mode for the package name.
* Verifies that the calling process has {@link android.Manifest.permission#MANAGE_GAME_MODE}.
@@ -649,16 +708,8 @@ public final class GameManagerService extends IGameManagerService.Stub {
throws SecurityException {
checkPermission(Manifest.permission.MANAGE_GAME_MODE);
// Restrict to games only.
try {
final ApplicationInfo applicationInfo = mPackageManager
.getApplicationInfoAsUser(packageName, PackageManager.MATCH_ALL, userId);
if (applicationInfo.category != ApplicationInfo.CATEGORY_GAME) {
// Ignore attempt to set the game mode for applications that are not identified
// as game. See {@link PackageManager#setApplicationCategoryHint(String, int)}
return;
}
} catch (PackageManager.NameNotFoundException e) {
if (!isPackageGame(packageName, userId)) {
// Restrict to games only.
return;
}

View File

@@ -163,7 +163,7 @@ cc_defaults {
"android.hardware.memtrack-V1-ndk",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
"android.hardware.power-V2-cpp",
"android.hardware.power-V3-cpp",
"android.hardware.power.stats@1.0",
"android.hardware.power.stats-V1-ndk",
"android.hardware.thermal@1.0",