diff options
| author | 2021-05-12 03:00:13 +0000 | |
|---|---|---|
| committer | 2021-05-12 03:00:13 +0000 | |
| commit | 5ed9c4ca81ab715966942bc534abb83150eca2d8 (patch) | |
| tree | 169efe564761dac04722c29ef3dc62e46ee5c612 | |
| parent | 74a435858a4df85dcebae6e6dc7f110dffed07cf (diff) | |
| parent | 0b0634c4a9c132a6061387a03b9e6690a17ac521 (diff) | |
Merge "Fix hard dragging the window magnification from the bottom of the screen" into sc-dev
10 files changed, 393 insertions, 133 deletions
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index 927bce08268d..2cf3ad2dcd49 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -105,6 +105,8 @@ public class QuickStepContract { public static final int SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1 << 17; // The IME is showing public static final int SYSUI_STATE_IME_SHOWING = 1 << 18; + // The window magnification is overlapped with system gesture insets at the bottom. + public static final int SYSUI_STATE_MAGNIFICATION_OVERLAP = 1 << 19; @Retention(RetentionPolicy.SOURCE) @IntDef({SYSUI_STATE_SCREEN_PINNING, @@ -125,7 +127,8 @@ public class QuickStepContract { SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, SYSUI_STATE_ONE_HANDED_ACTIVE, SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY, - SYSUI_STATE_IME_SHOWING + SYSUI_STATE_IME_SHOWING, + SYSUI_STATE_MAGNIFICATION_OVERLAP }) public @interface SystemUiStateFlags {} @@ -153,6 +156,7 @@ public class QuickStepContract { str.add((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0 ? "allow_gesture" : ""); str.add((flags & SYSUI_STATE_IME_SHOWING) != 0 ? "ime_visible" : ""); + str.add((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0 ? "magnification_overlap" : ""); return str.toString(); } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java b/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java index b69001d1ba07..c472457b0206 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java @@ -63,17 +63,15 @@ abstract class DisplayIdIndexSupplier<T> { } /** - * Gets the object by the element index. + * Returns the object with the given display id. * - * <p> If the index is bigger than the array size, an {@link ArrayIndexOutOfBoundsException} is - * thrown for apps targeting {@link android.os.Build.VERSION_CODES#Q} and later </p> * - * @param index the element index + * @param displayId the logical display Id * @return T - * @see SparseArray#valueAt(int) */ - public T valueAt(int index) { - return mSparseArray.valueAt(index); + @Nullable + public T valueAt(int displayId) { + return mSparseArray.get(displayId); } @NonNull diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java index 4c892e29f386..4b30ec3e6f6f 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationGestureDetector.java @@ -113,7 +113,7 @@ class MagnificationGestureDetector { final float rawX = event.getRawX(); final float rawY = event.getRawY(); boolean handled = false; - switch (event.getAction()) { + switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mPointerDown.set(rawX, rawY); mHandler.postAtTime(mCancelTapGestureRunnable, diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java index 4f5fdc90e929..cee395bd9a6a 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java @@ -18,10 +18,11 @@ package com.android.systemui.accessibility; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; + import android.annotation.MainThread; import android.annotation.Nullable; import android.content.Context; -import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.hardware.display.DisplayManager; @@ -37,9 +38,13 @@ import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SystemUI; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.model.SysUiState; +import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; +import java.io.FileDescriptor; +import java.io.PrintWriter; + import javax.inject.Inject; /** @@ -52,34 +57,33 @@ import javax.inject.Inject; public class WindowMagnification extends SystemUI implements WindowMagnifierCallback, CommandQueue.Callbacks { private static final String TAG = "WindowMagnification"; - private static final int CONFIG_MASK = - ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION - | ActivityInfo.CONFIG_LOCALE; private final ModeSwitchesController mModeSwitchesController; private final Handler mHandler; private final AccessibilityManager mAccessibilityManager; private final CommandQueue mCommandQueue; + private final OverviewProxyService mOverviewProxyService; private WindowMagnificationConnectionImpl mWindowMagnificationConnectionImpl; private Configuration mLastConfiguration; + private SysUiState mSysUiState; private static class AnimationControllerSupplier extends DisplayIdIndexSupplier<WindowMagnificationAnimationController> { private final Context mContext; private final Handler mHandler; - private final NavigationModeController mNavigationModeController; private final WindowMagnifierCallback mWindowMagnifierCallback; + private final SysUiState mSysUiState; AnimationControllerSupplier(Context context, Handler handler, - NavigationModeController navigationModeController, - WindowMagnifierCallback windowMagnifierCallback, DisplayManager displayManager) { + WindowMagnifierCallback windowMagnifierCallback, + DisplayManager displayManager, SysUiState sysUiState) { super(displayManager); mContext = context; mHandler = handler; - mNavigationModeController = navigationModeController; mWindowMagnifierCallback = windowMagnifierCallback; + mSysUiState = sysUiState; } @Override @@ -89,10 +93,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall final WindowMagnificationController controller = new WindowMagnificationController( mContext, mHandler, new SfVsyncFrameCallbackProvider(), null, - new SurfaceControl.Transaction(), mWindowMagnifierCallback); - final int navBarMode = mNavigationModeController.addListener( - controller::onNavigationModeChanged); - controller.onNavigationModeChanged(navBarMode); + new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState); return new WindowMagnificationAnimationController(windowContext, controller); } } @@ -103,24 +104,22 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall @Inject public WindowMagnification(Context context, @Main Handler mainHandler, CommandQueue commandQueue, ModeSwitchesController modeSwitchesController, - NavigationModeController navigationModeController) { + SysUiState sysUiState, OverviewProxyService overviewProxyService) { super(context); mHandler = mainHandler; mLastConfiguration = new Configuration(context.getResources().getConfiguration()); mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class); mCommandQueue = commandQueue; mModeSwitchesController = modeSwitchesController; + mSysUiState = sysUiState; + mOverviewProxyService = overviewProxyService; mAnimationControllerSupplier = new AnimationControllerSupplier(context, - mHandler, navigationModeController, this, - context.getSystemService(DisplayManager.class)); + mHandler, this, context.getSystemService(DisplayManager.class), sysUiState); } @Override public void onConfigurationChanged(Configuration newConfig) { final int configDiff = newConfig.diff(mLastConfiguration); - if ((configDiff & CONFIG_MASK) == 0) { - return; - } mLastConfiguration.setTo(newConfig); mAnimationControllerSupplier.forEach( animationController -> animationController.onConfigurationChanged(configDiff)); @@ -132,6 +131,28 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall @Override public void start() { mCommandQueue.addCallback(this); + mOverviewProxyService.addCallback(new OverviewProxyService.OverviewProxyListener() { + @Override + public void onConnectionChanged(boolean isConnected) { + if (isConnected) { + updateSysUiStateFlag(); + } + } + }); + } + + private void updateSysUiStateFlag() { + //TODO(b/187510533): support multi-display once SysuiState supports it. + final WindowMagnificationAnimationController controller = + mAnimationControllerSupplier.valueAt(Display.DEFAULT_DISPLAY); + if (controller != null) { + controller.updateSysUiStateFlag(); + } else { + // The instance is initialized when there is an IPC request. Considering + // self-crash cases, we need to reset the flag in such situation. + mSysUiState.setFlag(SYSUI_STATE_MAGNIFICATION_OVERLAP, false) + .commitUpdate(Display.DEFAULT_DISPLAY); + } } @MainThread @@ -210,6 +231,13 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall } } + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println(TAG); + mAnimationControllerSupplier.forEach( + animationController -> animationController.dump(pw)); + } + private void setWindowMagnificationConnection() { if (mWindowMagnificationConnectionImpl == null) { mWindowMagnificationConnectionImpl = new WindowMagnificationConnectionImpl(this, diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java index 5758b1575f5a..36fef3ed6b51 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java @@ -31,6 +31,7 @@ import android.view.animation.AccelerateInterpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.R; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -269,6 +270,14 @@ class WindowMagnificationAnimationController implements ValueAnimator.AnimatorUp mController.enableWindowMagnification(sentScale, centerX, centerY); } + public void updateSysUiStateFlag() { + mController.updateSysUIStateFlag(); + } + + void dump(PrintWriter pw) { + mController.dump(pw); + } + private static ValueAnimator newValueAnimator(Resources resources) { final ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration( diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index ae16703405a5..fcb090a76d5b 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -16,9 +16,10 @@ package com.android.systemui.accessibility; +import static android.view.WindowInsets.Type.systemGestures; import static android.view.WindowManager.LayoutParams; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; + +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; @@ -28,6 +29,7 @@ import android.annotation.UiContext; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; +import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.PixelFormat; import android.graphics.Rect; @@ -52,14 +54,17 @@ import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.view.WindowMetrics; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.R; +import com.android.systemui.model.SysUiState; import com.android.systemui.shared.system.WindowManagerWrapper; +import java.io.PrintWriter; import java.text.NumberFormat; import java.util.Locale; @@ -111,6 +116,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private final View.OnLayoutChangeListener mMirrorSurfaceViewLayoutChangeListener; private final Runnable mMirrorViewRunnable; private final Runnable mUpdateStateDescriptionRunnable; + private final Runnable mWindowInsetChangeRunnable; private View mMirrorView; private SurfaceView mMirrorSurfaceView; private int mMirrorSurfaceMargin; @@ -119,9 +125,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private int mOuterBorderSize; // The boundary of magnification frame. private final Rect mMagnificationFrameBoundary = new Rect(); - - private int mNavBarMode; - private int mNavGestureHeight; + // The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid. + private int mSystemGestureTop = -1; private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; private final MagnificationGestureDetector mGestureDetector; @@ -130,6 +135,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold private Locale mLocale; private NumberFormat mPercentFormat; private float mBounceEffectAnimationScale; + private SysUiState mSysUiState; + // Set it to true when the view is overlapped with the gesture insets at the bottom. + private boolean mOverlapWithGestureInsets; @Nullable private MirrorWindowControl mMirrorWindowControl; @@ -137,11 +145,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold WindowMagnificationController(@UiContext Context context, @NonNull Handler handler, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, - @NonNull WindowMagnifierCallback callback) { + @NonNull WindowMagnifierCallback callback, SysUiState sysUiState) { mContext = context; mHandler = handler; mSfVsyncFrameProvider = sfVsyncFrameProvider; mWindowMagnifierCallback = callback; + mSysUiState = sysUiState; final Display display = mContext.getDisplay(); mDisplayId = mContext.getDisplayId(); @@ -170,13 +179,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorViewRunnable = () -> { if (mMirrorView != null) { mMirrorView.getBoundsOnScreen(mMirrorViewBounds); + updateSystemUIStateIfNeeded(); mWindowMagnifierCallback.onWindowMagnifierBoundsChanged( mDisplayId, mMirrorViewBounds); } }; mMirrorViewLayoutChangeListener = - (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + if (!mHandler.hasCallbacks(mMirrorViewRunnable)) { mHandler.post(mMirrorViewRunnable); + } + }; + mMirrorSurfaceViewLayoutChangeListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> applyTapExcludeRegion(); @@ -199,6 +213,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mMirrorView.setStateDescription(formatStateDescription(mScale)); } }; + mWindowInsetChangeRunnable = this::onWindowInsetChanged; } private void updateDimensions() { @@ -210,7 +225,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold R.dimen.magnification_drag_view_size); mOuterBorderSize = mResources.getDimensionPixelSize( R.dimen.magnification_outer_border_margin); - updateNavigationBarDimensions(); } private void computeBounceAnimationScale() { @@ -220,16 +234,16 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mBounceEffectAnimationScale = Math.min(animationScaleMax, ANIMATION_BOUNCE_EFFECT_SCALE); } - private void updateNavigationBarDimensions() { - if (!supportsSwipeUpGesture()) { - mNavGestureHeight = 0; - return; + private boolean updateSystemGestureInsetsTop() { + final WindowMetrics windowMetrics = mWm.getCurrentWindowMetrics(); + final Insets insets = windowMetrics.getWindowInsets().getInsets(systemGestures()); + final int gestureTop = + insets.bottom != 0 ? windowMetrics.getBounds().bottom - insets.bottom : -1; + if (gestureTop != mSystemGestureTop) { + mSystemGestureTop = gestureTop; + return true; } - mNavGestureHeight = (mWindowBounds.width() > mWindowBounds.height()) - ? mResources.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height_landscape) - : mResources.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_gesture_height); + return false; } /** @@ -255,6 +269,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if (mMirrorWindowControl != null) { mMirrorWindowControl.destroyControl(); } + updateSystemUIStateIfNeeded(); } /** @@ -277,6 +292,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold } } + private void updateSystemUIStateIfNeeded() { + updateSysUIState(false); + } + private void updateAccessibilityWindowTitleIfNeeded() { if (!isWindowVisible()) return; LayoutParams params = (LayoutParams) mMirrorView.getLayoutParams(); @@ -284,13 +303,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold mWm.updateViewLayout(mMirrorView, params); } - /** Handles MirrorWindow position when the navigation bar mode changed. */ - public void onNavigationModeChanged(int mode) { - mNavBarMode = mode; - updateNavigationBarDimensions(); - updateMirrorViewLayout(); - } - /** Handles MirrorWindow position when the device rotation changed. */ private void onRotate() { final Display display = mContext.getDisplay(); @@ -299,7 +311,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold setMagnificationFrameBoundary(); mRotation = display.getRotation(); - updateNavigationBarDimensions(); if (!isWindowVisible()) { return; @@ -351,6 +362,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold params.x = mMagnificationFrame.left - mMirrorSurfaceMargin; params.y = mMagnificationFrame.top - mMirrorSurfaceMargin; params.layoutInDisplayCutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + params.receiveInsetsIgnoringZOrder = true; params.setTitle(mContext.getString(R.string.magnification_window_title)); params.accessibilityTitle = getAccessibilityWindowTitle(); @@ -368,6 +380,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); mMirrorView.addOnLayoutChangeListener(mMirrorViewLayoutChangeListener); mMirrorView.setAccessibilityDelegate(new MirrorWindowA11yDelegate()); + mMirrorView.setOnApplyWindowInsetsListener((v, insets) -> { + if (!mHandler.hasCallbacks(mWindowInsetChangeRunnable)) { + mHandler.post(mWindowInsetChangeRunnable); + } + return v.onApplyWindowInsets(insets); + }); mWm.addView(mMirrorView, params); @@ -377,6 +395,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold addDragTouchListeners(); } + private void onWindowInsetChanged() { + if (updateSystemGestureInsetsTop()) { + updateSystemUIStateIfNeeded(); + } + } + private void applyTapExcludeRegion() { final Region tapExcludeRegion = calculateTapExclude(); final IWindow window = IWindow.Stub.asInterface(mMirrorView.getWindowToken()); @@ -464,17 +488,12 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return; } final int maxMirrorViewX = mWindowBounds.width() - mMirrorView.getWidth(); - final int maxMirrorViewY = - mWindowBounds.height() - mMirrorView.getHeight() - mNavGestureHeight; + final int maxMirrorViewY = mWindowBounds.height() - mMirrorView.getHeight(); + LayoutParams params = (LayoutParams) mMirrorView.getLayoutParams(); params.x = mMagnificationFrame.left - mMirrorSurfaceMargin; params.y = mMagnificationFrame.top - mMirrorSurfaceMargin; - // If nav bar mode supports swipe-up gesture, the Y position of mirror view should not - // overlap nav bar window to prevent window-dragging obscured. - if (supportsSwipeUpGesture()) { - params.y = Math.min(params.y, maxMirrorViewY); - } // Translates MirrorView position to make MirrorSurfaceView that is inside MirrorView // able to move close to the screen edges. @@ -508,6 +527,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return false; } + public void updateSysUIStateFlag() { + updateSysUIState(true); + } + /** * Calculates the desired source bounds. This will be the area under from the center of the * displayFrame, factoring in scale. @@ -569,6 +592,16 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return false; } + private void updateSysUIState(boolean force) { + final boolean overlap = isWindowVisible() && mSystemGestureTop > 0 + && mMirrorViewBounds.bottom > mSystemGestureTop; + if (force || overlap != mOverlapWithGestureInsets) { + mOverlapWithGestureInsets = overlap; + mSysUiState.setFlag(SYSUI_STATE_MAGNIFICATION_OVERLAP, mOverlapWithGestureInsets) + .commitUpdate(mDisplayId); + } + } + @Override public void surfaceCreated(SurfaceHolder holder) { createMirror(); @@ -676,10 +709,6 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold return mMirrorView != null; } - private boolean supportsSwipeUpGesture() { - return mNavBarMode == NAV_BAR_MODE_2BUTTON || mNavBarMode == NAV_BAR_MODE_GESTURAL; - } - private CharSequence formatStateDescription(float scale) { // Cache the locale-appropriate NumberFormat. Configuration locale is guaranteed // non-null, so the first time this is called we will always get the appropriate @@ -722,6 +751,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold scaleAnimator.start(); } + public void dump(PrintWriter pw) { + pw.println("WindowMagnificationController (displayId=" + mDisplayId + "):"); + pw.println(" mOverlapWithGestureInsets:" + mOverlapWithGestureInsets); + pw.println(" mScale:" + mScale); + pw.println(" mMirrorViewBounds:" + (isWindowVisible() ? mMirrorViewBounds : "empty")); + pw.println(" mSystemGestureTop:" + mSystemGestureTop); + } + private class MirrorWindowA11yDelegate extends View.AccessibilityDelegate { @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java index 1d9eaae4f233..77286b11f652 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java @@ -37,7 +37,8 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.model.SysUiState; +import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; import org.junit.Before; @@ -67,9 +68,12 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { @Mock private ModeSwitchesController mModeSwitchesController; @Mock - private NavigationModeController mNavigationModeController; + private SysUiState mSysUiState; @Mock private IRemoteMagnificationAnimationCallback mAnimationCallback; + @Mock + private OverviewProxyService mOverviewProxyService; + private IWindowMagnificationConnection mIWindowMagnificationConnection; private WindowMagnification mWindowMagnification; @@ -83,8 +87,8 @@ public class IWindowMagnificationConnectionTest extends SysuiTestCase { }).when(mAccessibilityManager).setWindowMagnificationConnection( any(IWindowMagnificationConnection.class)); mWindowMagnification = new WindowMagnification(getContext(), - getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController, - mNavigationModeController); + getContext().getMainThreadHandler(), mCommandQueue, + mModeSwitchesController, mSysUiState, mOverviewProxyService); mWindowMagnification.mAnimationControllerSupplier = new FakeAnimationControllerSupplier( mContext.getSystemService(DisplayManager.class)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java index 4e4c33a27da8..045fb57f11f9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java @@ -41,6 +41,7 @@ import androidx.test.filters.LargeTest; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SysuiTestCase; +import com.android.systemui.model.SysUiState; import org.junit.After; import org.junit.Before; @@ -83,6 +84,8 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { IRemoteMagnificationAnimationCallback mAnimationCallback; @Mock IRemoteMagnificationAnimationCallback mAnimationCallback2; + @Mock + SysUiState mSysUiState; private SpyWindowMagnificationController mController; private WindowMagnificationController mSpyController; private WindowMagnificationAnimationController mWindowMagnificationAnimationController; @@ -98,7 +101,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2; mController = new SpyWindowMagnificationController(mContext, mHandler, mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(), - mWindowMagnifierCallback); + mWindowMagnifierCallback, mSysUiState); mSpyController = mController.getSpyController(); mWindowMagnificationAnimationController = new WindowMagnificationAnimationController( mContext, mController, newValueAnimator()); @@ -394,6 +397,13 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { verify(mSpyController).onConfigurationChanged(100); } + @Test + public void updateSysUiStateFlag_passThrough() { + mWindowMagnificationAnimationController.updateSysUiStateFlag(); + + verify(mSpyController).updateSysUIStateFlag(); + } + private void verifyFinalSpec(float expectedScale, float expectedCenterX, float expectedCenterY) { assertEquals(expectedScale, mController.getScale(), 0f); @@ -440,9 +450,9 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase { SpyWindowMagnificationController(Context context, Handler handler, SfVsyncFrameCallbackProvider sfVsyncFrameProvider, MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction, - WindowMagnifierCallback callback) { + WindowMagnifierCallback callback, SysUiState sysUiState) { super(context, handler, sfVsyncFrameProvider, mirrorWindowControl, transaction, - callback); + callback, sysUiState); mSpyController = Mockito.mock(WindowMagnificationController.class); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 7d617db6cc0e..b8734df678d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -17,12 +17,15 @@ package com.android.systemui.accessibility; import static android.view.Choreographer.FrameCallback; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; +import static android.view.WindowInsets.Type.systemGestures; import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; + import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasItems; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -33,6 +36,9 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -40,49 +46,60 @@ import android.app.Instrumentation; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; +import android.graphics.Insets; +import android.graphics.Rect; +import android.graphics.Region; import android.os.Handler; import android.os.SystemClock; import android.testing.AndroidTestingRunner; import android.testing.TestableResources; +import android.text.TextUtils; import android.view.Display; import android.view.Surface; import android.view.SurfaceControl; import android.view.View; +import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.WindowManager; +import android.view.WindowMetrics; import android.view.accessibility.AccessibilityNodeInfo; import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; +import androidx.test.filters.LargeTest; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.model.SysUiState; +import com.android.systemui.util.leak.ReferenceTestUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -@SmallTest +@LargeTest @RunWith(AndroidTestingRunner.class) public class WindowMagnificationControllerTest extends SysuiTestCase { + private static final int LAYOUT_CHANGE_TIMEOUT_MS = 5000; @Mock - Handler mHandler; - @Mock - SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; - @Mock - MirrorWindowControl mMirrorWindowControl; + private Handler mHandler; @Mock - WindowMagnifierCallback mWindowMagnifierCallback; + private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider; @Mock - SurfaceControl.Transaction mTransaction; + private MirrorWindowControl mMirrorWindowControl; @Mock + private WindowMagnifierCallback mWindowMagnifierCallback; + @Mock (answer = Answers.RETURNS_DEEP_STUBS) + private SurfaceControl.Transaction mTransaction; private WindowManager mWindowManager; + private SysUiState mSysUiState = new SysUiState(); private Resources mResources; private WindowMagnificationController mWindowMagnificationController; private Instrumentation mInstrumentation; @@ -93,37 +110,30 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mContext = Mockito.spy(getContext()); mInstrumentation = InstrumentationRegistry.getInstrumentation(); - WindowManager wm = mContext.getSystemService(WindowManager.class); - doAnswer(invocation -> - wm.getMaximumWindowMetrics() - ).when(mWindowManager).getMaximumWindowMetrics(); - doAnswer(invocation -> - wm.getCurrentWindowMetrics() - ).when(mWindowManager).getCurrentWindowMetrics(); + final WindowManager wm = mContext.getSystemService(WindowManager.class); + mWindowManager = spy(new TestableWindowManager(wm)); + mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager); doAnswer(invocation -> { - mMirrorView = invocation.getArgument(0); - WindowManager.LayoutParams lp = invocation.getArgument(1); - mMirrorView.setLayoutParams(lp); - return null; - }).when(mWindowManager).addView(any(View.class), any(WindowManager.LayoutParams.class)); - doAnswer(invocation -> { - mMirrorView = null; - return null; - }).when(mWindowManager).removeView(any(View.class)); - doAnswer(invocation -> { FrameCallback callback = invocation.getArgument(0); callback.doFrame(0); return null; }).when(mSfVsyncFrameProvider).postFrameCallback( any(FrameCallback.class)); - when(mTransaction.remove(any())).thenReturn(mTransaction); - when(mTransaction.setGeometry(any(), any(), any(), - anyInt())).thenReturn(mTransaction); + doAnswer(invocation -> { + final Runnable runnable = invocation.getArgument(0); + runnable.run(); + return null; + }).when(mHandler).post( + any(Runnable.class)); + + mSysUiState.addCallback(Mockito.mock(SysUiState.SysUiStateCallback.class)); + mResources = getContext().getOrCreateTestableResources().getResources(); mWindowMagnificationController = new WindowMagnificationController(mContext, mHandler, mSfVsyncFrameProvider, - mMirrorWindowControl, mTransaction, mWindowMagnifierCallback); + mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState); + verify(mMirrorWindowControl).setWindowDelegate( any(MirrorWindowControl.MirrorWindowDelegate.class)); } @@ -135,12 +145,21 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @Test - public void enableWindowMagnification_showControl() { + public void enableWindowMagnification_showControlAndNotifyBoundsChanged() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); }); + verify(mMirrorWindowControl).showControl(); + ArgumentCaptor<Rect> boundsCaptor = ArgumentCaptor.forClass(Rect.class); + verify(mWindowMagnifierCallback, + timeout(LAYOUT_CHANGE_TIMEOUT_MS)).onWindowMagnifierBoundsChanged( + eq(mContext.getDisplayId()), boundsCaptor.capture()); + final Rect actualBounds = new Rect(); + mMirrorView.getBoundsOnScreen(actualBounds); + assertEquals(actualBounds, boundsCaptor.getValue()); + } @Test @@ -158,6 +177,25 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @Test + public void deleteWindowMagnification_enableAtTheBottom_overlapFlagIsFalse() { + final WindowManager wm = mContext.getSystemService(WindowManager.class); + final Rect bounds = wm.getCurrentWindowMetrics().getBounds(); + + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, + bounds.bottom); + }); + ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag); + + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.deleteWindowMagnification(); + }); + + verify(mMirrorWindowControl).destroyControl(); + assertFalse(hasMagnificationOverlapFlag()); + } + + @Test public void moveMagnifier_schedulesFrame() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, @@ -210,7 +248,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { }); assertEquals(Surface.ROTATION_90, mWindowMagnificationController.mRotation); - verify(mWindowManager).updateViewLayout(any(), any()); + // The first invocation is called when the surface is created. + verify(mWindowManager, times(2)).updateViewLayout(any(), any()); } @Test @@ -318,17 +357,6 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } @Test - public void onNavigationModeChanged_updateMirrorViewLayout() { - mInstrumentation.runOnMainSync(() -> { - mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, - Float.NaN); - mWindowMagnificationController.onNavigationModeChanged(NAV_BAR_MODE_GESTURAL); - }); - - verify(mWindowManager).updateViewLayout(eq(mMirrorView), any()); - } - - @Test public void enableWindowMagnification_hasA11yWindowTitle() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, @@ -353,16 +381,12 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { final TestableResources testableResources = getContext().getOrCreateTestableResources(); testableResources.addOverride(com.android.internal.R.string.android_system_label, newA11yWindowTitle); - when(mContext.getResources()).thenReturn(testableResources.getResources()); mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE); }); - ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass( - WindowManager.LayoutParams.class); - verify(mWindowManager).updateViewLayout(eq(mMirrorView), paramsArgumentCaptor.capture()); - assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle); + assertTrue(TextUtils.equals(newA11yWindowTitle, getAccessibilityWindowTitle())); } @Test @@ -386,4 +410,95 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { } fail("mMirrorView scale is not changed"); } + + @Test + public void moveWindowMagnificationToTheBottom_enabled_overlapFlagIsTrue() { + final WindowManager wm = mContext.getSystemService(WindowManager.class); + final Rect bounds = wm.getCurrentWindowMetrics().getBounds(); + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, + Float.NaN); + }); + + mInstrumentation.runOnMainSync(() -> { + mWindowMagnificationController.moveWindowMagnifier(0, bounds.height()); + }); + + ReferenceTestUtils.waitForCondition(() -> hasMagnificationOverlapFlag()); + } + + private CharSequence getAccessibilityWindowTitle() { + if (mMirrorView == null) { + return null; + } + WindowManager.LayoutParams layoutParams = + (WindowManager.LayoutParams) mMirrorView.getLayoutParams(); + return layoutParams.accessibilityTitle; + } + + private boolean hasMagnificationOverlapFlag() { + return (mSysUiState.getFlags() & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0; + } + + private class TestableWindowManager implements WindowManager { + + private final WindowManager mWindowManager; + + TestableWindowManager(WindowManager windowManager) { + mWindowManager = windowManager; + } + + @Override + public Display getDefaultDisplay() { + return mWindowManager.getDefaultDisplay(); + } + + @Override + public void removeViewImmediate(View view) { + mWindowManager.removeViewImmediate(view); + } + + @Override + public void requestAppKeyboardShortcuts(KeyboardShortcutsReceiver receiver, int deviceId) { + mWindowManager.requestAppKeyboardShortcuts(receiver, deviceId); + } + + @Override + public Region getCurrentImeTouchRegion() { + return mWindowManager.getCurrentImeTouchRegion(); + } + + @Override + public void addView(View view, ViewGroup.LayoutParams params) { + mMirrorView = view; + mWindowManager.addView(view, params); + } + + @Override + public void updateViewLayout(View view, ViewGroup.LayoutParams params) { + mWindowManager.updateViewLayout(view, params); + } + + @Override + public void removeView(View view) { + mMirrorView = null; + mWindowManager.removeView(view); + } + + @Override + public WindowMetrics getCurrentWindowMetrics() { + final Insets systemGesturesInsets = Insets.of(0, 0, 0, 10); + final WindowInsets insets = new WindowInsets.Builder() + .setInsets(systemGestures(), systemGesturesInsets) + .build(); + final WindowMetrics windowMetrics = new WindowMetrics( + mWindowManager.getCurrentWindowMetrics().getBounds(), insets); + return windowMetrics; + } + + @Override + public WindowMetrics getMaximumWindowMetrics() { + return mWindowManager.getMaximumWindowMetrics(); + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java index 78331143af94..6ef7cc3f0af8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java @@ -16,15 +16,21 @@ package com.android.systemui.accessibility; +import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP; + 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.doAnswer; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.os.RemoteException; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -36,12 +42,14 @@ import android.view.accessibility.IWindowMagnificationConnectionCallback; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; -import com.android.systemui.navigationbar.NavigationModeController; +import com.android.systemui.model.SysUiState; +import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.CommandQueue; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -50,17 +58,21 @@ import org.mockito.MockitoAnnotations; @TestableLooper.RunWithLooper public class WindowMagnificationTest extends SysuiTestCase { + private static final int TEST_DISPLAY = Display.DEFAULT_DISPLAY; @Mock private AccessibilityManager mAccessibilityManager; @Mock private ModeSwitchesController mModeSwitchesController; @Mock - private NavigationModeController mNavigationModeController; + private SysUiState mSysUiState; @Mock private IWindowMagnificationConnectionCallback mConnectionCallback; + @Mock + private OverviewProxyService mOverviewProxyService; + private CommandQueue mCommandQueue; private WindowMagnification mWindowMagnification; - + private OverviewProxyListener mOverviewProxyListener; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -72,11 +84,18 @@ public class WindowMagnificationTest extends SysuiTestCase { }).when(mAccessibilityManager).setWindowMagnificationConnection( any(IWindowMagnificationConnection.class)); + when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState); + mCommandQueue = new CommandQueue(getContext()); mWindowMagnification = new WindowMagnification(getContext(), getContext().getMainThreadHandler(), mCommandQueue, mModeSwitchesController, - mNavigationModeController); + mSysUiState, mOverviewProxyService); mWindowMagnification.start(); + + final ArgumentCaptor<OverviewProxyListener> listenerArgumentCaptor = + ArgumentCaptor.forClass(OverviewProxyListener.class); + verify(mOverviewProxyService).addCallback(listenerArgumentCaptor.capture()); + mOverviewProxyListener = listenerArgumentCaptor.getValue(); } @Test @@ -99,10 +118,9 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onWindowMagnifierBoundsChanged(Display.DEFAULT_DISPLAY, testBounds); + mWindowMagnification.onWindowMagnifierBoundsChanged(TEST_DISPLAY, testBounds); - verify(mConnectionCallback).onWindowMagnifierBoundsChanged(Display.DEFAULT_DISPLAY, - testBounds); + verify(mConnectionCallback).onWindowMagnifierBoundsChanged(TEST_DISPLAY, testBounds); } @Test @@ -111,10 +129,9 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onPerformScaleAction(Display.DEFAULT_DISPLAY, newScale); + mWindowMagnification.onPerformScaleAction(TEST_DISPLAY, newScale); - verify(mConnectionCallback).onPerformScaleAction(eq(Display.DEFAULT_DISPLAY), - eq(newScale)); + verify(mConnectionCallback).onPerformScaleAction(TEST_DISPLAY, newScale); } @Test @@ -122,9 +139,9 @@ public class WindowMagnificationTest extends SysuiTestCase { mCommandQueue.requestWindowMagnificationConnection(true); waitForIdleSync(); - mWindowMagnification.onAccessibilityActionPerformed(Display.DEFAULT_DISPLAY); + mWindowMagnification.onAccessibilityActionPerformed(TEST_DISPLAY); - verify(mConnectionCallback).onAccessibilityActionPerformed(eq(Display.DEFAULT_DISPLAY)); + verify(mConnectionCallback).onAccessibilityActionPerformed(TEST_DISPLAY); } @Test @@ -135,4 +152,42 @@ public class WindowMagnificationTest extends SysuiTestCase { verify(mModeSwitchesController).onConfigurationChanged(anyInt()); } + + @Test + public void overviewProxyIsConnected_noController_resetFlag() { + mOverviewProxyListener.onConnectionChanged(true); + + verify(mSysUiState).setFlag(SYSUI_STATE_MAGNIFICATION_OVERLAP, false); + verify(mSysUiState).commitUpdate(mContext.getDisplayId()); + } + + @Test + public void overviewProxyIsConnected_controllerIsAvailable_updateSysUiStateFlag() { + final WindowMagnificationAnimationController mController = mock( + WindowMagnificationAnimationController.class); + mWindowMagnification.mAnimationControllerSupplier = new FakeAnimationControllerSupplier( + mContext.getSystemService(DisplayManager.class), mController); + mWindowMagnification.mAnimationControllerSupplier.get(TEST_DISPLAY); + + mOverviewProxyListener.onConnectionChanged(true); + + verify(mController).updateSysUiStateFlag(); + } + + private static class FakeAnimationControllerSupplier extends + DisplayIdIndexSupplier<WindowMagnificationAnimationController> { + + private final WindowMagnificationAnimationController mController; + + FakeAnimationControllerSupplier(DisplayManager displayManager, + WindowMagnificationAnimationController controller) { + super(displayManager); + mController = controller; + } + + @Override + protected WindowMagnificationAnimationController createInstance(Display display) { + return mController; + } + } } |