Loading core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -11093,6 +11093,7 @@ package android.service.games { method public void onCreate(); method public void onDestroy(); method public void onGameTaskFocusChanged(boolean); method public void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY) 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 +42 −2 Original line number Diff line number Diff line Loading @@ -83,6 +83,15 @@ public abstract class GameSession { GameSession::doDestroy, GameSession.this)); } @Override public void onTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture) { Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage( GameSession::dispatchTransientSystemBarVisibilityFromRevealGestureChanged, GameSession.this, visibleDueToGesture)); } @Override public void onTaskFocusChanged(boolean focused) { Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage( Loading @@ -109,6 +118,7 @@ public abstract class GameSession { } private LifecycleState mLifecycleState = LifecycleState.INITIALIZED; private boolean mAreTransientInsetsVisibleDueToGesture = false; private IGameSessionController mGameSessionController; private int mTaskId; private GameSessionRootView mGameSessionRootView; Loading Loading @@ -138,11 +148,23 @@ public abstract class GameSession { } @Hide void doDestroy() { private void doDestroy() { mSurfaceControlViewHost.release(); moveToState(LifecycleState.DESTROYED); } /** @hide */ @VisibleForTesting @MainThread public void dispatchTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture) { boolean didValueChange = mAreTransientInsetsVisibleDueToGesture != visibleDueToGesture; mAreTransientInsetsVisibleDueToGesture = visibleDueToGesture; if (didValueChange) { onTransientSystemBarVisibilityFromRevealGestureChanged(visibleDueToGesture); } } /** * @hide */ Loading Loading @@ -252,7 +274,23 @@ public abstract class GameSession { * * @param focused True if the game task is focused, false if the game task is unfocused. */ public void onGameTaskFocusChanged(boolean focused) {} public void onGameTaskFocusChanged(boolean focused) { } /** * Called when the visibility of the transient system bars changed due to the user performing * the reveal gesture. The reveal gesture is defined as a swipe to reveal the transient system * bars that originates from the system bars. * * @param visibleDueToGesture if the transient bars triggered by the reveal gesture are visible. * This is {@code true} when the transient system bars become visible * due to user performing the reveal gesture. This is {@code false} * when the transient system bars are hidden or become permanently * visible. */ public void onTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture) { } /** * Sets the task overlay content to an explicit view. This view is placed directly into the game Loading Loading @@ -344,12 +382,14 @@ public abstract class GameSession { /** * Called when taking the screenshot failed. * * @param statusCode Indicates the reason for failure. */ void onFailure(@ScreenshotFailureStatus int statusCode); /** * Called when taking the screenshot succeeded. * * @param bitmap The screenshot. */ void onSuccess(@NonNull Bitmap bitmap); Loading core/java/android/service/games/IGameSession.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -21,5 +21,6 @@ package android.service.games; */ oneway interface IGameSession { void onDestroyed(); void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean visibleDueToGesture); void onTaskFocusChanged(boolean focused); } services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java +49 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ServiceConnector; import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerInternal.TaskSystemBarsListener; import com.android.server.wm.WindowManagerService; import java.util.List; Loading @@ -62,6 +63,18 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan private static final int CREATE_GAME_SESSION_TIMEOUT_MS = 10_000; private static final boolean DEBUG = false; private final TaskSystemBarsListener mTaskSystemBarsVisibilityListener = new TaskSystemBarsListener() { @Override public void onTransientSystemBarsVisibilityChanged( int taskId, boolean visible, boolean wereRevealedFromSwipeOnSystemBar) { GameServiceProviderInstanceImpl.this.onTransientSystemBarsVisibilityChanged( taskId, visible, wereRevealedFromSwipeOnSystemBar); } }; private final TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException { Loading Loading @@ -203,6 +216,8 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } catch (RemoteException e) { Slog.w(TAG, "Failed to register task stack listener", e); } mWindowManagerInternal.registerTaskSystemBarsListener(mTaskSystemBarsVisibilityListener); } @GuardedBy("mLock") Loading @@ -218,6 +233,9 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan Slog.w(TAG, "Failed to unregister task stack listener", e); } mWindowManagerInternal.unregisterTaskSystemBarsListener( mTaskSystemBarsVisibilityListener); for (GameSessionRecord gameSessionRecord : mGameSessions.values()) { destroyGameSessionFromRecord(gameSessionRecord); } Loading Loading @@ -307,6 +325,37 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } } private void onTransientSystemBarsVisibilityChanged( int taskId, boolean visible, boolean wereRevealedFromSwipeOnSystemBar) { if (visible && !wereRevealedFromSwipeOnSystemBar) { return; } GameSessionRecord gameSessionRecord; synchronized (mLock) { gameSessionRecord = mGameSessions.get(taskId); } if (gameSessionRecord == null) { return; } IGameSession gameSession = gameSessionRecord.getGameSession(); if (gameSession == null) { return; } try { gameSession.onTransientSystemBarVisibilityFromRevealGestureChanged(visible); } catch (RemoteException ex) { Slog.w(TAG, "Failed to send transient system bars visibility from reveal gesture for task: " + taskId); } } private void createGameSession(int taskId) { synchronized (mLock) { createGameSessionLocked(taskId); Loading services/core/java/com/android/server/wm/InsetsPolicy.java +44 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityTaskManager; import android.app.StatusBarManager; import android.graphics.Insets; import android.graphics.Rect; Loading Loading @@ -181,6 +182,10 @@ class InsetsPolicy { mShowingTransientTypes.toArray(), isGestureOnSystemBar); } updateBarControlTarget(mFocusedWin); dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, isTransient(ITYPE_STATUS_BAR) || isTransient(ITYPE_NAVIGATION_BAR), isGestureOnSystemBar); // The leashes can be created while updating bar control target. The surface transaction // of the new leashes might not be applied yet. The callback posted here ensures we can Loading @@ -198,6 +203,12 @@ class InsetsPolicy { if (mShowingTransientTypes.size() == 0) { return; } dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, /* areVisible= */ false, /* wereRevealedFromSwipeOnSystemBar= */ false); startAnimation(false /* show */, () -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { Loading Loading @@ -373,6 +384,11 @@ class InsetsPolicy { mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); } mShowingTransientTypes.clear(); dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, /* areVisible= */ false, /* wereRevealedFromSwipeOnSystemBar= */ false); } private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin, Loading Loading @@ -521,6 +537,32 @@ class InsetsPolicy { listener.mControlCallbacks.controlAnimationUnchecked(typesReady, controls, show); } private void dispatchTransientSystemBarsVisibilityChanged( @Nullable WindowState focusedWindow, boolean areVisible, boolean wereRevealedFromSwipeOnSystemBar) { if (focusedWindow == null) { return; } Task task = focusedWindow.getTask(); if (task == null) { return; } int taskId = task.mTaskId; boolean isValidTaskId = taskId != ActivityTaskManager.INVALID_TASK_ID; if (!isValidTaskId) { return; } mDisplayContent.mWmService.mTaskSystemBarsListenerController .dispatchTransientSystemBarVisibilityChanged( taskId, areVisible, wereRevealedFromSwipeOnSystemBar); } private class BarWindow { private final int mId; Loading Loading
core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -11093,6 +11093,7 @@ package android.service.games { method public void onCreate(); method public void onDestroy(); method public void onGameTaskFocusChanged(boolean); method public void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_GAME_ACTIVITY) 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 +42 −2 Original line number Diff line number Diff line Loading @@ -83,6 +83,15 @@ public abstract class GameSession { GameSession::doDestroy, GameSession.this)); } @Override public void onTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture) { Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage( GameSession::dispatchTransientSystemBarVisibilityFromRevealGestureChanged, GameSession.this, visibleDueToGesture)); } @Override public void onTaskFocusChanged(boolean focused) { Handler.getMain().executeOrSendMessage(PooledLambda.obtainMessage( Loading @@ -109,6 +118,7 @@ public abstract class GameSession { } private LifecycleState mLifecycleState = LifecycleState.INITIALIZED; private boolean mAreTransientInsetsVisibleDueToGesture = false; private IGameSessionController mGameSessionController; private int mTaskId; private GameSessionRootView mGameSessionRootView; Loading Loading @@ -138,11 +148,23 @@ public abstract class GameSession { } @Hide void doDestroy() { private void doDestroy() { mSurfaceControlViewHost.release(); moveToState(LifecycleState.DESTROYED); } /** @hide */ @VisibleForTesting @MainThread public void dispatchTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture) { boolean didValueChange = mAreTransientInsetsVisibleDueToGesture != visibleDueToGesture; mAreTransientInsetsVisibleDueToGesture = visibleDueToGesture; if (didValueChange) { onTransientSystemBarVisibilityFromRevealGestureChanged(visibleDueToGesture); } } /** * @hide */ Loading Loading @@ -252,7 +274,23 @@ public abstract class GameSession { * * @param focused True if the game task is focused, false if the game task is unfocused. */ public void onGameTaskFocusChanged(boolean focused) {} public void onGameTaskFocusChanged(boolean focused) { } /** * Called when the visibility of the transient system bars changed due to the user performing * the reveal gesture. The reveal gesture is defined as a swipe to reveal the transient system * bars that originates from the system bars. * * @param visibleDueToGesture if the transient bars triggered by the reveal gesture are visible. * This is {@code true} when the transient system bars become visible * due to user performing the reveal gesture. This is {@code false} * when the transient system bars are hidden or become permanently * visible. */ public void onTransientSystemBarVisibilityFromRevealGestureChanged( boolean visibleDueToGesture) { } /** * Sets the task overlay content to an explicit view. This view is placed directly into the game Loading Loading @@ -344,12 +382,14 @@ public abstract class GameSession { /** * Called when taking the screenshot failed. * * @param statusCode Indicates the reason for failure. */ void onFailure(@ScreenshotFailureStatus int statusCode); /** * Called when taking the screenshot succeeded. * * @param bitmap The screenshot. */ void onSuccess(@NonNull Bitmap bitmap); Loading
core/java/android/service/games/IGameSession.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -21,5 +21,6 @@ package android.service.games; */ oneway interface IGameSession { void onDestroyed(); void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean visibleDueToGesture); void onTaskFocusChanged(boolean focused); }
services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java +49 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.infra.AndroidFuture; import com.android.internal.infra.ServiceConnector; import com.android.server.wm.WindowManagerInternal; import com.android.server.wm.WindowManagerInternal.TaskSystemBarsListener; import com.android.server.wm.WindowManagerService; import java.util.List; Loading @@ -62,6 +63,18 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan private static final int CREATE_GAME_SESSION_TIMEOUT_MS = 10_000; private static final boolean DEBUG = false; private final TaskSystemBarsListener mTaskSystemBarsVisibilityListener = new TaskSystemBarsListener() { @Override public void onTransientSystemBarsVisibilityChanged( int taskId, boolean visible, boolean wereRevealedFromSwipeOnSystemBar) { GameServiceProviderInstanceImpl.this.onTransientSystemBarsVisibilityChanged( taskId, visible, wereRevealedFromSwipeOnSystemBar); } }; private final TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException { Loading Loading @@ -203,6 +216,8 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } catch (RemoteException e) { Slog.w(TAG, "Failed to register task stack listener", e); } mWindowManagerInternal.registerTaskSystemBarsListener(mTaskSystemBarsVisibilityListener); } @GuardedBy("mLock") Loading @@ -218,6 +233,9 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan Slog.w(TAG, "Failed to unregister task stack listener", e); } mWindowManagerInternal.unregisterTaskSystemBarsListener( mTaskSystemBarsVisibilityListener); for (GameSessionRecord gameSessionRecord : mGameSessions.values()) { destroyGameSessionFromRecord(gameSessionRecord); } Loading Loading @@ -307,6 +325,37 @@ final class GameServiceProviderInstanceImpl implements GameServiceProviderInstan } } private void onTransientSystemBarsVisibilityChanged( int taskId, boolean visible, boolean wereRevealedFromSwipeOnSystemBar) { if (visible && !wereRevealedFromSwipeOnSystemBar) { return; } GameSessionRecord gameSessionRecord; synchronized (mLock) { gameSessionRecord = mGameSessions.get(taskId); } if (gameSessionRecord == null) { return; } IGameSession gameSession = gameSessionRecord.getGameSession(); if (gameSession == null) { return; } try { gameSession.onTransientSystemBarVisibilityFromRevealGestureChanged(visible); } catch (RemoteException ex) { Slog.w(TAG, "Failed to send transient system bars visibility from reveal gesture for task: " + taskId); } } private void createGameSession(int taskId) { synchronized (mLock) { createGameSessionLocked(taskId); Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +44 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityTaskManager; import android.app.StatusBarManager; import android.graphics.Insets; import android.graphics.Rect; Loading Loading @@ -181,6 +182,10 @@ class InsetsPolicy { mShowingTransientTypes.toArray(), isGestureOnSystemBar); } updateBarControlTarget(mFocusedWin); dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, isTransient(ITYPE_STATUS_BAR) || isTransient(ITYPE_NAVIGATION_BAR), isGestureOnSystemBar); // The leashes can be created while updating bar control target. The surface transaction // of the new leashes might not be applied yet. The callback posted here ensures we can Loading @@ -198,6 +203,12 @@ class InsetsPolicy { if (mShowingTransientTypes.size() == 0) { return; } dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, /* areVisible= */ false, /* wereRevealedFromSwipeOnSystemBar= */ false); startAnimation(false /* show */, () -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) { Loading Loading @@ -373,6 +384,11 @@ class InsetsPolicy { mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); } mShowingTransientTypes.clear(); dispatchTransientSystemBarsVisibilityChanged( mFocusedWin, /* areVisible= */ false, /* wereRevealedFromSwipeOnSystemBar= */ false); } private @Nullable InsetsControlTarget getStatusControlTarget(@Nullable WindowState focusedWin, Loading Loading @@ -521,6 +537,32 @@ class InsetsPolicy { listener.mControlCallbacks.controlAnimationUnchecked(typesReady, controls, show); } private void dispatchTransientSystemBarsVisibilityChanged( @Nullable WindowState focusedWindow, boolean areVisible, boolean wereRevealedFromSwipeOnSystemBar) { if (focusedWindow == null) { return; } Task task = focusedWindow.getTask(); if (task == null) { return; } int taskId = task.mTaskId; boolean isValidTaskId = taskId != ActivityTaskManager.INVALID_TASK_ID; if (!isValidTaskId) { return; } mDisplayContent.mWmService.mTaskSystemBarsListenerController .dispatchTransientSystemBarVisibilityChanged( taskId, areVisible, wereRevealedFromSwipeOnSystemBar); } private class BarWindow { private final int mId; Loading