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

Commit 05aee573 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Fix touch on QQS tiles" into tm-dev am: eae3e16a

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17896369



Change-Id: I0312b517fe215d492005019f3e4a4f009fd2b579
Ignore-AOSP-First: this is an automerge
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 67ca36aa eae3e16a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -85,8 +85,8 @@ import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.ShadeViewRefactor;
@@ -3615,7 +3615,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
    @ShadeViewRefactor(RefactorComponent.INPUT)
    protected boolean isInsideQsHeader(MotionEvent ev) {
        mQsHeader.getBoundsOnScreen(mQsHeaderBound);
        return mQsHeaderBound.contains((int) ev.getX(), (int) ev.getY());
        return mQsHeaderBound.contains((int) ev.getRawX(), (int) ev.getRawY());
    }

    @ShadeViewRefactor(RefactorComponent.INPUT)
+3 −3
Original line number Diff line number Diff line
@@ -2816,12 +2816,12 @@ public class NotificationPanelViewController extends PanelViewController {
            return false;
        }
        View header = mKeyguardShowing || mQs == null ? mKeyguardStatusBar : mQs.getHeader();

        int frameTop = mKeyguardShowing || mQs == null ? 0 : mQsFrame.getTop();
        mQsInterceptRegion.set(
                /* left= */ (int) mQsFrame.getX(),
                /* top= */ header.getTop(),
                /* top= */ header.getTop() + frameTop,
                /* right= */ (int) mQsFrame.getX() + mQsFrame.getWidth(),
                /* bottom= */ header.getBottom());
                /* bottom= */ header.getBottom() + frameTop);
        // Also allow QS to intercept if the touch is near the notch.
        mStatusBarTouchableRegionManager.updateRegionForNotch(mQsInterceptRegion);
        final boolean onHeader = mQsInterceptRegion.contains((int) x, (int) y);
+66 −0
Original line number Diff line number Diff line
@@ -34,15 +34,20 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
@@ -569,9 +574,70 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
        assertEquals(0, mStackScroller.getSpeedBumpIndex());
    }

    @Test
    public void testInsideQSHeader_noOffset() {
        ViewGroup qsHeader = mock(ViewGroup.class);
        Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
        mockBoundsOnScreen(qsHeader, boundsOnScreen);

        mStackScroller.setQsHeader(qsHeader);
        mStackScroller.setLeftTopRightBottom(0, 0, 2000, 2000);

        MotionEvent event1 = transformEventForView(createMotionEvent(100f, 100f), mStackScroller);
        assertTrue(mStackScroller.isInsideQsHeader(event1));

        MotionEvent event2 = transformEventForView(createMotionEvent(1100f, 100f), mStackScroller);
        assertFalse(mStackScroller.isInsideQsHeader(event2));
    }

    @Test
    public void testInsideQSHeader_Offset() {
        ViewGroup qsHeader = mock(ViewGroup.class);
        Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
        mockBoundsOnScreen(qsHeader, boundsOnScreen);

        mStackScroller.setQsHeader(qsHeader);
        mStackScroller.setLeftTopRightBottom(200, 200, 2000, 2000);

        MotionEvent event1 = transformEventForView(createMotionEvent(50f, 50f), mStackScroller);
        assertFalse(mStackScroller.isInsideQsHeader(event1));

        MotionEvent event2 = transformEventForView(createMotionEvent(150f, 150f), mStackScroller);
        assertTrue(mStackScroller.isInsideQsHeader(event2));

        MotionEvent event3 = transformEventForView(createMotionEvent(250f, 250f), mStackScroller);
        assertTrue(mStackScroller.isInsideQsHeader(event2));
    }

    private void setBarStateForTest(int state) {
        // Can't inject this through the listener or we end up on the actual implementation
        // rather than the mock because the spy just coppied the anonymous inner /shruggie.
        mStackScroller.setStatusBarState(state);
    }

    private static void mockBoundsOnScreen(View view, Rect bounds) {
        doAnswer(invocation -> {
            Rect out = invocation.getArgument(0);
            out.set(bounds);
            return null;
        }).when(view).getBoundsOnScreen(any());
    }

    private static MotionEvent transformEventForView(MotionEvent event, View view) {
        // From `ViewGroup#dispatchTransformedTouchEvent`
        MotionEvent transformed = event.copy();
        transformed.offsetLocation(-view.getTop(), -view.getLeft());
        return transformed;
    }

    private static MotionEvent createMotionEvent(float x, float y) {
        return MotionEvent.obtain(
                /* downTime= */0,
                /* eventTime= */0,
                MotionEvent.ACTION_DOWN,
                x,
                y,
                /* metaState= */0
        );
    }
}