From ca75e7e46675bfb85611b3415561aab94196cdbd Mon Sep 17 00:00:00 2001 From: Bill Lin Date: Tue, 15 Jun 2021 04:46:54 +0800 Subject: [PATCH] Allow one-handed mode shortcut expand notification 1) Add OneHandedEventCallback for WMShell to register callback, and if one handed mode settings set show notifications, when user tap one handed mode shortcut notify WMShell send KEYCODE_SYSTEM_NAVIGATION_DOWN through OneHandedEventCallback with SysUIMainExecutor. 2) Add isReady() flag in OneHandedDisplayAreaOrganizer and Simplify the flow of onActivatedActionChanged() to prevent potential race problem while auto-enable One-handed and immeditately startOneHanded(), however, DisplayAreaOrganizer#onDisplayAreaAppeared() may not ready for transtion yet, and result mState keep in unfinsihed STATE_ENTERING. 3) Adjust the transiton duration from 800ms to 600ms 800ms is a little bit long to affect timing of apply runtime overlay package. 4) DelayExecute setEnabledGesturalOverlay() until transition finised and at most delay once. - onSwipeToNotificationEnabledChanged() : DelayExecute - onEnabledSettingChanged() : DelayExecute - Ctor setupGesturalOverlay() : No DelayExecute - mState.isTransitioning() : DelayExecute Test: WMShellUnitTests Bug: 182425480 Change-Id: I2615c3b30ad95a858510b4bcc73d8f343843fc96 --- .../WindowManager/Shell/res/values/config.xml | 2 +- .../android/wm/shell/onehanded/OneHanded.java | 5 ++ .../shell/onehanded/OneHandedController.java | 78 ++++++++++++++++--- .../OneHandedDisplayAreaOrganizer.java | 11 ++- .../onehanded/OneHandedEventCallback.java | 28 +++++++ .../onehanded/OneHandedSettingsUtil.java | 11 +++ .../onehanded/OneHandedControllerTest.java | 45 ++++++++--- .../OneHandedDisplayAreaOrganizerTest.java | 14 ++++ .../com/android/systemui/wmshell/WMShell.java | 11 +++ .../android/systemui/wmshell/WMShellTest.java | 2 + 10 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml index 4c2863e4f5947..8cea869aea349 100644 --- a/libs/WindowManager/Shell/res/values/config.xml +++ b/libs/WindowManager/Shell/res/values/config.xml @@ -40,7 +40,7 @@ 250 - 800 + 600 40% diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java index 8dc05de9bb8f9..a525c2c0219ce 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java @@ -67,6 +67,11 @@ public interface OneHanded { */ void setLockedDisabled(boolean locked, boolean enabled); + /** + * Registers callback to notify WMShell when user tap shortcut to expand notification. + */ + void registerEventCallback(OneHandedEventCallback callback); + /** * Registers callback to be notified after {@link OneHandedDisplayAreaOrganizer} * transition start or finish diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index c275d50a5d56e..b43daa0da2c09 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -43,6 +43,7 @@ import android.util.Slog; import android.view.Surface; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -72,6 +73,7 @@ public class OneHandedController implements RemoteCallable private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY = "com.android.internal.systemui.onehanded.gestural"; private static final int OVERLAY_ENABLED_DELAY_MS = 250; + private static final int DISPLAY_AREA_READY_RETRY_MS = 10; static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; @@ -99,6 +101,7 @@ public class OneHandedController implements RemoteCallable private final Handler mMainHandler; private final OneHandedImpl mImpl = new OneHandedImpl(); + private OneHandedEventCallback mEventCallback; private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer; private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer; @@ -288,7 +291,7 @@ public class OneHandedController implements RemoteCallable mTimeoutObserver = getObserver(this::onTimeoutSettingChanged); mTaskChangeExitObserver = getObserver(this::onTaskChangeExitSettingChanged); mSwipeToNotificationEnabledObserver = - getObserver(this::onSwipeToNotificationEnabledSettingChanged); + getObserver(this::onSwipeToNotificationEnabledChanged); mDisplayController.addDisplayChangingController(mRotationController); setupCallback(); @@ -358,14 +361,23 @@ public class OneHandedController implements RemoteCallable Slog.d(TAG, "Temporary lock disabled"); return; } + + if (!mDisplayAreaOrganizer.isReady()) { + // Must wait until DisplayAreaOrganizer is ready for transitioning. + mMainExecutor.executeDelayed(this::startOneHanded, DISPLAY_AREA_READY_RETRY_MS); + return; + } + if (mState.isTransitioning() || mState.isInOneHanded()) { return; } + final int currentRotation = mDisplayAreaOrganizer.getDisplayLayout().rotation(); if (currentRotation != Surface.ROTATION_0 && currentRotation != Surface.ROTATION_180) { Slog.w(TAG, "One handed mode only support portrait mode"); return; } + mState.setState(STATE_ENTERING); final int yOffSet = Math.round( mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction); @@ -394,6 +406,10 @@ public class OneHandedController implements RemoteCallable mOneHandedUiEventLogger.writeEvent(uiEvent); } + void registerEventCallback(OneHandedEventCallback callback) { + mEventCallback = callback; + } + @VisibleForTesting void registerTransitionCallback(OneHandedTransitionCallback callback) { mDisplayAreaOrganizer.registerTransitionCallback(callback); @@ -463,9 +479,30 @@ public class OneHandedController implements RemoteCallable }; } + @VisibleForTesting + void notifyExpandNotification() { + mMainExecutor.execute(() -> mEventCallback.notifyExpandNotification()); + } + + @VisibleForTesting + void notifyUserConfigChanged(boolean success) { + if (!success) { + return; + } + // TODO Check UX if popup Toast to notify user when auto-enabled one-handed is good option. + Toast.makeText(mContext, R.string.one_handed_tutorial_title, Toast.LENGTH_LONG).show(); + } + @VisibleForTesting void onActivatedActionChanged() { - if (mState.isTransitioning() || !isOneHandedEnabled()) { + if (!isOneHandedEnabled()) { + final boolean success = mOneHandedSettingsUtil.setOneHandedModeEnabled( + mContext.getContentResolver(), 1 /* Enabled for shortcut */, mUserId); + notifyUserConfigChanged(success); + } + + if (isSwipeToNotificationEnabled()) { + notifyExpandNotification(); return; } @@ -494,11 +531,9 @@ public class OneHandedController implements RemoteCallable setOneHandedEnabled(enabled); // Also checks swipe to notification settings since they all need gesture overlay. - // Enabled overlay package may affect the current animation(e.g:Settings switch), - // so we delay 250ms to enabled overlay after switch animation finish - mMainExecutor.executeDelayed(() -> setEnabledGesturalOverlay( + setEnabledGesturalOverlay( enabled || mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( - mContext.getContentResolver(), mUserId)), OVERLAY_ENABLED_DELAY_MS); + mContext.getContentResolver(), mUserId), true /* DelayExecute */); } @VisibleForTesting @@ -542,7 +577,7 @@ public class OneHandedController implements RemoteCallable } @VisibleForTesting - void onSwipeToNotificationEnabledSettingChanged() { + void onSwipeToNotificationEnabledChanged() { final boolean enabled = mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled( mContext.getContentResolver(), mUserId); @@ -551,7 +586,7 @@ public class OneHandedController implements RemoteCallable // Also checks one handed mode settings since they all need gesture overlay. setEnabledGesturalOverlay( enabled || mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled( - mContext.getContentResolver(), mUserId)); + mContext.getContentResolver(), mUserId), true /* DelayExecute */); } private void setupTimeoutListener() { @@ -569,11 +604,19 @@ public class OneHandedController implements RemoteCallable return mIsOneHandedEnabled; } + @VisibleForTesting + boolean isSwipeToNotificationEnabled() { + return mIsSwipeToNotificationEnabled; + } + private void updateOneHandedEnabled() { if (mState.getState() == STATE_ENTERING || mState.getState() == STATE_ACTIVE) { mMainExecutor.execute(() -> stopOneHanded()); } + // Reset and align shortcut one_handed_mode_activated status with current mState + notifyShortcutState(mState.getState()); + mTouchHandler.onOneHandedEnabled(mIsOneHandedEnabled); if (!mIsOneHandedEnabled) { @@ -608,12 +651,19 @@ public class OneHandedController implements RemoteCallable if (info != null && !info.isEnabled()) { // Enable the default gestural one handed overlay. - setEnabledGesturalOverlay(true); + setEnabledGesturalOverlay(true /* enabled */, false /* delayExecute */); } } @VisibleForTesting - private void setEnabledGesturalOverlay(boolean enabled) { + private void setEnabledGesturalOverlay(boolean enabled, boolean delayExecute) { + if (mState.isTransitioning() || delayExecute) { + // Enabled overlay package may affect the current animation(e.g:Settings switch), + // so we delay 250ms to enabled overlay after switch animation finish, only delay once. + mMainExecutor.executeDelayed(() -> setEnabledGesturalOverlay(enabled, false), + OVERLAY_ENABLED_DELAY_MS); + return; + } try { mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT); } catch (RemoteException e) { @@ -628,6 +678,7 @@ public class OneHandedController implements RemoteCallable if (enabled == isFeatureEnabled) { return; } + mLockedDisabled = locked && !enabled; } @@ -760,6 +811,13 @@ public class OneHandedController implements RemoteCallable }); } + @Override + public void registerEventCallback(OneHandedEventCallback callback) { + mMainExecutor.execute(() -> { + OneHandedController.this.registerEventCallback(callback); + }); + } + @Override public void registerTransitionCallback(OneHandedTransitionCallback callback) { mMainExecutor.execute(() -> { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index b8da37fd0c25d..d749c320bf948 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -61,11 +61,12 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { private DisplayLayout mDisplayLayout = new DisplayLayout(); - private float mLastVisualOffset = 0; private final Rect mLastVisualDisplayBounds = new Rect(); private final Rect mDefaultDisplayBounds = new Rect(); private final OneHandedSettingsUtil mOneHandedSettingsUtil; + private boolean mIsReady; + private float mLastVisualOffset = 0; private int mEnterExitAnimationDurationMs; private ArrayMap mDisplayAreaTokenMap = new ArrayMap(); @@ -157,6 +158,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { final DisplayAreaAppearedInfo info = displayAreaInfos.get(i); onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash()); } + mIsReady = true; updateDisplayBounds(); return displayAreaInfos; } @@ -164,9 +166,14 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { @Override public void unregisterOrganizer() { super.unregisterOrganizer(); + mIsReady = false; resetWindowsOffset(); } + boolean isReady() { + return mIsReady; + } + /** * Handler for display rotation changes by {@link DisplayLayout} * @@ -312,6 +319,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer { pw.println(mDisplayAreaTokenMap); pw.print(innerPrefix + "mDefaultDisplayBounds="); pw.println(mDefaultDisplayBounds); + pw.print(innerPrefix + "mIsReady="); + pw.println(mIsReady); pw.print(innerPrefix + "mLastVisualDisplayBounds="); pw.println(mLastVisualDisplayBounds); pw.print(innerPrefix + "mLastVisualOffset="); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java new file mode 100644 index 0000000000000..d07eea271eacd --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEventCallback.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 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.wm.shell.onehanded; + +/** + * Additional callback interface for OneHanded events. + */ +public interface OneHandedEventCallback { + /** + * Called to notify expand notification shade. + */ + default void notifyExpandNotification() { + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java index 90fc823fb574d..da53b359a304a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java @@ -104,6 +104,17 @@ public final class OneHandedSettingsUtil { Settings.Secure.ONE_HANDED_MODE_ENABLED, 0 /* Disabled */, userId) == 1; } + /** + * Sets one handed enable or disable flag from Settings provider. + * + * @return true if the value was set, false on database errors + */ + public boolean setOneHandedModeEnabled(ContentResolver resolver, int enabled, int userId) { + return Settings.Secure.putIntForUser(resolver, + Settings.Secure.ONE_HANDED_MODE_ENABLED, enabled, userId); + } + + /** * Queries taps app to exit config from Settings provider. * diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index 1852279ee96c8..47789b7490ee2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -74,6 +74,8 @@ public class OneHandedControllerTest extends OneHandedTestCase { @Mock OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; @Mock + OneHandedEventCallback mMockEventCallback; + @Mock OneHandedTouchHandler mMockTouchHandler; @Mock OneHandedTutorialHandler mMockTutorialHandler; @@ -106,6 +108,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay); when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>()); + when(mMockDisplayAreaOrganizer.isReady()).thenReturn(true); when(mMockBackgroundOrganizer.getBackgroundSurface()).thenReturn(mMockLeash); when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn( mDefaultEnabled); @@ -241,7 +244,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { @Test public void testSettingsObserverUpdateSwipeToNotification() { - mSpiedOneHandedController.onSwipeToNotificationEnabledSettingChanged(); + mSpiedOneHandedController.onSwipeToNotificationEnabledChanged(); verify(mSpiedOneHandedController).setSwipeToNotificationEnabled(anyBoolean()); } @@ -311,6 +314,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { final DisplayLayout testDisplayLayout = new DisplayLayout(mDisplayLayout); testDisplayLayout.rotateTo(mContext.getResources(), Surface.ROTATION_180); mSpiedTransitionState.setState(STATE_NONE); + when(mMockDisplayAreaOrganizer.isReady()).thenReturn(true); when(mMockDisplayAreaOrganizer.getDisplayLayout()).thenReturn(testDisplayLayout); mSpiedOneHandedController.setOneHandedEnabled(true); mSpiedOneHandedController.setLockedDisabled(false /* locked */, false /* enabled */); @@ -372,8 +376,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true); mSpiedOneHandedController.onActivatedActionChanged(); - verify(mSpiedOneHandedController, never()).startOneHanded(); - verify(mSpiedOneHandedController, never()).stopOneHanded(); + verify(mSpiedTransitionState, never()).setState(STATE_EXITING); } @Test @@ -383,20 +386,20 @@ public class OneHandedControllerTest extends OneHandedTestCase { when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true); mSpiedOneHandedController.onActivatedActionChanged(); - verify(mSpiedOneHandedController, never()).startOneHanded(); - verify(mSpiedOneHandedController, never()).stopOneHanded(); + verify(mSpiedTransitionState, never()).setState(STATE_ENTERING); } @Test - public void testOneHandedDisabled_shortcutEnabled_skipActions() { + public void testOneHandedDisabled_shortcutTrigger_thenAutoEnabled() { when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false); when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE); when(mSpiedTransitionState.isTransitioning()).thenReturn(false); - when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true); + when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(false); + when(mMockSettingsUitl.setOneHandedModeEnabled(any(), anyInt(), anyInt())).thenReturn( + false); mSpiedOneHandedController.onActivatedActionChanged(); - verify(mSpiedOneHandedController, never()).startOneHanded(); - verify(mSpiedOneHandedController, never()).stopOneHanded(); + verify(mSpiedOneHandedController).notifyUserConfigChanged(anyBoolean()); } @Test @@ -408,4 +411,28 @@ public class OneHandedControllerTest extends OneHandedTestCase { verify(mSpiedTransitionState).addSListeners(mMockTutorialHandler); } + + @Test + public void testNotifyEventCallbackWithMainExecutor() { + when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(true); + when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE); + when(mSpiedTransitionState.isTransitioning()).thenReturn(false); + when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(true); + mSpiedOneHandedController.registerEventCallback(mMockEventCallback); + mSpiedOneHandedController.onActivatedActionChanged(); + + verify(mMockShellMainExecutor).execute(any()); + } + + @Test + public void testNotifyShortcutState_whenUpdateOneHandedEnabled() { + when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false); + when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE); + when(mSpiedTransitionState.isTransitioning()).thenReturn(false); + when(mSpiedOneHandedController.isSwipeToNotificationEnabled()).thenReturn(true); + mSpiedOneHandedController.registerEventCallback(mMockEventCallback); + mSpiedOneHandedController.setOneHandedEnabled(true); + + verify(mSpiedOneHandedController).notifyShortcutState(anyInt()); + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java index a27ed114de708..ef16fd391235c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java @@ -418,4 +418,18 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { verify(mSpiedDisplayAreaOrganizer, never()).resetWindowsOffset(); } + + @Test + public void testDisplayArea_notReadyForTransition() { + OneHandedDisplayAreaOrganizer testSpiedDisplayAreaOrganizer = spy( + new OneHandedDisplayAreaOrganizer(mContext, + mDisplayLayout, + mMockSettingsUitl, + mMockAnimationController, + mTutorialHandler, + mMockBackgroundOrganizer, + mMockShellMainExecutor)); + + assertThat(testSpiedDisplayAreaOrganizer.isReady()).isFalse(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 92ef8504d1232..3af82f91af1cb 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -34,6 +34,7 @@ import android.graphics.drawable.Drawable; import android.inputmethodservice.InputMethodService; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import android.view.KeyEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; @@ -57,6 +58,7 @@ import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.nano.WmShellTraceProto; import com.android.wm.shell.onehanded.OneHanded; +import com.android.wm.shell.onehanded.OneHandedEventCallback; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.onehanded.OneHandedUiEventLogger; import com.android.wm.shell.pip.Pip; @@ -253,6 +255,15 @@ public final class WMShell extends SystemUI } }); + oneHanded.registerEventCallback(new OneHandedEventCallback() { + @Override + public void notifyExpandNotification() { + mSysUiMainExecutor.execute( + () -> mCommandQueue.handleSystemKey( + KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN)); + } + }); + mOneHandedKeyguardCallback = new KeyguardUpdateMonitorCallback() { @Override public void onKeyguardBouncerChanged(boolean bouncer) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index 1dd0b21bda30f..ff15d0151ea44 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -37,6 +37,7 @@ import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import com.android.wm.shell.onehanded.OneHanded; +import com.android.wm.shell.onehanded.OneHandedEventCallback; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.Pip; @@ -106,6 +107,7 @@ public class WMShellTest extends SysuiTestCase { verify(mCommandQueue).addCallback(any(CommandQueue.Callbacks.class)); verify(mScreenLifecycle).addObserver(any(ScreenLifecycle.Observer.class)); verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class)); + verify(mOneHanded).registerEventCallback(any(OneHandedEventCallback.class)); } @Test