Merge "Fix hard dragging the window magnification from the bottom of the screen" into sc-dev
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
private Handler mHandler;
|
||||
@Mock
|
||||
SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
|
||||
private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
|
||||
@Mock
|
||||
MirrorWindowControl mMirrorWindowControl;
|
||||
@Mock
|
||||
WindowMagnifierCallback mWindowMagnifierCallback;
|
||||
@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
|
||||
@@ -157,6 +176,25 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
verify(mMirrorWindowControl).destroyControl();
|
||||
}
|
||||
|
||||
@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(() -> {
|
||||
@@ -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
|
||||
@@ -317,17 +356,6 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
|
||||
verify(mWindowMagnifierCallback).onAccessibilityActionPerformed(eq(displayId));
|
||||
}
|
||||
|
||||
@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(() -> {
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user