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

Commit 6324c67c authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "Applies left and right edge scale to side swipe width" into rvc-dev am:...

Merge "Applies left and right edge scale to side swipe width" into rvc-dev am: 7161e498 am: d2cda47d am: ceaabbd6

Change-Id: I7f9490d9232ba5275ac1c6c7c1b827a39f896d2a
parents 38d85927 ceaabbd6
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.policy;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;

/**
 * @hide
 */
public class GestureNavigationSettingsObserver extends ContentObserver {
    private Context mContext;
    private Runnable mOnChangeRunnable;

    public GestureNavigationSettingsObserver(Handler handler, Context context,
            Runnable onChangeRunnable) {
        super(handler);
        mContext = context;
        mOnChangeRunnable = onChangeRunnable;
    }

    public void register() {
        ContentResolver r = mContext.getContentResolver();
        r.registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT),
                false, this, UserHandle.USER_ALL);
        r.registerContentObserver(
                Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT),
                false, this, UserHandle.USER_ALL);
    }

    public void unregister() {
        mContext.getContentResolver().unregisterContentObserver(this);
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        if (mOnChangeRunnable != null) {
            mOnChangeRunnable.run();
        }
    }

    public int getLeftSensitivity(Resources userRes) {
        return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT);
    }

    public int getRightSensitivity(Resources userRes) {
        return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT);
    }

    private int getSensitivity(Resources userRes, String side) {
        final int inset = userRes.getDimensionPixelSize(
                com.android.internal.R.dimen.config_backGestureInset);
        final float scale = Settings.Secure.getFloatForUser(
                mContext.getContentResolver(), side, 1.0f, UserHandle.USER_CURRENT);
        return (int) (inset * scale);
    }
}
+20 −7
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;

import com.android.internal.policy.GestureNavigationSettingsObserver;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
@@ -99,8 +100,10 @@ public class EdgeBackGestureHandler implements DisplayListener,
    private final Region mExcludeRegion = new Region();
    private final Region mUnrestrictedExcludeRegion = new Region();

    // The edge width where touch down is allowed
    private int mEdgeWidth;
    // The left side edge width where touch down is allowed
    private int mEdgeWidthLeft;
    // The right side edge width where touch down is allowed
    private int mEdgeWidthRight;
    // The bottom gesture area height
    private int mBottomGestureHeight;
    // The slop to distinguish between horizontal and vertical motion
@@ -127,6 +130,8 @@ public class EdgeBackGestureHandler implements DisplayListener,
    private int mRightInset;
    private int mSysUiFlags;

    private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;

    private final NavigationEdgeBackPlugin.BackCallback mBackCallback =
            new NavigationEdgeBackPlugin.BackCallback() {
                @Override
@@ -174,13 +179,17 @@ public class EdgeBackGestureHandler implements DisplayListener,
        mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
                ViewConfiguration.getLongPressTimeout());

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

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

    public void updateCurrentUserResources(Resources res) {
        mEdgeWidth = res.getDimensionPixelSize(
                com.android.internal.R.dimen.config_backGestureInset);
        mEdgeWidthLeft = mGestureNavigationSettingsObserver.getLeftSensitivity(res);
        mEdgeWidthRight = mGestureNavigationSettingsObserver.getRightSensitivity(res);

        mBottomGestureHeight = res.getDimensionPixelSize(
                com.android.internal.R.dimen.navigation_bar_gesture_height);
    }
