diff options
| author | 2024-09-18 00:08:08 -0700 | |
|---|---|---|
| committer | 2024-09-18 07:39:22 +0000 | |
| commit | 52b5d1e217f11cea085ae668d64d12b7383a0ba9 (patch) | |
| tree | 519d76f713e23da39c5da8e7ce7e9f9a05f57a4b | |
| parent | 1949d7ec441a259ed5c45d34f5ec82fddf424fb6 (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.java | 30 | ||||
| -rw-r--r-- | core/java/android/app/SystemServiceRegistry.java | 32 | ||||
| -rw-r--r-- | core/tests/GameManagerTests/src/android/app/GameManagerTests.java | 6 | ||||
| -rw-r--r-- | services/java/com/android/server/SystemServer.java | 10 | ||||
| -rw-r--r-- | services/java/com/android/server/flags.aconfig | 8 |
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 |