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

Commit 9e211a72 authored by Justin Weir's avatar Justin Weir Committed by Android (Google) Code Review
Browse files

Merge "Long press Home status bar expands the shade" into main

parents 98ecea72 a38e46ce
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ import org.junit.Rule;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Answer;
@@ -515,7 +516,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
        when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
        when(mView.findViewById(R.id.keyguard_status_view))
                .thenReturn(mock(KeyguardStatusView.class));
        View rootView = mock(View.class);
        ViewGroup rootView = mock(ViewGroup.class);
        when(rootView.isVisibleToUser()).thenReturn(true);
        when(mView.getRootView()).thenReturn(rootView);
        when(rootView.findViewById(R.id.keyguard_status_view))
                .thenReturn(mock(KeyguardStatusView.class));
@@ -652,12 +654,21 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
            ((Runnable) invocation.getArgument(0)).run();
            return null;
        }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
        when(mNotificationShadeWindowController.getWindowRootView()).thenReturn(rootView);
        doAnswer(invocation -> {
            mLayoutChangeListener = invocation.getArgument(0);
            return null;
        }).when(mView).addOnLayoutChangeListener(any());

        when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                ViewTreeObserver.OnGlobalLayoutListener gll = invocation.getArgument(0);
                gll.onGlobalLayout();
                return null;
            }
        }).when(mViewTreeObserver).addOnGlobalLayoutListener(any());
        when(mView.getParent()).thenReturn(mViewParent);
        when(mQs.getHeader()).thenReturn(mQsHeader);
        when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
