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

Commit 38412951 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Keeing the device in gesture nav while user setup is pending

> Sending different insets to the app during user setup
> Keeping the back butotn visible and not handling edge swipe
> Fixing bug where EdgeBackGestureHandler is not updated with correct
  edge scale when user switches

Bug: 150004073
Bug: 148492421
Test: Manual
Change-Id: I112465a634de2c85d613c071b66f8c099c2c78e3
parent f996e424
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
        r.registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT),
                false, this, UserHandle.USER_ALL);
        r.registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE),
                false, this, UserHandle.USER_ALL);
    }

    public void unregister() {
@@ -68,6 +71,11 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
        return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT);
    }

    public boolean areNavigationButtonForcedVisible() {
        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) == 0;
    }

    private int getSensitivity(Resources userRes, String side) {
        final int inset = userRes.getDimensionPixelSize(
                com.android.internal.R.dimen.config_backGestureInset);
+33 −10
Original line number Diff line number Diff line
@@ -53,11 +53,13 @@ import android.view.WindowManagerGlobal;
import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
@@ -74,7 +76,7 @@ import java.util.concurrent.Executor;
/**
 * Utility class to handle edge swipes for back gesture
 */
public class EdgeBackGestureHandler implements DisplayListener,
public class EdgeBackGestureHandler extends CurrentUserTracker implements DisplayListener,
        PluginListener<NavigationEdgeBackPlugin>, ProtoTraceable<SystemUiTraceProto> {

    private static final String TAG = "EdgeBackGestureHandler";
@@ -165,6 +167,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
    private boolean mIsGesturalModeEnabled;
    private boolean mIsEnabled;
    private boolean mIsNavBarShownTransiently;
    private boolean mIsBackGestureAllowed;

    private InputMonitor mInputMonitor;
    private InputEventReceiver mInputEventReceiver;
@@ -200,7 +203,7 @@ public class EdgeBackGestureHandler implements DisplayListener,

    public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService,
            SysUiState sysUiFlagContainer, PluginManager pluginManager) {
        final Resources res = context.getResources();
        super(Dependency.get(BroadcastDispatcher.class));
        mContext = context;
        mDisplayId = context.getDisplayId();
        mMainExecutor = context.getMainExecutor();
@@ -216,20 +219,30 @@ public class EdgeBackGestureHandler implements DisplayListener,
                ViewConfiguration.getLongPressTimeout());

        mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(
                mContext.getMainThreadHandler(), mContext, () -> updateCurrentUserResources(res));
                mContext.getMainThreadHandler(), mContext, this::updateCurrentUserResources);

        updateCurrentUserResources(res);
        updateCurrentUserResources();
        sysUiFlagContainer.addCallback(sysUiFlags -> mSysUiFlags = sysUiFlags);
    }

    public void updateCurrentUserResources(Resources res) {
    public void updateCurrentUserResources() {
        Resources res = Dependency.get(NavigationModeController.class).getCurrentUserContext()
                .getResources();
        mEdgeWidthLeft = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
        mEdgeWidthRight = mGestureNavigationSettingsObserver.getRightSensitivity(res);
        mIsBackGestureAllowed =
                !mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();

        mBottomGestureHeight = res.getDimensionPixelSize(
                com.android.internal.R.dimen.navigation_bar_gesture_height);
    }

    @Override
    public void onUserSwitched(int newUserId) {
        updateIsEnabled();
        updateCurrentUserResources();
    }

    /**
     * @see NavigationBarView#onAttachedToWindow()
     */
@@ -243,6 +256,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
                Settings.Global.getUriFor(FIXED_ROTATION_TRANSFORM_SETTING_NAME),
                false /* notifyForDescendants */, mFixedRotationObserver, UserHandle.USER_ALL);
        updateIsEnabled();
        startTracking();
    }

    /**
@@ -255,6 +269,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
        }
        mContext.getContentResolver().unregisterContentObserver(mFixedRotationObserver);
        updateIsEnabled();
        stopTracking();
    }

    private void setRotationCallbacks(boolean enable) {
@@ -269,10 +284,13 @@ public class EdgeBackGestureHandler implements DisplayListener,
        }
    }

    public void onNavigationModeChanged(int mode, Context currentUserContext) {
    /**
     * @see NavigationModeController.ModeChangedListener#onNavigationModeChanged
     */
    public void onNavigationModeChanged(int mode) {
        mIsGesturalModeEnabled = QuickStepContract.isGesturalMode(mode);
        updateIsEnabled();
        updateCurrentUserResources(currentUserContext.getResources());
        updateCurrentUserResources();
    }

    public void onNavBarTransientStateChanged(boolean isTransient) {
@@ -363,6 +381,10 @@ public class EdgeBackGestureHandler implements DisplayListener,
        updateDisplaySize();
    }

    public boolean isHandlingGestures() {
        return mIsEnabled && mIsBackGestureAllowed;
    }

    private WindowManager.LayoutParams createLayoutParams() {
        Resources resources = mContext.getResources();
        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
@@ -469,9 +491,9 @@ public class EdgeBackGestureHandler implements DisplayListener,
            mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
            mLogGesture = false;
            mInRejectedExclusion = false;
            mAllowGesture = !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY())
                    && !mDisabledForQuickstep;
            mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed
                    && !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
            if (mAllowGesture) {
                mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
                mEdgeBackPlugin.onMotionEvent(ev);
@@ -599,6 +621,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
    public void dump(PrintWriter pw) {
        pw.println("EdgeBackGestureHandler:");
        pw.println("  mIsEnabled=" + mIsEnabled);
        pw.println("  mIsBackGestureAllowed=" + mIsBackGestureAllowed);
        pw.println("  mAllowGesture=" + mAllowGesture);
        pw.println("  mDisabledForQuickstep=" + mDisabledForQuickstep);
        pw.println("  mInRejectedExclusion" + mInRejectedExclusion);
+9 −11
Original line number Diff line number Diff line
@@ -123,7 +123,7 @@ public class NavigationBarView extends FrameLayout implements
    private KeyButtonDrawable mRecentIcon;
    private KeyButtonDrawable mDockedIcon;

    private final EdgeBackGestureHandler mEdgeBackGestureHandler;
    private EdgeBackGestureHandler mEdgeBackGestureHandler;
    private final DeadZone mDeadZone;
    private boolean mDeadZoneConsuming = false;
    private final NavigationBarTransitions mBarTransitions;
@@ -244,7 +244,7 @@ public class NavigationBarView extends FrameLayout implements
    private final OnComputeInternalInsetsListener 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 (!isGesturalMode(mNavBarMode) || mImeVisible) {
        if (!mEdgeBackGestureHandler.isHandlingGestures() || mImeVisible) {
            info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
            return;
        }
@@ -296,8 +296,6 @@ public class NavigationBarView extends FrameLayout implements
                R.style.RotateButtonCCWStart90,
                isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton);

        final ContextualButton backButton = new ContextualButton(R.id.back, 0);

        mConfiguration = new Configuration();
        mTmpLastConfiguration = new Configuration();
        mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -305,7 +303,7 @@ public class NavigationBarView extends FrameLayout implements
        mScreenPinningNotify = new ScreenPinningNotify(mContext);
        mBarTransitions = new NavigationBarTransitions(this, Dependency.get(CommandQueue.class));

        mButtonDispatchers.put(R.id.back, backButton);
        mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
        mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
        mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
        mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
@@ -659,7 +657,7 @@ public class NavigationBarView extends FrameLayout implements
        boolean disableHomeHandle = disableRecent
                && ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);

        boolean disableBack = !useAltBack && (isGesturalMode(mNavBarMode)
        boolean disableBack = !useAltBack && (mEdgeBackGestureHandler.isHandlingGestures()
                || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));

        // When screen pinning, don't hide back and home when connected service or back and
@@ -838,10 +836,9 @@ public class NavigationBarView extends FrameLayout implements

    @Override
    public void onNavigationModeChanged(int mode) {
        Context curUserCtx = Dependency.get(NavigationModeController.class).getCurrentUserContext();
        mNavBarMode = mode;
        mBarTransitions.onNavigationModeChanged(mNavBarMode);
        mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode, curUserCtx);
        mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode);
        mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
        getRotateSuggestionButton().onNavigationModeChanged(mNavBarMode);

