Loading core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -11184,6 +11184,7 @@ package android.service.games { method public void onCreate(); method public void onDestroy(); method public void onGameTaskFocusChanged(boolean); method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public final boolean restartGame(); method public void setTaskOverlayView(@NonNull android.view.View, @NonNull android.view.ViewGroup.LayoutParams); method public void takeScreenshot(@NonNull java.util.concurrent.Executor, @NonNull android.service.games.GameSession.ScreenshotCallback); } core/java/android/service/games/GameSession.java +20 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.Hide; import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; import android.content.res.Configuration; Loading Loading @@ -270,6 +271,25 @@ public abstract class GameSession { mGameSessionRootView.addView(view, layoutParams); } /** * Attempts to force stop and relaunch the game associated with the current session. This may * be useful, for example, after applying settings that will not take effect until the game is * restarted. * * @return {@code true} if the game was successfully restarted; otherwise, {@code false}. */ @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public final boolean restartGame() { try { mGameSessionController.restartGame(mTaskId); } catch (RemoteException e) { Slog.w(TAG, "Failed to restart game", e); return false; } return true; } /** * Root view of the {@link SurfaceControlViewHost} associated with the {@link GameSession} * instance. It is responsible for observing changes in the size of the window and resizing Loading core/java/android/service/games/IGameSessionController.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.service.games; import android.content.Intent; import com.android.internal.infra.AndroidFuture; /** Loading @@ -23,4 +24,6 @@ import com.android.internal.infra.AndroidFuture; */ oneway interface IGameSessionController { void takeScreenshot(int taskId, in AndroidFuture gameScreenshotResultFuture); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)") void restartGame(in int taskId); } services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java +6 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.app; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.Context; import android.content.Intent; Loading @@ -36,17 +37,19 @@ final class GameServiceProviderInstanceFactoryImpl implements GameServiceProvide private final Context mContext; GameServiceProviderInstanceFactoryImpl(@NonNull Context context) { this.mContext = context; mContext = context; } @NonNull @Override public GameServiceProviderInstance create(@NonNull GameServiceProviderConfiguration gameServiceProviderConfiguration) { public GameServiceProviderInstance create( @NonNull GameServiceProviderConfiguration gameServiceProviderConfiguration) { return new GameServiceProviderInstanceImpl( gameServiceProviderConfiguration.getUserHandle(), BackgroundThread.getExecutor(), mContext, new GameClassifierImpl(mContext.getPackageManager()), ActivityManager.getService(), ActivityTaskManager.getService(), (WindowManagerService) ServiceManager.getService(Context.WINDOW_SERVICE), LocalServices.getService(WindowManagerInternal.class), Loading services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java +44 −0 Original line number Diff line number Diff line Loading @@ -16,13 +16,18 @@ package com.android.server.app; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; import android.app.IActivityManager; import android.app.IActivityTaskManager; import android.app.TaskStackListener; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Rect; import android.os.RemoteException; Loading Loading @@ -110,12 +115,23 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan gameScreenshotResultFuture); }); } @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void restartGame(int taskId) { mContext.enforceCallingPermission(Manifest.permission.FORCE_STOP_PACKAGES, "restartGame()"); mBackgroundExecutor.execute(() -> { GameServiceProviderInstanceImpl.this.restartGame(taskId); }); } }; private final Object mLock = new Object(); private final UserHandle mUserHandle; private final Executor mBackgroundExecutor; private final Context mContext; private final GameClassifier mGameClassifier; private final IActivityManager mActivityManager; private final IActivityTaskManager mActivityTaskManager; private final WindowManagerService mWindowManagerService; private final WindowManagerInternal mWindowManagerInternal; Loading @@ -131,7 +147,9 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan GameServiceProviderInstanceImpl( @NonNull UserHandle userHandle, @NonNull Executor backgroundExecutor, @NonNull Context context, @NonNull GameClassifier gameClassifier, @NonNull IActivityManager activityManager, @NonNull IActivityTaskManager activityTaskManager, @NonNull WindowManagerService windowManagerService, @NonNull WindowManagerInternal windowManagerInternal, Loading @@ -139,7 +157,9 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan @NonNull ServiceConnector<IGameSessionService> gameSessionServiceConnector) { mUserHandle = userHandle; mBackgroundExecutor = backgroundExecutor; mContext = context; mGameClassifier = gameClassifier; mActivityManager = activityManager; mActivityTaskManager = activityTaskManager; mWindowManagerService = windowManagerService; mWindowManagerInternal = windowManagerInternal; Loading Loading @@ -310,6 +330,7 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan + ") is not awaiting game session request. Ignoring."); return; } mGameSessions.put(taskId, existingGameSessionRecord.withGameSessionRequested()); GameSessionViewHostConfiguration gameSessionViewHostConfiguration = createViewHostConfigurationForTask(taskId); Loading Loading @@ -532,4 +553,27 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } }); } private void restartGame(int taskId) { String packageName; synchronized (mLock) { boolean isTaskAssociatedWithGameSession = mGameSessions.containsKey(taskId); if (!isTaskAssociatedWithGameSession) { return; } packageName = mGameSessions.get(taskId).getComponentName().getPackageName(); } try { mActivityManager.forceStopPackage(packageName, UserHandle.USER_CURRENT); } catch (RemoteException e) { e.rethrowFromSystemServer(); } Intent launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName); mContext.startActivity(launchIntent); } } Loading
core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -11184,6 +11184,7 @@ package android.service.games { method public void onCreate(); method public void onDestroy(); method public void onGameTaskFocusChanged(boolean); method @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public final boolean restartGame(); method public void setTaskOverlayView(@NonNull android.view.View, @NonNull android.view.ViewGroup.LayoutParams); method public void takeScreenshot(@NonNull java.util.concurrent.Executor, @NonNull android.service.games.GameSession.ScreenshotCallback); }
core/java/android/service/games/GameSession.java +20 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.annotation.Hide; import android.annotation.IntDef; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; import android.content.res.Configuration; Loading Loading @@ -270,6 +271,25 @@ public abstract class GameSession { mGameSessionRootView.addView(view, layoutParams); } /** * Attempts to force stop and relaunch the game associated with the current session. This may * be useful, for example, after applying settings that will not take effect until the game is * restarted. * * @return {@code true} if the game was successfully restarted; otherwise, {@code false}. */ @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public final boolean restartGame() { try { mGameSessionController.restartGame(mTaskId); } catch (RemoteException e) { Slog.w(TAG, "Failed to restart game", e); return false; } return true; } /** * Root view of the {@link SurfaceControlViewHost} associated with the {@link GameSession} * instance. It is responsible for observing changes in the size of the window and resizing Loading
core/java/android/service/games/IGameSessionController.aidl +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.service.games; import android.content.Intent; import com.android.internal.infra.AndroidFuture; /** Loading @@ -23,4 +24,6 @@ import com.android.internal.infra.AndroidFuture; */ oneway interface IGameSessionController { void takeScreenshot(int taskId, in AndroidFuture gameScreenshotResultFuture); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)") void restartGame(in int taskId); }
services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java +6 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.app; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.Context; import android.content.Intent; Loading @@ -36,17 +37,19 @@ final class GameServiceProviderInstanceFactoryImpl implements GameServiceProvide private final Context mContext; GameServiceProviderInstanceFactoryImpl(@NonNull Context context) { this.mContext = context; mContext = context; } @NonNull @Override public GameServiceProviderInstance create(@NonNull GameServiceProviderConfiguration gameServiceProviderConfiguration) { public GameServiceProviderInstance create( @NonNull GameServiceProviderConfiguration gameServiceProviderConfiguration) { return new GameServiceProviderInstanceImpl( gameServiceProviderConfiguration.getUserHandle(), BackgroundThread.getExecutor(), mContext, new GameClassifierImpl(mContext.getPackageManager()), ActivityManager.getService(), ActivityTaskManager.getService(), (WindowManagerService) ServiceManager.getService(Context.WINDOW_SERVICE), LocalServices.getService(WindowManagerInternal.class), Loading
services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java +44 −0 Original line number Diff line number Diff line Loading @@ -16,13 +16,18 @@ package com.android.server.app; import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityTaskManager; import android.app.IActivityManager; import android.app.IActivityTaskManager; import android.app.TaskStackListener; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Rect; import android.os.RemoteException; Loading Loading @@ -110,12 +115,23 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan gameScreenshotResultFuture); }); } @RequiresPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) public void restartGame(int taskId) { mContext.enforceCallingPermission(Manifest.permission.FORCE_STOP_PACKAGES, "restartGame()"); mBackgroundExecutor.execute(() -> { GameServiceProviderInstanceImpl.this.restartGame(taskId); }); } }; private final Object mLock = new Object(); private final UserHandle mUserHandle; private final Executor mBackgroundExecutor; private final Context mContext; private final GameClassifier mGameClassifier; private final IActivityManager mActivityManager; private final IActivityTaskManager mActivityTaskManager; private final WindowManagerService mWindowManagerService; private final WindowManagerInternal mWindowManagerInternal; Loading @@ -131,7 +147,9 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan GameServiceProviderInstanceImpl( @NonNull UserHandle userHandle, @NonNull Executor backgroundExecutor, @NonNull Context context, @NonNull GameClassifier gameClassifier, @NonNull IActivityManager activityManager, @NonNull IActivityTaskManager activityTaskManager, @NonNull WindowManagerService windowManagerService, @NonNull WindowManagerInternal windowManagerInternal, Loading @@ -139,7 +157,9 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan @NonNull ServiceConnector<IGameSessionService> gameSessionServiceConnector) { mUserHandle = userHandle; mBackgroundExecutor = backgroundExecutor; mContext = context; mGameClassifier = gameClassifier; mActivityManager = activityManager; mActivityTaskManager = activityTaskManager; mWindowManagerService = windowManagerService; mWindowManagerInternal = windowManagerInternal; Loading Loading @@ -310,6 +330,7 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan + ") is not awaiting game session request. Ignoring."); return; } mGameSessions.put(taskId, existingGameSessionRecord.withGameSessionRequested()); GameSessionViewHostConfiguration gameSessionViewHostConfiguration = createViewHostConfigurationForTask(taskId); Loading Loading @@ -532,4 +553,27 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } }); } private void restartGame(int taskId) { String packageName; synchronized (mLock) { boolean isTaskAssociatedWithGameSession = mGameSessions.containsKey(taskId); if (!isTaskAssociatedWithGameSession) { return; } packageName = mGameSessions.get(taskId).getComponentName().getPackageName(); } try { mActivityManager.forceStopPackage(packageName, UserHandle.USER_CURRENT); } catch (RemoteException e) { e.rethrowFromSystemServer(); } Intent launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName); mContext.startActivity(launchIntent); } }