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

Commit 2b7d70be authored by Dave Mankoff's avatar Dave Mankoff Committed by Android (Google) Code Review
Browse files

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

parents bd588d16 c6999a66
Loading
Loading
Loading
Loading
+114 −3
Original line number Diff line number Diff line
@@ -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) {
+9 −0
Original line number Diff line number Diff line
@@ -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
+8 −116
Original line number Diff line number Diff line
@@ -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.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) {
+4 −5
Original line number Diff line number Diff line
@@ -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));
    }