summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yeabkal Wubshit <yeabkal@google.com> 2024-09-18 00:08:08 -0700
committer Yeabkal Wubshit <yeabkal@google.com> 2024-09-18 07:39:22 +0000
commit52b5d1e217f11cea085ae668d64d12b7383a0ba9 (patch)
tree519d76f713e23da39c5da8e7ce7e9f9a05f57a4b
parent1949d7ec441a259ed5c45d34f5ec82fddf424fb6 (diff)
Remove GameManagerService from Wear
This change removes the GameManagerService from Wear devices. Consequently, the GameManager client API will have no use for Wear devices. Thus, GameManager is now also allowed to be not published by Wear devices. To avoid affecting existing apps that may be interacting with a GameManager instance, we are guarding the absence of GameManager with an app target SDK check. Apps that target an SDK prior to this change will still be able to get a GameManager instance, but it will be no-op. The public documentation has also been updated to reflect these new changes. Bug: 340929737 Test: atest CtsGameManagerTestCases CtsGameFrameRateTestCases GameManagerTests Flag: android.server.remove_game_manager_service_from_wear Change-Id: Id5affc748a97b7204ebf4c61a198ebd87d757a2a
-rw-r--r--core/java/android/app/GameManager.java30
-rw-r--r--core/java/android/app/SystemServiceRegistry.java32
-rw-r--r--core/tests/GameManagerTests/src/android/app/GameManagerTests.java6
-rw-r--r--services/java/com/android/server/SystemServer.java10
-rw-r--r--services/java/com/android/server/flags.aconfig8
5 files changed, 74 insertions, 12 deletions
diff --git a/core/java/android/app/GameManager.java b/core/java/android/app/GameManager.java
index c6fa064a6b0f..12deaec08f53 100644
--- a/core/java/android/app/GameManager.java
+++ b/core/java/android/app/GameManager.java
@@ -29,16 +29,24 @@ 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;
-import android.os.ServiceManager.ServiceNotFoundException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* The GameManager allows system apps to modify and query the game mode of apps.
+ *
+ * <p><b>Note:</b> After {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}, some devices
+ * that do not support the GameManager features <i>may</i> not publish a GameManager instance.
+ * These device types include:
+ * <ul>
+ * <li> Wear devices ({@link PackageManager#FEATURE_WATCH})
+ * </ul>
+ *
+ * <p>Therefore, you should always do a {@code null} check on the return value of
+ * {@link Context#getSystemService(Class)} and {@link Context#getSystemService(String)} when trying
+ * to obtain an instance of GameManager on the aforementioned device types.
*/
@SystemService(Context.GAME_SERVICE)
public final class GameManager {
@@ -46,7 +54,7 @@ public final class GameManager {
private static final String TAG = "GameManager";
private final @Nullable Context mContext;
- private final IGameManagerService mService;
+ private final @Nullable IGameManagerService mService;
/** @hide */
@IntDef(flag = false, prefix = {"GAME_MODE_"}, value = {
@@ -92,10 +100,9 @@ public final class GameManager {
*/
public static final int GAME_MODE_CUSTOM = 4;
- GameManager(Context context, Handler handler) throws ServiceNotFoundException {
+ GameManager(Context context, @Nullable IGameManagerService service) {
mContext = context;
- mService = IGameManagerService.Stub.asInterface(
- ServiceManager.getServiceOrThrow(Context.GAME_SERVICE));
+ mService = service;
}
/**
@@ -145,6 +152,7 @@ public final class GameManager {
// 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) {
+ if (mService == null) return GAME_MODE_UNSUPPORTED;
final int gameMode;
try {
gameMode = mService.getGameMode(packageName,
@@ -176,6 +184,7 @@ public final class GameManager {
@UserHandleAware
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public @Nullable GameModeInfo getGameModeInfo(@NonNull String packageName) {
+ if (mService == null) return null;
try {
return mService.getGameModeInfo(packageName, mContext.getUserId());
} catch (RemoteException e) {
@@ -196,6 +205,7 @@ public final class GameManager {
@UserHandleAware
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public void setGameMode(@NonNull String packageName, @GameMode int gameMode) {
+ if (mService == null) return;
try {
mService.setGameMode(packageName, gameMode, mContext.getUserId());
} catch (RemoteException e) {
@@ -212,6 +222,7 @@ public final class GameManager {
*/
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public @GameMode int[] getAvailableGameModes(@NonNull String packageName) {
+ if (mService == null) return new int[0];
try {
return mService.getAvailableGameModes(packageName, mContext.getUserId());
} catch (RemoteException e) {
@@ -232,6 +243,7 @@ public final class GameManager {
@TestApi
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public boolean isAngleEnabled(@NonNull String packageName) {
+ if (mService == null) return false;
try {
return mService.isAngleEnabled(packageName, mContext.getUserId());
} catch (RemoteException e) {
@@ -246,6 +258,7 @@ public final class GameManager {
*/
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public void notifyGraphicsEnvironmentSetup() {
+ if (mService == null) return;
try {
mService.notifyGraphicsEnvironmentSetup(
mContext.getPackageName(), mContext.getUserId());
@@ -259,6 +272,7 @@ public final class GameManager {
* @param gameState An object set to the current state.
*/
public void setGameState(@NonNull GameState gameState) {
+ if (mService == null) return;
try {
mService.setGameState(mContext.getPackageName(), gameState, mContext.getUserId());
} catch (RemoteException e) {
@@ -275,6 +289,7 @@ public final class GameManager {
*/
@TestApi
public void setGameServiceProvider(@Nullable String packageName) {
+ if (mService == null) return;
try {
mService.setGameServiceProvider(packageName);
} catch (RemoteException e) {
@@ -296,6 +311,7 @@ public final class GameManager {
@RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
public void updateCustomGameModeConfiguration(@NonNull String packageName,
@NonNull GameModeConfiguration gameModeConfig) {
+ if (mService == null) return;
try {
mService.updateCustomGameModeConfiguration(packageName, gameModeConfig,
mContext.getUserId());
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 03bec71548a8..c13a58f52ac8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -17,6 +17,7 @@
package android.app;
import static android.app.appfunctions.flags.Flags.enableAppFunctionManager;
+import static android.server.Flags.removeGameManagerServiceFromWear;
import android.accounts.AccountManager;
import android.accounts.IAccountManager;
@@ -74,6 +75,7 @@ import android.companion.virtual.IVirtualDeviceManager;
import android.companion.virtual.VirtualDeviceManager;
import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
import android.compat.annotation.EnabledSince;
import android.content.ClipboardManager;
import android.content.ContentCaptureOptions;
@@ -309,6 +311,16 @@ public final class SystemServiceRegistry {
static final long ENABLE_CHECKING_TELEPHONY_FEATURES_FOR_VCN = 330902016;
/**
+ * After {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, Wear devices will be allowed to publish
+ * no {@link GameManager} instance. This is because the respective system service is no longer
+ * started for Wear devices given that the applications of the service do not currently apply to
+ * Wear.
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ static final long NULL_GAME_MANAGER_IN_WEAR = 340929737;
+
+ /**
* The corresponding vendor API for Android V
*
* <p>Starting with Android V, the vendor API format has switched to YYYYMM.
@@ -1624,8 +1636,24 @@ public final class SystemServiceRegistry {
@Override
public GameManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- return new GameManager(ctx.getOuterContext(),
- ctx.mMainThread.getHandler());
+ final PackageManager pm = ctx.getPackageManager();
+ final boolean isWatch = pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ final IBinder binder =
+ // Allow a potentially absent GameManagerService only for
+ // Wear devices. For non-Wear devices, throw a
+ // ServiceNotFoundException when the service is missing.
+ (removeGameManagerServiceFromWear() && isWatch)
+ ? ServiceManager.getService(Context.GAME_SERVICE)
+ : ServiceManager.getServiceOrThrow(Context.GAME_SERVICE);
+
+ if (binder == null
+ && Compatibility.isChangeEnabled(NULL_GAME_MANAGER_IN_WEAR)) {
+ return null;
+ }
+
+ return new GameManager(
+ ctx.getOuterContext(),
+ IGameManagerService.Stub.asInterface(binder));
}
});
diff --git a/core/tests/GameManagerTests/src/android/app/GameManagerTests.java b/core/tests/GameManagerTests/src/android/app/GameManagerTests.java
index d34c91ee48ba..e81cdee940b4 100644
--- a/core/tests/GameManagerTests/src/android/app/GameManagerTests.java
+++ b/core/tests/GameManagerTests/src/android/app/GameManagerTests.java
@@ -22,7 +22,10 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
+import static org.junit.Assume.assumeNotNull;
+
import android.content.Context;
+import android.content.pm.PackageManager;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -47,6 +50,9 @@ public final class GameManagerTests {
public void setUp() {
mContext = getInstrumentation().getContext();
mGameManager = mContext.getSystemService(GameManager.class);
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ assumeNotNull(mGameManager);
+ }
mPackageName = mContext.getPackageName();
// Reset the Game Mode for the test app, since it persists across invocations.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ab459df1cdf6..7530b0ea93fb 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -3005,9 +3005,13 @@ public final class SystemServer implements Dumpable {
}
t.traceEnd();
- t.traceBegin("GameManagerService");
- mSystemServiceManager.startService(GameManagerService.Lifecycle.class);
- t.traceEnd();
+ if (!isWatch || !android.server.Flags.removeGameManagerServiceFromWear()) {
+ t.traceBegin("GameManagerService");
+ mSystemServiceManager.startService(GameManagerService.Lifecycle.class);
+ t.traceEnd();
+ } else {
+ Slog.d(TAG, "Not starting GameManagerService");
+ }
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
t.traceBegin("UwbService");
diff --git a/services/java/com/android/server/flags.aconfig b/services/java/com/android/server/flags.aconfig
index ec74ef191b81..09906912ef3f 100644
--- a/services/java/com/android/server/flags.aconfig
+++ b/services/java/com/android/server/flags.aconfig
@@ -35,4 +35,12 @@ flag {
namespace: "wear_systems"
description: "Allow NetworkTimeUpdateService on Wear"
bug: "327508176"
+}
+
+flag {
+ name: "remove_game_manager_service_from_wear"
+ namespace: "wear_frameworks"
+ description: "Remove GameManagerService from Wear"
+ bug: "340929737"
+ is_fixed_read_only: true
} \ No newline at end of file