@@ -911,7 +922,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
    }

    protected boolean onTouchEvent(MotionEvent ev) {
        return mTouchHandler.onTouch(mView, ev);
        return mNotificationPanelViewController.handleExternalTouch(ev);
    }

    protected void setDozing(boolean dozing, boolean dozingAlwaysOn) {
+58 −0
Original line number Diff line number Diff line
@@ -363,6 +363,64 @@ public class NotificationPanelViewControllerTest extends NotificationPanelViewCo
        assertThat((int) mNotificationPanelViewController.getExpandedHeight()).isEqualTo(200);
    }

    @Test
    @EnableFlags(com.android.systemui.Flags.FLAG_SHADE_EXPANDS_ON_STATUS_BAR_LONG_PRESS)
    public void onStatusBarLongPress_shadeExpands() {
        long downTime = 42L;
        // Start touch session with down event
        onTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, 1f, 1f, 0));
        // Status bar triggers long press expand
        mNotificationPanelViewController.onStatusBarLongPress(
                MotionEvent.obtain(downTime, downTime + 27L, MotionEvent.ACTION_MOVE, 1f, 1f, 0));
        assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
        // Shade ignores the rest of the long press's touch session
        assertThat(onTouchEvent(
                MotionEvent.obtain(downTime, downTime + 42L, MotionEvent.ACTION_MOVE, 1f, 1f,
                        0))).isFalse();

        // Start new touch session
        long downTime2 = downTime + 100L;
        assertThat(onTouchEvent(
                MotionEvent.obtain(downTime2, downTime2, MotionEvent.ACTION_DOWN, 1f, 1f,
                        0))).isTrue();
        // Shade no longer ignoring touches
        assertThat(onTouchEvent(
                MotionEvent.obtain(downTime2, downTime2 + 2L, MotionEvent.ACTION_MOVE, 1f, 1f,
                        0))).isTrue();
    }

    @Test
    @EnableFlags(com.android.systemui.Flags.FLAG_SHADE_EXPANDS_ON_STATUS_BAR_LONG_PRESS)
    public void onStatusBarLongPress_qsExpands() {
        long downTime = 42L;
        // Start with shade already expanded
        mNotificationPanelViewController.setExpandedFraction(1F);

        // Start touch session with down event
        onTouchEvent(MotionEvent.obtain(downTime, downTime, MotionEvent.ACTION_DOWN, 1f, 1f, 0));
        // Status bar triggers long press expand
        mNotificationPanelViewController.onStatusBarLongPress(
                MotionEvent.obtain(downTime, downTime + 27L, MotionEvent.ACTION_MOVE, 1f, 1f, 0));
        assertThat(mNotificationPanelViewController.isExpanded()).isTrue();
        // Shade expands to QS
        verify(mQsController, atLeastOnce()).flingQs(0F, ShadeViewController.FLING_EXPAND);
        // Shade ignores the rest of the long press's touch session
        assertThat(onTouchEvent(
                MotionEvent.obtain(downTime, downTime + 42L, MotionEvent.ACTION_MOVE, 1f, 1f,
                        0))).isFalse();

        // Start new touch session
        long downTime2 = downTime + 100L;
        assertThat(onTouchEvent(
                MotionEvent.obtain(downTime2, downTime2, MotionEvent.ACTION_DOWN, 1f, 1f,
                        0))).isTrue();
        // Shade no longer ignoring touches
        assertThat(onTouchEvent(
                MotionEvent.obtain(downTime2, downTime2 + 2L, MotionEvent.ACTION_MOVE, 1f, 1f,
                        0))).isTrue();

    }

    @Test
    @DisableFlags(com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
    public void test_pulsing_onTouchEvent_noTracking() {
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.shade

import android.content.Context
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject

/** Accepts touch events, detects long press, and calls ShadeViewController#onStatusBarLongPress. */
@SysUISingleton
class LongPressGestureDetector
@Inject
constructor(context: Context, val shadeViewController: ShadeViewController) {
    val gestureDetector =
        GestureDetector(
            context,
            object : SimpleOnGestureListener() {
                override fun onLongPress(event: MotionEvent) {
                    shadeViewController.onStatusBarLongPress(event)
                }
            },
        )

    /** Accepts touch events to detect long presses. */
    fun handleTouch(ev: MotionEvent) {
        gestureDetector.onTouchEvent(ev)
    }
}
+29 −0
Original line number Diff line number Diff line
@@ -365,6 +365,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
    private final TouchHandler mTouchHandler = new TouchHandler();

    private long mDownTime;
    private long mStatusBarLongPressDowntime;
    private boolean mTouchSlopExceededBeforeDown;
    private float mOverExpansion;
    private CentralSurfaces mCentralSurfaces;
@@ -3098,6 +3099,25 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
        }
    }

    /** @deprecated Temporary a11y solution until dual shade launch b/371224114 */
    @Override
    @Deprecated
    public void onStatusBarLongPress(MotionEvent event) {
        mShadeLog.d("Status Bar was long pressed.");
        ShadeExpandsOnStatusBarLongPress.assertInNewMode();
        mStatusBarLongPressDowntime = event.getDownTime();
        if (isTracking()) {
            onTrackingStopped(true);
        }
        if (isExpanded() && !mQsController.getExpanded()) {
            mShadeLog.d("Status Bar was long pressed. Expanding to QS.");
            expandToQs();
        } else {
            mShadeLog.d("Status Bar was long pressed. Expanding to Notifications.");
            expandToNotifications();
        }
    }

    @Override
    public int getBarState() {
        return mBarState;
@@ -3761,6 +3781,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
    private void endMotionEvent(MotionEvent event, float x, float y, boolean forceCancel) {
        mShadeLog.logEndMotionEvent("endMotionEvent called", forceCancel, false);
        mTrackingPointer = -1;
        mStatusBarLongPressDowntime = 0L;
        mAmbientState.setSwipingUp(false);
        if ((isTracking() && mTouchSlopExceeded) || Math.abs(x - mInitialExpandX) > mTouchSlop
                || Math.abs(y - mInitialExpandY) > mTouchSlop
@@ -5077,6 +5098,13 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                }
                return true;
            }
            // This touch session has already resulted in shade expansion. Ignore everything else.
            if (ShadeExpandsOnStatusBarLongPress.isEnabled()
                    && event.getActionMasked() != MotionEvent.ACTION_DOWN
                    && event.getDownTime() == mStatusBarLongPressDowntime) {
                mShadeLog.d("Touch has same down time as Status Bar long press. Ignoring.");
                return false;
            }
            if (event.getActionMasked() == MotionEvent.ACTION_DOWN && isFullyCollapsed()) {
                mMetricsLogger.count(COUNTER_PANEL_OPEN, 1);
                handled = true;
@@ -5157,6 +5185,7 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
                    mUpdateFlingOnLayout = false;
                    mMotionAborted = false;
                    mDownTime = mSystemClock.uptimeMillis();
                    mStatusBarLongPressDowntime = 0L;
                    mTouchAboveFalsingThreshold = false;
                    mCollapsedAndHeadsUpOnDown =
                            isFullyCollapsed() && mHeadsUpManager.hasPinnedHeadsUp();
+5 −3
Original line number Diff line number Diff line
@@ -98,6 +98,10 @@ interface ShadeViewController {
    /** Returns the ShadeHeadsUpTracker. */
    val shadeHeadsUpTracker: ShadeHeadsUpTracker

    @Deprecated("Temporary a11y solution until dual shade launch b/371224114")
    /** Notifies the shade that a status bar detected a long press gesture. */
    fun onStatusBarLongPress(event: MotionEvent)

    /** Returns the ShadeFoldAnimator. */
    @Deprecated("This interface is deprecated in Scene Container")
    val shadeFoldAnimator: ShadeFoldAnimator
@@ -179,9 +183,7 @@ interface ShadeViewStateProvider {
    /** Returns the expanded height of the panel view. */
    @Deprecated("deprecated by SceneContainerFlag.isEnabled") val panelViewExpandedHeight: Float

    /**
     * Returns true if heads up should be visible.
     */
    /** Returns true if heads up should be visible. */
    @Deprecated("deprecated by SceneContainerFlag.isEnabled.") fun shouldHeadsUpBeVisible(): Boolean

    /** Return the fraction of the shade that's expanded, when in lockscreen. */
Loading