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

Commit 70b5ca25 authored by Bill Lin's avatar Bill Lin
Browse files

Update state and touch region after one handed overlay changed

The matrix for overall modes x state changes:
-----------------------------------------------------
   Mode     |      State changed     | *Before|*After
-----------------------------------------------------
  OneHanded |  Portrait->Landscape   |  80dp  |  32dp
  OneHanded |  Landscape->Portrait   |  32dp  |  80dp
-----------------------------------------------------
  OneHanded |  Disable->Enable       |  32dp  |  32dp
 (Landscape)|  Enable->Disable       |  32dp  |  32dp
-----------------------------------------------------
  OneHanded |  Disable->Enable       |  32dp  |  80dp
 (Portrait) |  Enable->Disable       |  80dp  |  32dp
-----------------------------------------------------
  NO_BUTTON |  Portrait->Landscape   |  32dp  |  32dp
  NO_BUTTON |  Landscape->Portrait   |  32dp  |  32dp
  2 BUTTON  |  Portrait->Landscape   |  48dp  |  48dp
  2 BUTTON  |  Landscape->Portrait   |  48dp  |  48dp
  3 BUTTON  |  Portrait->Landscape   |  48dp  |  48dp
  3 BUTTON  |  Landscape->Portrait   |  48dp  |  48dp
-----------------------------------------------------
* dimen : navigation_bar_gesture_height

Test: adb bugrepot | grep mOneHandedModeRegion
Test: manually triger one handed
Test: atest WindowInsetsBehaviorTests
Test: atest com.android.launcher3.memory.MemoryTests
Test: flake -once
Test: rnlot -t com.android.launcher3.memory.MemoryTests
Bug: 157958539
Bug: 159183864
Change-Id: I19755938c3c93eb59a9f621af5722f5679c1da14
parent 95bb9f0f
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import androidx.annotation.WorkerThread;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher;
@@ -298,6 +299,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
        mAM = ActivityManagerWrapper.getInstance();
        mDeviceState = new RecentsAnimationDeviceState(this);
        mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
        mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
        mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
        ProtoTracer.INSTANCE.get(this).add(this);

@@ -338,6 +340,13 @@ public class TouchInteractionService extends Service implements PluginListener<O
        resetHomeBounceSeenOnQuickstepEnabledFirstTime();
    }

    /**
     * Called when the one handed mode overlay package changes, to recreate touch region.
     */
    private void onOneHandedModeOverlayChanged(int newGesturalHeight) {
        initInputMonitor();
    }

    @UiThread
    public void onUserUnlocked() {
        mTaskAnimationManager = new TaskAnimationManager();
@@ -813,6 +822,13 @@ public class TouchInteractionService extends Service implements PluginListener<O
        }
        if (mOverviewComponentObserver.canHandleConfigChanges(activity.getComponentName(),
                activity.getResources().getConfiguration().diff(newConfig))) {
            // Since navBar gestural height are different between portrait and landscape,
            // can handle orientation changes and refresh navigation gestural region through
            // onOneHandedModeChanged()
            int newGesturalHeight = ResourceUtils.getNavbarSize(
                    ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
                    getApplicationContext().getResources());
            mDeviceState.onOneHandedModeChanged(newGesturalHeight);
            return;
        }

