Merge "Remove Dependency#get calls from NavigationBarView" into tm-dev

This commit is contained in:
Dave Mankoff
2022-05-06 02:46:22 +00:00
committed by Android (Google) Code Review
4 changed files with 135 additions and 124 deletions

View File

@@ -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<NavigationBarView> implements
private final Optional<Recents> mRecentsOptional;
private final DeviceConfigProxy mDeviceConfigProxy;
private final NavigationBarTransitions mNavigationBarTransitions;
private final EdgeBackGestureHandler mEdgeBackGestureHandler;
private final Optional<BackAnimation> 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<NavigationBarView> implements
DeadZone deadZone,
DeviceConfigProxy deviceConfigProxy,
NavigationBarTransitions navigationBarTransitions,
EdgeBackGestureHandler edgeBackGestureHandler,
Optional<BackAnimation> backAnimation,
UserContextProvider userContextProvider) {
super(navigationBarView);
@@ -542,6 +550,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mDeadZone = deadZone;
mDeviceConfigProxy = deviceConfigProxy;
mNavigationBarTransitions = navigationBarTransitions;
mEdgeBackGestureHandler = edgeBackGestureHandler;
mBackAnimation = backAnimation;
mHandler = mainHandler;
mUiEventLogger = uiEventLogger;
@@ -555,6 +564,29 @@ public class NavigationBar extends ViewController<NavigationBarView> 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<NavigationBarView> 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<NavigationBarView> 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<NavigationBarView> 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<NavigationBarView> 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<NavigationBarView> 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<View, Rect> 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<View, Rect> 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) {

View File

@@ -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

View File

@@ -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<View, Rect> 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<ButtonDispatcher> 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<Boolean> 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<View, Rect> 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) {

View File

@@ -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));
}