diff options
| author | 2022-02-02 04:26:31 +0000 | |
|---|---|---|
| committer | 2022-02-02 04:26:31 +0000 | |
| commit | 8dfa0b9fa03fdb35e3236efcd47a31a013dec088 (patch) | |
| tree | 36742006e1bfa3d911f305d6f9a1b1ae628fe712 | |
| parent | 813624d64da744d9071769ded84beb2e4241f9b2 (diff) | |
| parent | 36764e48959bf3d2f17b7bbe1563a9c1f1aaabbd (diff) | |
Merge "Introduce GameSession.onTransientSystemBarsVisibilityFromRevealGestureChanged(...)"
10 files changed, 369 insertions, 12 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt index c7be8d3c48d7..83e472d6128d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -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); diff --git a/core/java/android/service/games/GameSession.java b/core/java/android/service/games/GameSession.java index 9590933cf2da..e33f1801129b 100644 --- a/core/java/android/service/games/GameSession.java +++ b/core/java/android/service/games/GameSession.java @@ -84,6 +84,15 @@ public abstract class GameSession { } @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( GameSession::moveToState, GameSession.this, @@ -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; @@ -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 */ @@ -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 @@ -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); diff --git a/core/java/android/service/games/IGameSession.aidl b/core/java/android/service/games/IGameSession.aidl index 71da6302b63d..49c36c6a301c 100644 --- a/core/java/android/service/games/IGameSession.aidl +++ b/core/java/android/service/games/IGameSession.aidl @@ -21,5 +21,6 @@ package android.service.games; */ oneway interface IGameSession { void onDestroyed(); + void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean visibleDueToGesture); void onTaskFocusChanged(boolean focused); } diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java index af1dd335ab1e..960fbf1d9330 100644 --- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java +++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java @@ -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; @@ -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 { @@ -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") @@ -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); } @@ -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); diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 10776abee51e..1e121737e2ac 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -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; @@ -134,7 +135,7 @@ class InsetsPolicy { /** Updates the target which can control system bars. */ void updateBarControlTarget(@Nullable WindowState focusedWin) { - if (mFocusedWin != focusedWin){ + if (mFocusedWin != focusedWin) { abortTransient(); } mFocusedWin = focusedWin; @@ -156,7 +157,7 @@ class InsetsPolicy { } boolean isHidden(@InternalInsetsType int type) { - final InsetsSourceProvider provider = mStateController.peekSourceProvider(type); + final InsetsSourceProvider provider = mStateController.peekSourceProvider(type); return provider != null && provider.hasWindow() && !provider.getSource().isVisible(); } @@ -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 @@ -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--) { @@ -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, @@ -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; diff --git a/services/core/java/com/android/server/wm/TaskSystemBarsListenerController.java b/services/core/java/com/android/server/wm/TaskSystemBarsListenerController.java new file mode 100644 index 000000000000..acb6061de93f --- /dev/null +++ b/services/core/java/com/android/server/wm/TaskSystemBarsListenerController.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 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 com.android.server.wm; + +import com.android.internal.os.BackgroundThread; +import com.android.server.wm.WindowManagerInternal.TaskSystemBarsListener; + +import java.util.HashSet; +import java.util.concurrent.Executor; + +/** + * Manages dispatch of task system bar changes to interested listeners. All invocations must be + * performed while the {@link WindowManagerService#getWindowManagerLock() Window Manager Lock} is + * held. + */ +final class TaskSystemBarsListenerController { + + private final HashSet<TaskSystemBarsListener> mListeners = new HashSet<>(); + private final Executor mBackgroundExecutor; + + TaskSystemBarsListenerController() { + this.mBackgroundExecutor = BackgroundThread.getExecutor(); + } + + void registerListener(TaskSystemBarsListener listener) { + mListeners.add(listener); + } + + void unregisterListener(TaskSystemBarsListener listener) { + mListeners.remove(listener); + } + + void dispatchTransientSystemBarVisibilityChanged( + int taskId, + boolean visible, + boolean wereRevealedFromSwipeOnSystemBar) { + HashSet<TaskSystemBarsListener> localListeners; + localListeners = new HashSet<>(mListeners); + + mBackgroundExecutor.execute(() -> { + for (TaskSystemBarsListener listener : localListeners) { + listener.onTransientSystemBarsVisibilityChanged( + taskId, + visible, + wereRevealedFromSwipeOnSystemBar); + } + }); + } +} diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index 20fa7a9da256..4900f9292f2a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -256,6 +256,25 @@ public abstract class WindowManagerInternal { } /** + * An interface to be notified when the system bars for a task change. + */ + public interface TaskSystemBarsListener { + + /** + * Called when the visibility of the system bars of a task change. + * + * @param taskId the identifier of the task. + * @param visible if the transient system bars are visible. + * @param wereRevealedFromSwipeOnSystemBar if the transient bars were revealed due to a + * swipe gesture on a system bar. + */ + void onTransientSystemBarsVisibilityChanged( + int taskId, + boolean visible, + boolean wereRevealedFromSwipeOnSystemBar); + } + + /** * An interface to be notified when keyguard exit animation should start. */ public interface KeyguardExitAnimationStartListener { @@ -519,6 +538,20 @@ public abstract class WindowManagerInternal { public abstract void registerAppTransitionListener(AppTransitionListener listener); /** + * Registers a listener to be notified to when the system bars of a task changes. + * + * @param listener The listener to register. + */ + public abstract void registerTaskSystemBarsListener(TaskSystemBarsListener listener); + + /** + * Registers a listener to be notified to when the system bars of a task changes. + * + * @param listener The listener to unregister. + */ + public abstract void unregisterTaskSystemBarsListener(TaskSystemBarsListener listener); + + /** * Registers a listener to be notified to start the keyguard exit animation. * * @param listener The listener to register. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b37cb4f286f9..50467a98f5ad 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -683,6 +683,7 @@ public class WindowManagerService extends IWindowManager.Stub () -> mDisplayRotationController = null; final DisplayWindowListenerController mDisplayNotificationController; + final TaskSystemBarsListenerController mTaskSystemBarsListenerController; boolean mDisplayFrozen = false; long mDisplayFreezeTime = 0; @@ -1265,6 +1266,7 @@ public class WindowManagerService extends IWindowManager.Stub mScreenFrozenLock.setReferenceCounted(false); mDisplayNotificationController = new DisplayWindowListenerController(this); + mTaskSystemBarsListenerController = new TaskSystemBarsListenerController(); mActivityManager = ActivityManager.getService(); mActivityTaskManager = ActivityTaskManager.getService(); @@ -7591,6 +7593,20 @@ public class WindowManagerService extends IWindowManager.Stub } @Override + public void registerTaskSystemBarsListener(TaskSystemBarsListener listener) { + synchronized (mGlobalLock) { + mTaskSystemBarsListenerController.registerListener(listener); + } + } + + @Override + public void unregisterTaskSystemBarsListener(TaskSystemBarsListener listener) { + synchronized (mGlobalLock) { + mTaskSystemBarsListenerController.unregisterListener(listener); + } + } + + @Override public void registerKeyguardExitAnimationStartListener( KeyguardExitAnimationStartListener listener) { synchronized (mGlobalLock) { diff --git a/services/tests/mockingservicestests/src/android/service/games/GameSessionTest.java b/services/tests/mockingservicestests/src/android/service/games/GameSessionTest.java index fec9b1249d17..e89c812ba1fb 100644 --- a/services/tests/mockingservicestests/src/android/service/games/GameSessionTest.java +++ b/services/tests/mockingservicestests/src/android/service/games/GameSessionTest.java @@ -359,6 +359,34 @@ public final class GameSessionTest { LifecycleTrackingGameSession.LifecycleMethodCall.ON_DESTROY).inOrder(); } + @Test + public void dispatchTransientVisibilityChanged_valueUnchanged_doesNotInvokeCallback() { + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(false); + + assertThat(mGameSession.mCapturedTransientSystemBarVisibilityFromRevealGestures).hasSize(0); + } + + @Test + public void dispatchTransientVisibilityChanged_valueChanged_invokesCallback() { + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(true); + + assertThat(mGameSession.mCapturedTransientSystemBarVisibilityFromRevealGestures) + .containsExactly(true).inOrder(); + } + + @Test + public void dispatchTransientVisibilityChanged_manyTimes_invokesCallbackWhenValueChanges() { + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(false); + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(true); + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(false); + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(false); + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(true); + mGameSession.dispatchTransientSystemBarVisibilityFromRevealGestureChanged(true); + + assertThat(mGameSession.mCapturedTransientSystemBarVisibilityFromRevealGestures) + .containsExactly(true, false, true).inOrder(); + } + private static class LifecycleTrackingGameSession extends GameSession { private enum LifecycleMethodCall { ON_CREATE, @@ -368,6 +396,8 @@ public final class GameSessionTest { } final List<LifecycleMethodCall> mLifecycleMethodCalls = new ArrayList<>(); + final List<Boolean> mCapturedTransientSystemBarVisibilityFromRevealGestures = + new ArrayList<>(); @Override public void onCreate() { @@ -387,5 +417,11 @@ public final class GameSessionTest { mLifecycleMethodCalls.add(LifecycleMethodCall.ON_GAME_TASK_UNFOCUSED); } } + + @Override + public void onTransientSystemBarVisibilityFromRevealGestureChanged( + boolean visibleDueToGesture) { + mCapturedTransientSystemBarVisibilityFromRevealGestures.add(visibleDueToGesture); + } } } diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java index 317a51b3fe2d..08de62bc6537 100644 --- a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java @@ -31,7 +31,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import android.Manifest; @@ -72,6 +71,7 @@ import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.FunctionalUtils.ThrowingConsumer; import com.android.internal.util.Preconditions; import com.android.server.wm.WindowManagerInternal; +import com.android.server.wm.WindowManagerInternal.TaskSystemBarsListener; import com.android.server.wm.WindowManagerService; import org.junit.After; @@ -112,6 +112,7 @@ public final class GameServiceProviderInstanceImplTest { private static final ComponentName GAME_B_MAIN_ACTIVITY = new ComponentName(GAME_B_PACKAGE, "com.package.game.b.MainActivity"); + private static final Bitmap TEST_BITMAP = Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888); private MockitoSession mMockingSession; @@ -131,6 +132,7 @@ public final class GameServiceProviderInstanceImplTest { private FakeGameSessionService mFakeGameSessionService; private FakeServiceConnector<IGameSessionService> mFakeGameSessionServiceConnector; private ArrayList<ITaskStackListener> mTaskStackListeners; + private ArrayList<TaskSystemBarsListener> mTaskSystemBarsListeners; private ArrayList<RunningTaskInfo> mRunningTaskInfos; @Mock @@ -159,15 +161,25 @@ public final class GameServiceProviderInstanceImplTest { mTaskStackListeners.add(invocation.getArgument(0)); return null; }).when(mMockActivityTaskManager).registerTaskStackListener(any()); + doAnswer(invocation -> { + mTaskStackListeners.remove(invocation.getArgument(0)); + return null; + }).when(mMockActivityTaskManager).unregisterTaskStackListener(any()); + + mTaskSystemBarsListeners = new ArrayList<>(); + doAnswer(invocation -> { + mTaskSystemBarsListeners.add(invocation.getArgument(0)); + return null; + }).when(mMockWindowManagerInternal).registerTaskSystemBarsListener(any()); + doAnswer(invocation -> { + mTaskSystemBarsListeners.remove(invocation.getArgument(0)); + return null; + }).when(mMockWindowManagerInternal).unregisterTaskSystemBarsListener(any()); mRunningTaskInfos = new ArrayList<>(); when(mMockActivityTaskManager.getTasks(anyInt(), anyBoolean(), anyBoolean())).thenReturn( mRunningTaskInfos); - doAnswer(invocation -> { - mTaskStackListeners.remove(invocation.getArgument(0)); - return null; - }).when(mMockActivityTaskManager).unregisterTaskStackListener(any()); mGameServiceProviderInstance = new GameServiceProviderInstanceImpl( new UserHandle(USER_ID), @@ -394,7 +406,60 @@ public final class GameServiceProviderInstanceImplTest { .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); verify(mMockWindowManagerInternal).addTaskOverlay(eq(10), eq(mockSurfacePackage10)); - verifyNoMoreInteractions(mMockWindowManagerInternal); + } + + @Test + public void taskSystemBarsListenerChanged_noAssociatedGameSession_doesNothing() { + mGameServiceProviderInstance.start(); + + dispatchTaskSystemBarsEvent(taskSystemBarsListener -> { + taskSystemBarsListener.onTransientSystemBarsVisibilityChanged( + 10, + /* areVisible= */ false, + /* wereRevealedFromSwipeOnSystemBar= */ false); + }); + } + + @Test + public void systemBarsTransientShownDueToGesture_hasGameSession_propagatesToGameSession() { + mGameServiceProviderInstance.start(); + startTask(10, GAME_A_MAIN_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + + dispatchTaskSystemBarsEvent(taskSystemBarsListener -> { + taskSystemBarsListener.onTransientSystemBarsVisibilityChanged( + 10, + /* areVisible= */ true, + /* wereRevealedFromSwipeOnSystemBar= */ true); + }); + + assertThat(gameSession10.mAreTransientSystemBarsVisibleFromRevealGesture).isTrue(); + } + + @Test + public void systemBarsTransientShownButNotGesture_hasGameSession_notPropagatedToGameSession() { + mGameServiceProviderInstance.start(); + startTask(10, GAME_A_MAIN_ACTIVITY); + mFakeGameService.requestCreateGameSession(10); + + FakeGameSession gameSession10 = new FakeGameSession(); + SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class); + mFakeGameSessionService.removePendingFutureForTaskId(10) + .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10)); + + dispatchTaskSystemBarsEvent(taskSystemBarsListener -> { + taskSystemBarsListener.onTransientSystemBarsVisibilityChanged( + 10, + /* areVisible= */ true, + /* wereRevealedFromSwipeOnSystemBar= */ false); + }); + + assertThat(gameSession10.mAreTransientSystemBarsVisibleFromRevealGesture).isFalse(); } @Test @@ -492,7 +557,6 @@ public final class GameServiceProviderInstanceImplTest { verify(mMockWindowManagerInternal).addTaskOverlay(eq(10), eq(mockSurfacePackage10)); verify(mMockWindowManagerInternal).removeTaskOverlay(eq(10), eq(mockSurfacePackage10)); - verifyNoMoreInteractions(mMockWindowManagerInternal); } @Test @@ -830,6 +894,13 @@ public final class GameServiceProviderInstanceImplTest { mMockContext.setPermission(permission, PackageManager.PERMISSION_DENIED); } + private void dispatchTaskSystemBarsEvent( + ThrowingConsumer<TaskSystemBarsListener> taskSystemBarsListenerConsumer) { + for (TaskSystemBarsListener listener : mTaskSystemBarsListeners) { + taskSystemBarsListenerConsumer.accept(listener); + } + } + static final class FakeGameService extends IGameService.Stub { private IGameServiceController mGameServiceController; @@ -944,6 +1015,7 @@ public final class GameServiceProviderInstanceImplTest { private static class FakeGameSession extends IGameSession.Stub { boolean mIsDestroyed = false; boolean mIsFocused = false; + boolean mAreTransientSystemBarsVisibleFromRevealGesture = false; @Override public void onDestroyed() { @@ -954,6 +1026,11 @@ public final class GameServiceProviderInstanceImplTest { public void onTaskFocusChanged(boolean focused) { mIsFocused = focused; } + + @Override + public void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean areVisible) { + mAreTransientSystemBarsVisibleFromRevealGesture = areVisible; + } } private final class MockContext extends ContextWrapper { @@ -1005,5 +1082,4 @@ public final class GameServiceProviderInstanceImplTest { return mLastStartedIntent; } } - } |