Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b0634c4 authored by ryanlwlin's avatar ryanlwlin
Browse files

Fix hard dragging the window magnification from the bottom of the screen

The window magnifier is hard to drag when it is at the bottom
of the screen. This is due to that launcher is detecting
swipe-up system gesture.

To fix it, we set the system ui state flag to true when
the window is overlapped with the gesture detection area.
We also update the gesture dection area via OnApplyWindowInsetsListener
Once the area is changed, we will update the flag again if necessary.

In the testing part, we use real WindowManager to verify the
functionality.

Bug: 179648683
Test: atest com.android.systemui.accessibility
      manually test and use the following command to check the flag
      adb shell dumpsys activity service TouchInteractionService
Change-Id: Ia09bd26b3eb164790614c173594d997d45f4ecdc
parent 20e9693c
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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();
    }

+5 −7
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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,
+47 −19
Original line number Diff line number Diff line
@@ -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,
+9 −0
Original line number Diff line number Diff line
@@ -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(
Loading