Introduce GameSession.onTransientSystemBarsVisibilityFromRevealGestureChanged(...)

Adds support for a GameSession to detect when the transient system bars
are revealed and hidden using the GameSession reveal gesture.

Test: Manual e2e testing
Bug: 210119966
Bug: 202414447
Bug: 202417255
CTS-Coverage-Bug: 206128693
Change-Id: I614f9aeae65d6be6e3262ef58011612062036b35
This commit is contained in:
David Samuelson
2022-01-28 05:30:43 +00:00
parent 53fef98a25
commit 36764e4895
10 changed files with 369 additions and 12 deletions

View File

@@ -11074,6 +11074,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);

View File

@@ -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(
@@ -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);

View File

@@ -21,5 +21,6 @@ package android.service.games;
*/
oneway interface IGameSession {
void onDestroyed();
void onTransientSystemBarVisibilityFromRevealGestureChanged(boolean visibleDueToGesture);
void onTaskFocusChanged(boolean focused);
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
});
}
}

View File

@@ -255,6 +255,25 @@ public abstract class WindowManagerInternal {
public void onAppTransitionFinishedLocked(IBinder token) {}
}
/**
* 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.
*/
@@ -518,6 +537,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.
*

View File

@@ -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();
@@ -7590,6 +7592,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) {

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}