+23 −6
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ class OrientationTouchTransformer {
    private final RectF mAssistantRightRegion = new RectF();
    private final RectF mOneHandedModeRegion = new RectF();
    private int mCurrentDisplayRotation;
    private int mNavBarGesturalHeight;
    private boolean mEnableMultipleRegions;
    private Resources mResources;
    private OrientationRectF mLastRectTouched;
@@ -104,20 +105,35 @@ class OrientationTouchTransformer {
        mResources = resources;
        mMode = mode;
        mContractInfo = contractInfo;
        mNavBarGesturalHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
    }

    void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info) {
        if (mMode == newMode) {
            return;
        }
        this.mMode = newMode;
    private void refreshTouchRegion(DefaultDisplay.Info info, Resources newRes) {
        // Swipe touch regions are independent of nav mode, so we have to clear them explicitly
        // here to avoid, for ex, a nav region for 2-button rotation 0 being used for 3-button mode
        // It tries to cache and reuse swipe regions whenever possible based only on rotation
        mResources = newRes;
        mSwipeTouchRegions.clear();
        resetSwipeRegions(info);
    }

    void setNavigationMode(SysUINavigationMode.Mode newMode, DefaultDisplay.Info info,
            Resources newRes) {
        if (mMode == newMode) {
            return;
        }
        this.mMode = newMode;
        refreshTouchRegion(info, newRes);
    }

    void setGesturalHeight(int newGesturalHeight, DefaultDisplay.Info info, Resources newRes) {
        if (mNavBarGesturalHeight == newGesturalHeight) {
            return;
        }
        mNavBarGesturalHeight = newGesturalHeight;
        refreshTouchRegion(info, newRes);
    }

    /**
     * Sets the current nav bar region to listen to events for as determined by
     * {@param info}. If multiple nav bar regions are enabled, then this region will be added
@@ -197,7 +213,7 @@ class OrientationTouchTransformer {

        Point size = display.realSize;
        int rotation = display.rotation;
        int touchHeight = getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE);
        int touchHeight = mNavBarGesturalHeight;
        OrientationRectF orientationRectF =
                new OrientationRectF(0, 0, size.x, size.y, rotation);
        if (mMode == SysUINavigationMode.Mode.NO_BUTTON) {
@@ -338,6 +354,7 @@ class OrientationTouchTransformer {
            regions.append(rectF.mRotation).append(" ");
        }
        pw.println(regions.toString());
        pw.println("  mNavBarGesturalHeight=" + mNavBarGesturalHeight);
        pw.println("  mOneHandedModeRegion=" + mOneHandedModeRegion);
    }

+21 −3
Original line number Diff line number Diff line
@@ -52,8 +52,8 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.OrientationEventListener;
import android.view.Surface;

import androidx.annotation.BinderThread;

@@ -63,6 +63,7 @@ import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DefaultDisplay;
import com.android.launcher3.util.SecureSettingsObserver;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.SysUINavigationMode.OneHandedModeChangeListener;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -81,7 +82,8 @@ import java.util.stream.Collectors;
 */
public class RecentsAnimationDeviceState implements
        NavigationModeChangeListener,
        DefaultDisplay.DisplayInfoChangeListener {
        DefaultDisplay.DisplayInfoChangeListener,
        OneHandedModeChangeListener {

    private final Context mContext;
    private final SysUINavigationMode mSysUiNavMode;
@@ -310,6 +312,15 @@ public class RecentsAnimationDeviceState implements
        runOnDestroy(() -> mSysUiNavMode.removeModeChangeListener(listener));
    }

    /**
     * Adds a listener for the one handed mode change,
     * guaranteed to be called after the device state's mode has changed.
     */
    public void addOneHandedModeChangedCallback(OneHandedModeChangeListener listener) {
        listener.onOneHandedModeChanged(mSysUiNavMode.addOneHandedOverlayChangeListener(listener));
        runOnDestroy(() -> mSysUiNavMode.removeOneHandedOverlayChangeListener(listener));
    }

    @Override
    public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
        mDefaultDisplay.removeChangeListener(this);
@@ -324,7 +335,8 @@ public class RecentsAnimationDeviceState implements

        mNavBarPosition = new NavBarPosition(newMode, mDefaultDisplay.getInfo());

        mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo());
        mOrientationTouchTransformer.setNavigationMode(newMode, mDefaultDisplay.getInfo(),
                mContext.getApplicationContext().getResources());
        if (!mMode.hasGestures && newMode.hasGestures) {
            setupOrientationSwipeHandler();
        } else if (mMode.hasGestures && !newMode.hasGestures){
@@ -363,6 +375,12 @@ public class RecentsAnimationDeviceState implements
        }
    }

    @Override
    public void onOneHandedModeChanged(int newGesturalHeight) {
        mOrientationTouchTransformer.setGesturalHeight(newGesturalHeight, mDefaultDisplay.getInfo(),
                mContext.getApplicationContext().getResources());
    }

    /**
     * @return the current navigation mode for the device.
     */
+57 −16
Original line number Diff line number Diff line
@@ -16,14 +16,15 @@

package com.android.quickstep;

import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.util.Log;

import com.android.launcher3.ResourceUtils;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.MainThreadInitializedObject;

@@ -58,15 +59,19 @@ public class SysUINavigationMode {
            new MainThreadInitializedObject<>(SysUINavigationMode::new);

    private static final String TAG = "SysUINavigationMode";

    private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
    private static final String NAV_BAR_INTERACTION_MODE_RES_NAME =
            "config_navBarInteractionMode";
    private static final String TARGET_OVERLAY_PACKAGE = "android";

    private final Context mContext;
    private Mode mMode;

    private int mNavBarGesturalHeight;

    private final List<NavigationModeChangeListener> mChangeListeners = new ArrayList<>();
    private final List<OneHandedModeChangeListener> mOneHandedOverlayChangeListeners =
            new ArrayList<>();

    public SysUINavigationMode(Context context) {
        mContext = context;
@@ -76,8 +81,9 @@ public class SysUINavigationMode {
            @Override
            public void onReceive(Context context, Intent intent) {
                updateMode();
                updateGesturalHeight();
            }
        }, getPackageFilter("android", ACTION_OVERLAY_CHANGED));
        }, getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED));
    }

    /** Updates navigation mode when needed. */
