From ab0ee99c7b2fe2c6a12aea2cdb6a09cb9a7ca962 Mon Sep 17 00:00:00 2001 From: Dave Mankoff Date: Wed, 9 Feb 2022 16:56:26 -0500 Subject: [PATCH] Remove Dependency#get calls from NavigationBarView Removes Dependency.get(EdgeBackGestureHandler.class) from NavigationBarview. Bug: 218354102 Test: manual && atest SystemUITests Change-Id: I956e943504966fcecfd3da477535937a2aba7a9d Merged-In: I956e943504966fcecfd3da477535937a2aba7a9d --- .../systemui/navigationbar/NavigationBar.java | 117 ++++++++++++++++- .../navigationbar/NavigationBarModule.java | 9 ++ .../navigationbar/NavigationBarView.java | 124 ++---------------- .../navigationbar/NavigationBarTest.java | 9 +- 4 files changed, 135 insertions(+), 124 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 3bb4e6481bd6a..3c373f447c345 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -70,6 +70,7 @@ import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.Region; import android.os.Binder; import android.os.Bundle; import android.os.Handler; @@ -91,6 +92,8 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewTreeObserver; +import android.view.ViewTreeObserver.InternalInsetsInfo; +import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import android.view.WindowInsetsController.Appearance; import android.view.WindowInsetsController.Behavior; import android.view.WindowManager; @@ -121,6 +124,7 @@ import com.android.systemui.navigationbar.buttons.ButtonDispatcher; import com.android.systemui.navigationbar.buttons.DeadZone; import com.android.systemui.navigationbar.buttons.KeyButtonView; import com.android.systemui.navigationbar.buttons.RotationContextButton; +import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import com.android.systemui.navigationbar.gestural.QuickswitchOrientedNavHandle; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; @@ -153,6 +157,7 @@ import com.android.wm.shell.pip.Pip; import java.io.PrintWriter; import java.util.Locale; +import java.util.Map; import java.util.Optional; import java.util.function.Consumer; @@ -199,12 +204,14 @@ public class NavigationBar extends ViewController implements private final Optional mRecentsOptional; private final DeviceConfigProxy mDeviceConfigProxy; private final NavigationBarTransitions mNavigationBarTransitions; + private final EdgeBackGestureHandler mEdgeBackGestureHandler; private final Optional mBackAnimation; private final Handler mHandler; private final UiEventLogger mUiEventLogger; private final NavBarHelper mNavBarHelper; private final NotificationShadeDepthController mNotificationShadeDepthController; private final UserContextProvider mUserContextProvider; + private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener; private NavigationBarFrame mFrame; private @WindowVisibleState int mNavigationBarWindowState = WINDOW_STATE_SHOWING; @@ -516,6 +523,7 @@ public class NavigationBar extends ViewController implements DeadZone deadZone, DeviceConfigProxy deviceConfigProxy, NavigationBarTransitions navigationBarTransitions, + EdgeBackGestureHandler edgeBackGestureHandler, Optional backAnimation, UserContextProvider userContextProvider) { super(navigationBarView); @@ -542,6 +550,7 @@ public class NavigationBar extends ViewController implements mDeadZone = deadZone; mDeviceConfigProxy = deviceConfigProxy; mNavigationBarTransitions = navigationBarTransitions; + mEdgeBackGestureHandler = edgeBackGestureHandler; mBackAnimation = backAnimation; mHandler = mainHandler; mUiEventLogger = uiEventLogger; @@ -555,6 +564,29 @@ public class NavigationBar extends ViewController implements mInputMethodManager = inputMethodManager; mUserContextProvider = userContextProvider; + mOnComputeInternalInsetsListener = info -> { + // When the nav bar is in 2-button or 3-button mode, or when IME is visible in fully + // gestural mode, the entire nav bar should be touchable. + if (!mEdgeBackGestureHandler.isHandlingGestures()) { + // We're in 2/3 button mode OR back button force-shown in SUW + if (!mImeVisible) { + // IME not showing, take all touches + info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); + } + if (!mView.isImeRenderingNavButtons()) { + // IME showing but not drawing any buttons, take all touches + info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); + } + } + + // When in gestural and the IME is showing, don't use the nearest region since it will + // take gesture space away from the IME + info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); + info.touchableRegion.set(getButtonLocations(false /* includeFloatingButtons */, + false /* inScreen */, false /* useNearestRegion */)); + }; + + mView.setEdgeBackGestureHandler(mEdgeBackGestureHandler); mNavBarMode = mNavigationModeController.addListener(mModeChangedListener); } @@ -569,6 +601,7 @@ public class NavigationBar extends ViewController implements mView.setBarTransitions(mNavigationBarTransitions); mView.setTouchHandler(mTouchHandler); mView.setNavBarMode(mNavBarMode); + mEdgeBackGestureHandler.setStateChangeCallback(mView::updateStates); mView.updateRotationButton(); mView.setVisibility( @@ -646,11 +679,14 @@ public class NavigationBar extends ViewController implements mView.setNavBarMode(mNavBarMode); mView.setUpdateActiveTouchRegionsCallback( () -> mOverviewProxyService.onActiveNavBarRegionChanges( - mView.getButtonLocations( + getButtonLocations( true /* includeFloatingButtons */, true /* inScreen */, true /* useNearestRegion */))); + mView.getViewTreeObserver().addOnComputeInternalInsetsListener( + mOnComputeInternalInsetsListener); + mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mPipOptional.ifPresent(mView::addPipExclusionBoundsChangeListener); @@ -721,6 +757,8 @@ public class NavigationBar extends ViewController implements mOrientationHandle.getViewTreeObserver().removeOnGlobalLayoutListener( mOrientationHandleGlobalLayoutListener); } + mView.getViewTreeObserver().removeOnComputeInternalInsetsListener( + mOnComputeInternalInsetsListener); mHandler.removeCallbacks(mAutoDim); mHandler.removeCallbacks(mOnVariableDurationHomeLongClick); mHandler.removeCallbacks(mEnableLayoutTransitions); @@ -1044,8 +1082,8 @@ public class NavigationBar extends ViewController implements } private void handleTransientChanged() { - mView.onTransientStateChanged(mTransientShown, - mTransientShownFromGestureOnSystemBar); + mEdgeBackGestureHandler.onNavBarTransientStateChanged(mTransientShown); + final int transitionMode = transitionMode(mTransientShown, mAppearance); if (updateTransitionMode(transitionMode) && mLightBarController != null) { mLightBarController.onNavigationBarModeChanged(transitionMode); @@ -1639,6 +1677,79 @@ public class NavigationBar extends ViewController implements mNavigationIconHints = hints; } + /** + * @param includeFloatingButtons Whether to include the floating rotation and overlay button in + * the region for all the buttons + * @param inScreenSpace Whether to return values in screen space or window space + * @param useNearestRegion Whether to use the nearest region instead of the actual button bounds + * @return + */ + Region getButtonLocations(boolean includeFloatingButtons, boolean inScreenSpace, + boolean useNearestRegion) { + if (useNearestRegion && !inScreenSpace) { + // We currently don't support getting the nearest region in anything but screen space + useNearestRegion = false; + } + Region region = new Region(); + Map touchRegionCache = mView.getButtonTouchRegionCache(); + updateButtonLocation( + region, touchRegionCache, mView.getBackButton(), inScreenSpace, useNearestRegion); + updateButtonLocation( + region, touchRegionCache, mView.getHomeButton(), inScreenSpace, useNearestRegion); + updateButtonLocation(region, touchRegionCache, mView.getRecentsButton(), inScreenSpace, + useNearestRegion); + updateButtonLocation(region, touchRegionCache, mView.getImeSwitchButton(), inScreenSpace, + useNearestRegion); + updateButtonLocation( + region, touchRegionCache, mView.getAccessibilityButton(), inScreenSpace, + useNearestRegion); + if (includeFloatingButtons && mView.getFloatingRotationButton().isVisible()) { + // Note: this button is floating so the nearest region doesn't apply + updateButtonLocation( + region, mView.getFloatingRotationButton().getCurrentView(), inScreenSpace); + } else { + updateButtonLocation(region, touchRegionCache, mView.getRotateSuggestionButton(), + inScreenSpace, useNearestRegion); + } + return region; + } + + private void updateButtonLocation( + Region region, + Map touchRegionCache, + ButtonDispatcher button, + boolean inScreenSpace, + boolean useNearestRegion) { + if (button == null) { + return; + } + View view = button.getCurrentView(); + if (view == null || !button.isVisible()) { + return; + } + // If the button is tappable from perspective of NearestTouchFrame, then we'll + // include the regions where the tap is valid instead of just the button layout location + if (useNearestRegion && touchRegionCache.containsKey(view)) { + region.op(touchRegionCache.get(view), Region.Op.UNION); + return; + } + updateButtonLocation(region, view, inScreenSpace); + } + + private void updateButtonLocation(Region region, View view, boolean inScreenSpace) { + Rect bounds = new Rect(); + if (inScreenSpace) { + view.getBoundsOnScreen(bounds); + } else { + int[] location = new int[2]; + view.getLocationInWindow(location); + bounds.set(location[0], location[1], + location[0] + view.getWidth(), + location[1] + view.getHeight()); + } + region.op(bounds, Region.Op.UNION); + } + private final ModeChangedListener mModeChangedListener = new ModeChangedListener() { @Override public void onNavigationModeChanged(int mode) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java index 93bf136e88f12..f6bfd6c8f9c51 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java @@ -24,6 +24,7 @@ import android.view.WindowManager; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.navigationbar.NavigationBarComponent.NavigationBarScope; +import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler; import dagger.Module; import dagger.Provides; @@ -55,6 +56,14 @@ public interface NavigationBarModule { return barView.findViewById(R.id.navigation_bar_view); } + /** */ + @Provides + @NavigationBarScope + static EdgeBackGestureHandler provideEdgeBackGestureHandler( + EdgeBackGestureHandler.Factory factory, @DisplayId Context context) { + return factory.create(context); + } + /** A WindowManager specific to the display's context. */ @Provides @NavigationBarScope diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 6e00ebc1dc5d2..a13c199df41e0 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -41,8 +41,6 @@ import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.Region; -import android.graphics.Region.Op; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; @@ -53,8 +51,6 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver.InternalInsetsInfo; -import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; import android.view.WindowInsets; import android.view.WindowInsetsController.Behavior; import android.view.WindowManager; @@ -93,7 +89,6 @@ import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.pip.Pip; import java.io.PrintWriter; -import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.concurrent.Executor; @@ -123,11 +118,6 @@ public class NavigationBarView extends FrameLayout { private int mNavBarMode; private boolean mImeDrawsImeNavBar; - private final Region mTmpRegion = new Region(); - private final int[] mTmpPosition = new int[2]; - private Rect mTmpBounds = new Rect(); - private Map mButtonFullTouchableRegions = new HashMap<>(); - private KeyButtonDrawable mBackIcon; private KeyButtonDrawable mHomeDefaultIcon; private KeyButtonDrawable mRecentIcon; @@ -138,7 +128,6 @@ public class NavigationBarView extends FrameLayout { private EdgeBackGestureHandler mEdgeBackGestureHandler; private final DeadZone mDeadZone; - private boolean mDeadZoneConsuming = false; private NavigationBarTransitions mBarTransitions; @Nullable private AutoHideController mAutoHideController; @@ -152,7 +141,6 @@ public class NavigationBarView extends FrameLayout { private boolean mUseCarModeUi = false; private boolean mInCarMode = false; private boolean mDockedStackExists; - private boolean mImeVisible; private boolean mScreenOn = true; private final SparseArray mButtonDispatchers = new SparseArray<>(); @@ -272,31 +260,6 @@ public class NavigationBarView extends FrameLayout { } }; - private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener = info -> { - // When the nav bar is in 2-button or 3-button mode, or when the back button is force-shown - // while in gesture nav in SUW, the entire nav bar should be touchable. - if (!mEdgeBackGestureHandler.isHandlingGestures()) { - // We're in 2/3 button mode OR back button force-shown in SUW - if (!mImeVisible) { - // IME not showing, take all touches - info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); - return; - } - - if (!isImeRenderingNavButtons()) { - // IME showing but not drawing any buttons, take all touches - info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME); - return; - } - } - - // When in gestural and the IME is showing, don't use the nearest region since it will take - // gesture space away from the IME - info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION); - info.touchableRegion.set(getButtonLocations(false /* includeFloatingButtons */, - false /* inScreen */, false /* useNearestRegion */)); - }; - private final RotationButtonUpdatesCallback mRotationButtonListener = new RotationButtonUpdatesCallback() { @Override @@ -315,13 +278,6 @@ public class NavigationBarView extends FrameLayout { } }; - private final Consumer mNavbarOverlayVisibilityChangeCallback = (visible) -> { - if (visible && mAutoHideController != null) { - mAutoHideController.touchAutoHide(); - } - notifyActiveTouchRegions(); - }; - public NavigationBarView(Context context, AttributeSet attrs) { super(context, attrs); @@ -380,9 +336,6 @@ public class NavigationBarView extends FrameLayout { mNavColorSampleMargin = getResources() .getDimensionPixelSize(R.dimen.navigation_handle_sample_horizontal_margin); - mEdgeBackGestureHandler = Dependency.get(EdgeBackGestureHandler.Factory.class) - .create(mContext); - mEdgeBackGestureHandler.setStateChangeCallback(this::updateStates); Executor backgroundExecutor = Dependency.get(Dependency.BACKGROUND_EXECUTOR); mRegionSamplingHelper = new RegionSamplingHelper(this, new RegionSamplingHelper.SamplingCallback() { @@ -409,6 +362,10 @@ public class NavigationBarView extends FrameLayout { }, backgroundExecutor); } + public void setEdgeBackGestureHandler(EdgeBackGestureHandler edgeBackGestureHandler) { + mEdgeBackGestureHandler = edgeBackGestureHandler; + } + void setBarTransitions(NavigationBarTransitions navigationBarTransitions) { mBarTransitions = navigationBarTransitions; } @@ -681,8 +638,7 @@ public class NavigationBarView extends FrameLayout { if (!visible) { mTransitionListener.onBackAltCleared(); } - mImeVisible = visible; - mRotationButtonController.getRotationButton().setCanShowRotationButton(!mImeVisible); + mRotationButtonController.getRotationButton().setCanShowRotationButton(!visible); } void setDisabledFlags(int disabledFlags, SysUiState sysUiState) { @@ -774,7 +730,7 @@ public class NavigationBarView extends FrameLayout { /** * Returns whether the IME is currently visible and drawing the nav buttons. */ - private boolean isImeRenderingNavButtons() { + boolean isImeRenderingNavButtons() { return mImeDrawsImeNavBar && mImeCanRenderGesturalNavButtons && (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0; @@ -1003,75 +959,14 @@ public class NavigationBarView extends FrameLayout { notifyActiveTouchRegions(); } - private void updateButtonTouchRegionCache() { + Map getButtonTouchRegionCache() { FrameLayout navBarLayout = mIsVertical ? mNavigationInflaterView.mVertical : mNavigationInflaterView.mHorizontal; - mButtonFullTouchableRegions = ((NearestTouchFrame) navBarLayout + return ((NearestTouchFrame) navBarLayout .findViewById(R.id.nav_buttons)).getFullTouchableChildRegions(); } - /** - * @param includeFloatingButtons Whether to include the floating rotation and overlay button in - * the region for all the buttons - * @param inScreenSpace Whether to return values in screen space or window space - * @param useNearestRegion Whether to use the nearest region instead of the actual button bounds - * @return - */ - Region getButtonLocations(boolean includeFloatingButtons, boolean inScreenSpace, - boolean useNearestRegion) { - // TODO: move this method to NavigationBar. - // TODO: don't use member variables for temp storage like mTmpRegion. - if (useNearestRegion && !inScreenSpace) { - // We currently don't support getting the nearest region in anything but screen space - useNearestRegion = false; - } - mTmpRegion.setEmpty(); - updateButtonTouchRegionCache(); - updateButtonLocation(getBackButton(), inScreenSpace, useNearestRegion); - updateButtonLocation(getHomeButton(), inScreenSpace, useNearestRegion); - updateButtonLocation(getRecentsButton(), inScreenSpace, useNearestRegion); - updateButtonLocation(getImeSwitchButton(), inScreenSpace, useNearestRegion); - updateButtonLocation(getAccessibilityButton(), inScreenSpace, useNearestRegion); - if (includeFloatingButtons && mFloatingRotationButton.isVisible()) { - // Note: this button is floating so the nearest region doesn't apply - updateButtonLocation(mFloatingRotationButton.getCurrentView(), inScreenSpace); - } else { - updateButtonLocation(getRotateSuggestionButton(), inScreenSpace, useNearestRegion); - } - return mTmpRegion; - } - - private void updateButtonLocation(ButtonDispatcher button, boolean inScreenSpace, - boolean useNearestRegion) { - if (button == null) { - return; - } - View view = button.getCurrentView(); - if (view == null || !button.isVisible()) { - return; - } - // If the button is tappable from perspective of NearestTouchFrame, then we'll - // include the regions where the tap is valid instead of just the button layout location - if (useNearestRegion && mButtonFullTouchableRegions.containsKey(view)) { - mTmpRegion.op(mButtonFullTouchableRegions.get(view), Op.UNION); - return; - } - updateButtonLocation(view, inScreenSpace); - } - - private void updateButtonLocation(View view, boolean inScreenSpace) { - if (inScreenSpace) { - view.getBoundsOnScreen(mTmpBounds); - } else { - view.getLocationInWindow(mTmpPosition); - mTmpBounds.set(mTmpPosition[0], mTmpPosition[1], - mTmpPosition[0] + view.getWidth(), - mTmpPosition[1] + view.getHeight()); - } - mTmpRegion.op(mTmpBounds, Op.UNION); - } - private void updateOrientationViews() { mHorizontal = findViewById(R.id.horizontal); mVertical = findViewById(R.id.vertical); @@ -1272,7 +1167,6 @@ public class NavigationBarView extends FrameLayout { mRotationButtonController.registerListeners(); } - getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener); updateNavButtonIcons(); } @@ -1288,8 +1182,6 @@ public class NavigationBarView extends FrameLayout { } mEdgeBackGestureHandler.onNavBarDetached(); - getViewTreeObserver().removeOnComputeInternalInsetsListener( - mOnComputeInternalInsetsListener); } public void dump(PrintWriter pw) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 7c303985d6512..a52608733ca42 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -60,6 +60,7 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.MotionEvent; import android.view.View; +import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowMetrics; @@ -164,7 +165,7 @@ public class NavigationBarTest extends SysuiTestCase { @Mock private UiEventLogger mUiEventLogger; @Mock - EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory; + private ViewTreeObserver mViewTreeObserver; @Mock EdgeBackGestureHandler mEdgeBackGestureHandler; NavBarHelper mNavBarHelper; @@ -199,8 +200,6 @@ public class NavigationBarTest extends SysuiTestCase { public void setup() throws Exception { MockitoAnnotations.initMocks(this); - when(mEdgeBackGestureHandlerFactory.create(any(Context.class))) - .thenReturn(mEdgeBackGestureHandler); when(mLightBarcontrollerFactory.create(any(Context.class))).thenReturn(mLightBarController); when(mAutoHideControllerFactory.create(any(Context.class))).thenReturn(mAutoHideController); when(mNavigationBarView.getHomeButton()).thenReturn(mHomeButton); @@ -213,6 +212,7 @@ public class NavigationBarTest extends SysuiTestCase { when(mNavigationBarTransitions.getLightTransitionsController()) .thenReturn(mLightBarTransitionsController); when(mStatusBarKeyguardViewManager.isNavBarVisible()).thenReturn(true); + when(mNavigationBarView.getViewTreeObserver()).thenReturn(mViewTreeObserver); when(mUserContextProvider.createCurrentUserContext(any(Context.class))) .thenReturn(mContext); setupSysuiDependency(); @@ -222,8 +222,6 @@ public class NavigationBarTest extends SysuiTestCase { mDependency.injectMockDependency(KeyguardStateController.class); mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController); mDependency.injectMockDependency(NavigationBarController.class); - mDependency.injectTestDependency(EdgeBackGestureHandler.Factory.class, - mEdgeBackGestureHandlerFactory); mDependency.injectTestDependency(OverviewProxyService.class, mOverviewProxyService); mDependency.injectTestDependency(NavigationModeController.class, mNavigationModeController); TestableLooper.get(this).runWithLooper(() -> { @@ -463,6 +461,7 @@ public class NavigationBarTest extends SysuiTestCase { mDeadZone, mDeviceConfigProxyFake, mNavigationBarTransitions, + mEdgeBackGestureHandler, Optional.of(mock(BackAnimation.class)), mUserContextProvider)); }