@@ -236,6 +245,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
        }

        if (!mIsEnabled) {
            mGestureNavigationSettingsObserver.unregister();
            mContext.getSystemService(DisplayManager.class).unregisterDisplayListener(this);
            mPluginManager.removePluginListener(this);

@@ -248,6 +258,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
            }

        } else {
            mGestureNavigationSettingsObserver.register();
            updateDisplaySize();
            mContext.getSystemService(DisplayManager.class).registerDisplayListener(this,
                    mContext.getMainThreadHandler());
@@ -321,7 +332,8 @@ public class EdgeBackGestureHandler implements DisplayListener,

    private boolean isWithinTouchRegion(int x, int y) {
        // Disallow if too far from the edge
        if (x > mEdgeWidth + mLeftInset && x < (mDisplaySize.x - mEdgeWidth - mRightInset)) {
        if (x > mEdgeWidthLeft + mLeftInset
                && x < (mDisplaySize.x - mEdgeWidthRight - mRightInset)) {
            return false;
        }

@@ -364,7 +376,7 @@ public class EdgeBackGestureHandler implements DisplayListener,
        if (action == MotionEvent.ACTION_DOWN) {
            // Verify if this is in within the touch region and we aren't in immersive mode, and
            // either the bouncer is showing or the notification panel is hidden
            mIsOnLeftEdge = ev.getX() <= mEdgeWidth + mLeftInset;
            mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
            mInRejectedExclusion = false;
            mAllowGesture = !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
@@ -461,7 +473,8 @@ public class EdgeBackGestureHandler implements DisplayListener,
        pw.println("  mExcludeRegion=" + mExcludeRegion);
        pw.println("  mUnrestrictedExcludeRegion=" + mUnrestrictedExcludeRegion);
        pw.println("  mIsAttached=" + mIsAttached);
        pw.println("  mEdgeWidth=" + mEdgeWidth);
        pw.println("  mEdgeWidthLeft=" + mEdgeWidthLeft);
        pw.println("  mEdgeWidthRight=" + mEdgeWidthRight);
    }

    @Override
+32 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
import android.content.pm.PackageManager;
import android.content.res.ApkAssets;
import android.os.PatternMatcher;
@@ -172,6 +173,9 @@ public class NavigationModeController implements Dumpable {
    public void updateCurrentInteractionMode(boolean notify) {
        mCurrentUserContext = getCurrentUserContext();
        int mode = getCurrentInteractionMode(mCurrentUserContext);
        if (mode == NAV_BAR_MODE_GESTURAL) {
            switchToDefaultGestureNavOverlayIfNecessary();
        }
        mUiBgExecutor.execute(() -> {
            Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
                    Secure.NAVIGATION_MODE, String.valueOf(mode));
@@ -277,6 +281,34 @@ public class NavigationModeController implements Dumpable {
        }
    }

    private void switchToDefaultGestureNavOverlayIfNecessary() {
        final int userId = mCurrentUserContext.getUserId();
        try {
            final IOverlayManager om = mOverlayManager;
            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
                // Settings.Secure for left and right sensitivity.
                final int curInset = mCurrentUserContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.config_backGestureInset);
                om.setEnabledExclusiveInCategory(NAV_BAR_MODE_GESTURAL_OVERLAY, userId);
                final int defInset = mCurrentUserContext.getResources().getDimensionPixelSize(
                        com.android.internal.R.dimen.config_backGestureInset);

                final float scale = defInset == 0 ? 1.0f : ((float) curInset) / defInset;
                Settings.Secure.putFloat(mCurrentUserContext.getContentResolver(),
                        Secure.BACK_GESTURE_INSET_SCALE_LEFT, scale);
                Settings.Secure.putFloat(mCurrentUserContext.getContentResolver(),
                        Secure.BACK_GESTURE_INSET_SCALE_RIGHT, scale);
                if (DEBUG) {
                    Log.v(TAG, "Moved back sensitivity for user " + userId + " to scale " + scale);
                }
            }
        } catch (SecurityException | IllegalStateException | RemoteException e) {
            Log.e(TAG, "Failed to switch to default gesture nav overlay for user " + userId);
        }
    }

    public void setModeOverlay(String overlayPkg, int userId) {
        mUiBgExecutor.execute(() -> {
            try {
+0 −228
Original line number Diff line number Diff line
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.phone;

import static android.view.Display.DEFAULT_DISPLAY;

import android.annotation.IntDef;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.graphics.Point;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Coordinates with the prototype settings plugin app that uses Settings.Global to allow different
 * prototypes to run in the system. The class will handle communication changes from the settings
 * app and call back to listeners.
 */
public class NavigationPrototypeController extends ContentObserver implements ComponentCallbacks {
    private static final String HIDE_BACK_BUTTON_SETTING = "quickstepcontroller_hideback";
    private static final String HIDE_HOME_BUTTON_SETTING = "quickstepcontroller_hidehome";
    private static final String PROTOTYPE_ENABLED = "prototype_enabled";

    public static final String EDGE_SENSITIVITY_WIDTH_SETTING =
            "quickstepcontroller_edge_width_sensitivity";
    private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map";
    public static final String NAV_COLOR_ADAPT_ENABLE_SETTING = "navbar_color_adapt_enable";
    public static final String SHOW_HOME_HANDLE_SETTING = "quickstepcontroller_showhandle";
    public static final String ENABLE_ASSISTANT_GESTURE = "ENABLE_ASSISTANT_GESTURE";

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({ACTION_DEFAULT, ACTION_QUICKSTEP, ACTION_QUICKSCRUB, ACTION_BACK,
            ACTION_QUICKSWITCH, ACTION_NOTHING, ACTION_ASSISTANT})
    @interface GestureAction {}
    static final int ACTION_DEFAULT = 0;
    static final int ACTION_QUICKSTEP = 1;
    static final int ACTION_QUICKSCRUB = 2;
    static final int ACTION_BACK = 3;
    static final int ACTION_QUICKSWITCH = 4;
    static final int ACTION_NOTHING = 5;
    static final int ACTION_ASSISTANT = 6;

    private OnPrototypeChangedListener mListener;

    /**
     * Each index corresponds to a different action set in QuickStepController
     * {@see updateSwipeLTRBackSetting}
     */
    private int[] mActionMap = new int[6];

    private final Context mContext;

    public NavigationPrototypeController(Context context) {
        super(new Handler());
        mContext = context;
        updateSwipeLTRBackSetting();
    }

    public void setOnPrototypeChangedListener(OnPrototypeChangedListener listener) {
        mListener = listener;
    }

    /**
     * Observe all the settings to react to from prototype settings
     */
    public void register() {
        registerObserver(HIDE_BACK_BUTTON_SETTING);
        registerObserver(HIDE_HOME_BUTTON_SETTING);
        registerObserver(GESTURE_MATCH_SETTING);
        registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING);
        registerObserver(SHOW_HOME_HANDLE_SETTING);
        registerObserver(ENABLE_ASSISTANT_GESTURE);
        mContext.registerComponentCallbacks(this);
    }

    /**
     * Disable observing settings to react to from prototype settings
     */
    public void unregister() {
        mContext.getContentResolver().unregisterContentObserver(this);
        mContext.unregisterComponentCallbacks(this);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange, uri);
        if (!selfChange && mListener != null) {
            final String path = uri.getPath();
            if (path.endsWith(GESTURE_MATCH_SETTING)) {
                // Get the settings gesture map corresponding to each action
                // {@see updateSwipeLTRBackSetting}
                updateSwipeLTRBackSetting();
                mListener.onGestureRemap(mActionMap);
            } else if (path.endsWith(HIDE_BACK_BUTTON_SETTING)) {
                mListener.onBackButtonVisibilityChanged(
                        !getGlobalBool(HIDE_BACK_BUTTON_SETTING, false));
            } else if (path.endsWith(HIDE_HOME_BUTTON_SETTING)) {
                mListener.onHomeButtonVisibilityChanged(!hideHomeButton());
            } else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) {
                mListener.onColorAdaptChanged(mContext.getDisplayId() == DEFAULT_DISPLAY);
            } else if (path.endsWith(SHOW_HOME_HANDLE_SETTING)) {
                mListener.onHomeHandleVisiblilityChanged(showHomeHandle());
            } else if (path.endsWith(ENABLE_ASSISTANT_GESTURE)) {
                mListener.onAssistantGestureEnabled(isAssistantGestureEnabled());
            }
        }
    }

    /**
     * @return the width for edge swipe
     */
    public int getEdgeSensitivityWidth() {
        return mContext.getResources().getDimensionPixelSize(
                com.android.internal.R.dimen.config_backGestureInset);
    }

    /**
     * @return full screen height
     */
    public int getEdgeSensitivityHeight() {
        final Point size = new Point();
        mContext.getDisplay().getRealSize(size);
        return size.y;
    }

    public boolean isEnabled() {
        return getGlobalBool(PROTOTYPE_ENABLED, false);
    }

    /**
     * Retrieve the action map to apply to the quick step controller
     * @return an action map
     */
    int[] getGestureActionMap() {
        return mActionMap;
    }

    /**
     * @return if home button should be invisible
     */
    boolean hideHomeButton() {
        return getGlobalBool(HIDE_HOME_BUTTON_SETTING, false /* default */);
    }

    boolean showHomeHandle() {
        return getGlobalBool(SHOW_HOME_HANDLE_SETTING, false /* default */);
    }

    boolean isAssistantGestureEnabled() {
        return getGlobalBool(ENABLE_ASSISTANT_GESTURE, false /* default */);
    }


    /**
     * Since Settings.Global cannot pass arrays, use a string to represent each character as a
     * gesture map to actions corresponding to {@see GestureAction}. The number is represented as:
     * Number: [up] [down] [left] [right]
     */
    private void updateSwipeLTRBackSetting() {
        String value = Settings.Global.getString(mContext.getContentResolver(),
                GESTURE_MATCH_SETTING);
        if (value != null) {
            for (int i = 0; i < mActionMap.length; ++i) {
                mActionMap[i] = Character.getNumericValue(value.charAt(i));
            }
        }
    }

    private boolean getGlobalBool(String name, boolean defaultVal) {
        return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal ? 1 : 0) == 1;
    }

    private int getGlobalInt(String name, int defaultVal) {
        return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal);
    }

    private void registerObserver(String name) {
        mContext.getContentResolver()
                .registerContentObserver(Settings.Global.getUriFor(name), false, this);
    }

    private static int convertDpToPixel(float dp) {
        return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (mListener != null) {
            mListener.onEdgeSensitivityChanged(getEdgeSensitivityWidth(),
                    getEdgeSensitivityHeight());
        }
    }

    @Override
    public void onLowMemory() {
    }

    public interface OnPrototypeChangedListener {
        void onGestureRemap(@GestureAction int[] actions);
        void onBackButtonVisibilityChanged(boolean visible);
        void onHomeButtonVisibilityChanged(boolean visible);
        void onHomeHandleVisiblilityChanged(boolean visible);
        void onColorAdaptChanged(boolean enabled);
        void onEdgeSensitivityChanged(int width, int height);
        void onAssistantGestureEnabled(boolean enabled);
    }
}
+1 −0
Original line number Diff line number Diff line
@@ -6523,6 +6523,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            lastReparentedStack.postReparent();
        }
        releaseSelfIfNeeded();
        mDisplayPolicy.release();

        if (!mAllSleepTokens.isEmpty()) {
            mRootWindowContainer.mSleepTokens.removeAll(mAllSleepTokens);
Loading