@@ -89,8 +95,34 @@ public class SysUINavigationMode {
        }
    }

    private void updateGesturalHeight() {
        int newGesturalHeight = ResourceUtils.getDimenByName(
                ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources(),
                INVALID_RESOURCE_HANDLE);

        if (newGesturalHeight == INVALID_RESOURCE_HANDLE) {
            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
            return;
        }

        if (mNavBarGesturalHeight != newGesturalHeight) {
            mNavBarGesturalHeight = newGesturalHeight;
            dispatchOneHandedOverlayChange();
        }
    }

    private void initializeMode() {
        int modeInt = getSystemIntegerRes(mContext, NAV_BAR_INTERACTION_MODE_RES_NAME);
        int modeInt = ResourceUtils.getIntegerByName(NAV_BAR_INTERACTION_MODE_RES_NAME,
                mContext.getResources(), INVALID_RESOURCE_HANDLE);
        mNavBarGesturalHeight = ResourceUtils.getDimenByName(
                ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, mContext.getResources(),
                INVALID_RESOURCE_HANDLE);

        if (modeInt == INVALID_RESOURCE_HANDLE) {
            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
            return;
        }

        for (Mode m : Mode.values()) {
            if (m.resValue == modeInt) {
                mMode = m;
@@ -104,6 +136,12 @@ public class SysUINavigationMode {
        }
    }

    private void dispatchOneHandedOverlayChange() {
        for (OneHandedModeChangeListener listener : mOneHandedOverlayChangeListeners) {
            listener.onOneHandedModeChanged(mNavBarGesturalHeight);
        }
    }

    public Mode addModeChangeListener(NavigationModeChangeListener listener) {
        mChangeListeners.add(listener);
        return mMode;
@@ -113,20 +151,17 @@ public class SysUINavigationMode {
        mChangeListeners.remove(listener);
    }

    public Mode getMode() {
        return mMode;
    public int addOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
        mOneHandedOverlayChangeListeners.add(listener);
        return mNavBarGesturalHeight;
    }

    private static int getSystemIntegerRes(Context context, String resName) {
        Resources res = context.getResources();
        int resId = res.getIdentifier(resName, "integer", "android");

        if (resId != 0) {
            return res.getInteger(resId);
        } else {
            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
            return -1;
    public void removeOneHandedOverlayChangeListener(OneHandedModeChangeListener listener) {
        mOneHandedOverlayChangeListeners.remove(listener);
    }

    public Mode getMode() {
        return mMode;
    }

    /** @return Whether we can remove the shelf from overview. */
@@ -144,10 +179,16 @@ public class SysUINavigationMode {
    public void dump(PrintWriter pw) {
        pw.println("SysUINavigationMode:");
        pw.println("  mode=" + mMode.name());
        pw.println("  mNavBarGesturalHeight=:" + mNavBarGesturalHeight);
    }

    public interface NavigationModeChangeListener {

        void onNavigationModeChanged(Mode newMode);
    }

    public interface OneHandedModeChangeListener {

        void onOneHandedModeChanged(int newGesturalHeight);
    }
}
 No newline at end of file
+8 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.util.TypedValue;

public class ResourceUtils {
    public static final int DEFAULT_NAVBAR_VALUE = 48;
    public static final int INVALID_RESOURCE_HANDLE = -1;
    public static final String NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE = "navigation_bar_width";
    public static final String NAVBAR_BOTTOM_GESTURE_SIZE = "navigation_bar_gesture_height";

@@ -51,7 +52,13 @@ public class ResourceUtils {
        return val;
    }

    public static int getIntegerByName(String resName, Resources res, int defaultValue) {
        int resId = res.getIdentifier(resName, "integer", "android");
        return resId != 0 ? res.getInteger(resId) : defaultValue;
    }

    public static int pxFromDp(float size, DisplayMetrics metrics) {
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, metrics));
        return size < 0 ? INVALID_RESOURCE_HANDLE : Math.round(
                TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, metrics));
    }
}