@@ -864,6 +861,7 @@ public class NavigationBarView extends FrameLayout implements

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        mNavigationInflaterView = findViewById(R.id.navigation_inflater);
        mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);

+5 −151
Original line number Diff line number Diff line
@@ -17,9 +17,6 @@
package com.android.systemui.statusbar.phone;

import static android.content.Intent.ACTION_OVERLAY_CHANGED;
import static android.content.Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
import static android.os.UserHandle.USER_CURRENT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;

@@ -38,17 +35,14 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.util.Log;
import android.util.SparseBooleanArray;

import com.android.systemui.Dumpable;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Executor;

import javax.inject.Inject;
@@ -70,104 +64,34 @@ public class NavigationModeController implements Dumpable {
    private final Context mContext;
    private Context mCurrentUserContext;
    private final IOverlayManager mOverlayManager;
    private final DeviceProvisionedController mDeviceProvisionedController;
    private final Executor mUiBgExecutor;

    private SparseBooleanArray mRestoreGesturalNavBarMode = new SparseBooleanArray();

    private ArrayList<ModeChangedListener> mListeners = new ArrayList<>();

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case ACTION_OVERLAY_CHANGED:
                    if (DEBUG) {
                        Log.d(TAG, "ACTION_OVERLAY_CHANGED");
                    }
                    updateCurrentInteractionMode(true /* notify */);
                    break;
            }
        }
    };

    private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedCallback =
            new DeviceProvisionedController.DeviceProvisionedListener() {
                @Override
                public void onDeviceProvisionedChanged() {
                    if (DEBUG) {
                        Log.d(TAG, "onDeviceProvisionedChanged: "
                                + mDeviceProvisionedController.isDeviceProvisioned());
                    }
                    // Once the device has been provisioned, check if we can restore gestural nav
                    restoreGesturalNavOverlayIfNecessary();
                }

                @Override
                public void onUserSetupChanged() {
                    if (DEBUG) {
                        Log.d(TAG, "onUserSetupChanged: "
                                + mDeviceProvisionedController.isCurrentUserSetup());
                    }
                    // Once the user has been setup, check if we can restore gestural nav
                    restoreGesturalNavOverlayIfNecessary();
                }

                @Override
                public void onUserSwitched() {
                    if (DEBUG) {
                        Log.d(TAG, "onUserSwitched: "
                                + ActivityManagerWrapper.getInstance().getCurrentUserId());
                    }

                    // Update the nav mode for the current user
                    updateCurrentInteractionMode(true /* notify */);

                    // When switching users, defer enabling the gestural nav overlay until the user
                    // is all set up
                    deferGesturalNavOverlayIfNecessary();
        }
    };

    @Inject
    public NavigationModeController(Context context,
            DeviceProvisionedController deviceProvisionedController,
            @UiBackground Executor uiBgExecutor) {
    public NavigationModeController(Context context, @UiBackground Executor uiBgExecutor) {
        mContext = context;
        mCurrentUserContext = context;
        mOverlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        mUiBgExecutor = uiBgExecutor;
        mDeviceProvisionedController = deviceProvisionedController;
        mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);

        IntentFilter overlayFilter = new IntentFilter(ACTION_OVERLAY_CHANGED);
        overlayFilter.addDataScheme("package");
        overlayFilter.addDataSchemeSpecificPart("android", PatternMatcher.PATTERN_LITERAL);
        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);

        IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED);
        mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
                null);

        updateCurrentInteractionMode(false /* notify */);

        // Check if we need to defer enabling gestural nav
        deferGesturalNavOverlayIfNecessary();
    }

    private boolean setGestureModeOverlayForMainLauncher() {
        if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL) {
            // Already in gesture mode
            return true;
        }

        Log.d(TAG, "Switching system navigation to full-gesture mode:"
                + " contextUser="
                + mCurrentUserContext.getUserId());

        setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
        return true;
    }

    public void updateCurrentInteractionMode(boolean notify) {
@@ -176,10 +100,9 @@ public class NavigationModeController implements Dumpable {
        if (mode == NAV_BAR_MODE_GESTURAL) {
            switchToDefaultGestureNavOverlayIfNecessary();
        }
        mUiBgExecutor.execute(() -> {
        mUiBgExecutor.execute(() ->
            Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
                    Secure.NAVIGATION_MODE, String.valueOf(mode));
        });
                    Secure.NAVIGATION_MODE, String.valueOf(mode)));
        if (DEBUG) {
            Log.e(TAG, "updateCurrentInteractionMode: mode=" + mode);
            dumpAssetPaths(mCurrentUserContext);
@@ -230,61 +153,11 @@ public class NavigationModeController implements Dumpable {
        }
    }

    private void deferGesturalNavOverlayIfNecessary() {
        final int userId = mDeviceProvisionedController.getCurrentUser();
        mRestoreGesturalNavBarMode.put(userId, false);
        if (mDeviceProvisionedController.isDeviceProvisioned()
                && mDeviceProvisionedController.isCurrentUserSetup()) {
            // User is already setup and device is provisioned, nothing to do
            if (DEBUG) {
                Log.d(TAG, "deferGesturalNavOverlayIfNecessary: device is provisioned and user is "
                        + "setup");
            }
            return;
        }

        ArrayList<String> defaultOverlays = new ArrayList<>();
        try {
            defaultOverlays.addAll(Arrays.asList(mOverlayManager.getDefaultOverlayPackages()));
        } catch (RemoteException e) {
            Log.e(TAG, "deferGesturalNavOverlayIfNecessary: failed to fetch default overlays");
        }
        if (!defaultOverlays.contains(NAV_BAR_MODE_GESTURAL_OVERLAY)) {
            // No default gesture nav overlay
            if (DEBUG) {
                Log.d(TAG, "deferGesturalNavOverlayIfNecessary: no default gestural overlay, "
                        + "default=" + defaultOverlays);
            }
            return;
        }

        // If the default is gestural, force-enable three button mode until the device is
        // provisioned
        setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
        mRestoreGesturalNavBarMode.put(userId, true);

        if (DEBUG) {
            Log.d(TAG, "deferGesturalNavOverlayIfNecessary: setting to 3 button mode");
        }
    }

    private void restoreGesturalNavOverlayIfNecessary() {
        if (DEBUG) {
            Log.d(TAG, "restoreGesturalNavOverlayIfNecessary: needs restore="
                    + mRestoreGesturalNavBarMode);
        }
        final int userId = mDeviceProvisionedController.getCurrentUser();
        if (mRestoreGesturalNavBarMode.get(userId)) {
            // Restore the gestural state if necessary
            setGestureModeOverlayForMainLauncher();
            mRestoreGesturalNavBarMode.put(userId, false);
        }
    }

    private void switchToDefaultGestureNavOverlayIfNecessary() {
        final int userId = mCurrentUserContext.getUserId();
        try {
            final IOverlayManager om = mOverlayManager;
            final IOverlayManager om = IOverlayManager.Stub.asInterface(
                    ServiceManager.getService(Context.OVERLAY_SERVICE));
            final OverlayInfo info = om.getOverlayInfo(NAV_BAR_MODE_GESTURAL_OVERLAY, userId);
            if (info != null && !info.isEnabled()) {
                // Enable the default gesture nav overlay, and move the back gesture inset scale to
@@ -309,20 +182,6 @@ public class NavigationModeController implements Dumpable {
        }
    }

    public void setModeOverlay(String overlayPkg, int userId) {
        mUiBgExecutor.execute(() -> {
            try {
                mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
                if (DEBUG) {
                    Log.d(TAG, "setModeOverlay: overlayPackage=" + overlayPkg
                            + " userId=" + userId);
                }
            } catch (SecurityException | IllegalStateException | RemoteException e) {
                Log.e(TAG, "Failed to enable overlay " + overlayPkg + " for user " + userId);
            }
        });
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        pw.println("NavigationModeController:");
@@ -334,11 +193,6 @@ public class NavigationModeController implements Dumpable {
            defaultOverlays = "failed_to_fetch";
        }
        pw.println("  defaultOverlays=" + defaultOverlays);
        pw.println("  restoreGesturalNavMode:");
        for (int i = 0; i < mRestoreGesturalNavBarMode.size(); i++) {
            pw.println("    userId=" + mRestoreGesturalNavBarMode.keyAt(i)
                    + " shouldRestore=" + mRestoreGesturalNavBarMode.valueAt(i));
        }
        dumpAssetPaths(mCurrentUserContext);
    }

+4 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.systemui.statusbar.phone;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -50,9 +51,11 @@ public class NavigationBarTransitionsTest extends SysuiTestCase {
        mDependency.injectMockDependency(IWindowManager.class);
        mDependency.injectMockDependency(AssistManager.class);
        mDependency.injectMockDependency(OverviewProxyService.class);
        mDependency.injectMockDependency(NavigationModeController.class);
        mDependency.injectMockDependency(StatusBarStateController.class);
        mDependency.injectMockDependency(KeyguardStateController.class);
        doReturn(mContext)
                .when(mDependency.injectMockDependency(NavigationModeController.class))
                .getCurrentUserContext();

        NavigationBarView navBar = spy(new NavigationBarView(mContext, null));
        when(navBar.getCurrentView()).thenReturn(navBar);
Loading