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

Commit 119e2ff2 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "3/ Update OneHanded to use shell main thread"

parents d9e7d240 5b431851
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wm.shell.common;

import android.annotation.NonNull;
import android.os.Handler;
import android.os.Looper;

/** Executor implementation which is backed by a Handler. */
public class HandlerExecutor implements ShellExecutor {
@@ -49,4 +50,14 @@ public class HandlerExecutor implements ShellExecutor {
    public void removeCallbacks(@NonNull Runnable r) {
        mHandler.removeCallbacks(r);
    }

    @Override
    public boolean hasCallback(Runnable r) {
        return mHandler.hasCallbacks(r);
    }

    @Override
    public Looper getLooper() {
        return mHandler.getLooper();
    }
}
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.wm.shell.common;

import android.os.Looper;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -69,4 +71,14 @@ public interface ShellExecutor extends Executor {
     * See {@link android.os.Handler#removeCallbacks}.
     */
    void removeCallbacks(Runnable r);

    /**
     * See {@link android.os.Handler#hasCallbacks(Runnable)}.
     */
    boolean hasCallback(Runnable r);

    /**
     * Returns the looper that this executor is running on.
     */
    Looper getLooper();
}
+0 −6
Original line number Diff line number Diff line
@@ -127,7 +127,6 @@ public class OneHandedAnimationController {
                mSurfaceControlTransactionFactory;

        private @TransitionDirection int mTransitionDirection;
        private int mTransitionOffset;

        private OneHandedTransitionAnimator(SurfaceControl leash, T startValue, T endValue) {
            mLeash = leash;
@@ -231,11 +230,6 @@ public class OneHandedAnimationController {
            return this;
        }

        OneHandedTransitionAnimator<T> setTransitionOffset(int offset) {
            mTransitionOffset = offset;
            return this;
        }

        T getStartValue() {
            return mStartValue;
        }
+189 −118
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.content.om.OverlayInfo;
import android.database.ContentObserver;
import android.graphics.Point;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
@@ -41,8 +40,10 @@ import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayChangeController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.TaskStackListenerCallback;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;

import java.io.PrintWriter;
@@ -51,7 +52,7 @@ import java.util.concurrent.Executor;
/**
 * Manages and manipulates the one handed states, transitions, and gesture for phones.
 */
public class OneHandedController implements OneHanded {
public class OneHandedController {
    private static final String TAG = "OneHandedController";

    private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
@@ -61,8 +62,8 @@ public class OneHandedController implements OneHanded {

    static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";

    private boolean mIsOneHandedEnabled;
    private boolean mIsSwipeToNotificationEnabled;
    private volatile boolean mIsOneHandedEnabled;
    private volatile boolean mIsSwipeToNotificationEnabled;
    private boolean mTaskChangeToExit;
    private float mOffSetFraction;

@@ -73,7 +74,9 @@ public class OneHandedController implements OneHanded {
    private final OneHandedTouchHandler mTouchHandler;
    private final OneHandedTutorialHandler mTutorialHandler;
    private final IOverlayManager mOverlayManager;
    private final Handler mMainHandler = new Handler(Looper.getMainLooper());
    private final ShellExecutor mMainExecutor;
    private final Handler mMainHandler;
    private final OneHandedImpl mImpl = new OneHandedImpl();

    private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
    private final AccessibilityManager mAccessibilityManager;
@@ -89,83 +92,10 @@ public class OneHandedController implements OneHanded {
                }
            };

    private final ContentObserver mEnabledObserver = new ContentObserver(mMainHandler) {
        @Override
        public void onChange(boolean selfChange) {
            final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
                    mContext.getContentResolver());
            OneHandedEvents.writeEvent(enabled
                    ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
                    : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);

            setOneHandedEnabled(enabled);

            // Also checks swipe to notification settings since they all need gesture overlay.
            setEnabledGesturalOverlay(
                    enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
                            mContext.getContentResolver()));
        }
    };

    private final ContentObserver mTimeoutObserver = new ContentObserver(mMainHandler) {
        @Override
        public void onChange(boolean selfChange) {
            final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
                    mContext.getContentResolver());
            int metricsId = OneHandedEvents.OneHandedSettingsTogglesEvent.INVALID.getId();
            switch (newTimeout) {
                case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER:
                    metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_NEVER;
                    break;
                case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS:
                    metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_4;
                    break;
                case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS:
                    metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_8;
                    break;
                case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS:
                    metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_12;
                    break;
                default:
                    // do nothing
                    break;
            }
            OneHandedEvents.writeEvent(metricsId);

            if (mTimeoutHandler != null) {
                mTimeoutHandler.setTimeout(newTimeout);
            }
        }
    };

    private final ContentObserver mTaskChangeExitObserver = new ContentObserver(mMainHandler) {
        @Override
        public void onChange(boolean selfChange) {
            final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
                    mContext.getContentResolver());
            OneHandedEvents.writeEvent(enabled
                    ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
                    : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);

            setTaskChangeToExit(enabled);
        }
    };

    private final ContentObserver mSwipeToNotificationEnabledObserver =
            new ContentObserver(mMainHandler) {
                @Override
                public void onChange(boolean selfChange) {
                    final boolean enabled =
                            OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
                                    mContext.getContentResolver());
                    setSwipeToNotificationEnabled(enabled);

                    // Also checks one handed mode settings since they all need gesture overlay.
                    setEnabledGesturalOverlay(
                            enabled || OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
                                    mContext.getContentResolver()));
                }
            };
    private final ContentObserver mEnabledObserver;
    private final ContentObserver mTimeoutObserver;
    private final ContentObserver mTaskChangeExitObserver;
    private final ContentObserver mSwipeToNotificationEnabledObserver;

    private AccessibilityManager.AccessibilityStateChangeListener
            mAccessibilityStateChangeListener =
@@ -188,33 +118,39 @@ public class OneHandedController implements OneHanded {
            };

    /**
     * Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
     * Creates {@link OneHanded}, returns {@code null} if the feature is not supported.
     */
    @Nullable
    public static OneHandedController create(
    public static OneHanded create(
            Context context, DisplayController displayController,
            TaskStackListenerImpl taskStackListener, Executor executor) {
            TaskStackListenerImpl taskStackListener,
            ShellExecutor mainExecutor,
            Handler mainHandler) {
        if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
            Slog.w(TAG, "Device doesn't support OneHanded feature");
            return null;
        }

        OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context);
        OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
        OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context,
                mainExecutor);
        OneHandedAnimationController animationController =
                new OneHandedAnimationController(context);
        OneHandedTouchHandler touchHandler = new OneHandedTouchHandler();
        OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
                mainExecutor);
        OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
                context, displayController);
                context, displayController, mainExecutor);
        OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
                new OneHandedBackgroundPanelOrganizer(context, displayController, executor);
                new OneHandedBackgroundPanelOrganizer(context, displayController, mainExecutor);
        OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
                context, displayController, animationController, tutorialHandler, executor,
                oneHandedBackgroundPanelOrganizer);
                context, displayController, animationController, tutorialHandler,
                oneHandedBackgroundPanelOrganizer, mainExecutor);
        IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        return new OneHandedController(context, displayController,
                oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
                gestureHandler, overlayManager, taskStackListener);
                gestureHandler, timeoutHandler, overlayManager, taskStackListener, mainExecutor,
                mainHandler).mImpl;
    }

    @VisibleForTesting
@@ -225,8 +161,11 @@ public class OneHandedController implements OneHanded {
            OneHandedTouchHandler touchHandler,
            OneHandedTutorialHandler tutorialHandler,
            OneHandedGestureHandler gestureHandler,
            OneHandedTimeoutHandler timeoutHandler,
            IOverlayManager overlayManager,
            TaskStackListenerImpl taskStackListener) {
            TaskStackListenerImpl taskStackListener,
            ShellExecutor mainExecutor,
            Handler mainHandler) {
        mContext = context;
        mBackgroundPanelOrganizer = backgroundPanelOrganizer;
        mDisplayAreaOrganizer = displayAreaOrganizer;
@@ -235,6 +174,8 @@ public class OneHandedController implements OneHanded {
        mTutorialHandler = tutorialHandler;
        mGestureHandler = gestureHandler;
        mOverlayManager = overlayManager;
        mMainExecutor = mainExecutor;
        mMainHandler = mainHandler;

        final float offsetPercentageConfig = context.getResources().getFraction(
                R.fraction.config_one_handed_offset, 1, 1);
@@ -246,7 +187,13 @@ public class OneHandedController implements OneHanded {
        mIsSwipeToNotificationEnabled =
                OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
                        context.getContentResolver());
        mTimeoutHandler = OneHandedTimeoutHandler.get();
        mTimeoutHandler = timeoutHandler;

        mEnabledObserver = getObserver(this::onEnabledSettingChanged);
        mTimeoutObserver = getObserver(this::onTimeoutSettingChanged);
        mTaskChangeExitObserver = getObserver(this::onTaskChangeExitSettingChanged);
        mSwipeToNotificationEnabledObserver =
                getObserver(this::onSwipeToNotificationEnabledSettingChanged);

        mDisplayController.addDisplayChangingController(mRotationController);

@@ -298,18 +245,8 @@ public class OneHandedController implements OneHanded {
        updateOneHandedEnabled();
    }

    @Override
    public boolean isOneHandedEnabled() {
        return mIsOneHandedEnabled;
    }

    @Override
    public boolean isSwipeToNotificationEnabled() {
        return mIsSwipeToNotificationEnabled;
    }

    @Override
    public void startOneHanded() {
    @VisibleForTesting
    void startOneHanded() {
        if (!mDisplayAreaOrganizer.isInOneHanded()) {
            final int yOffSet = Math.round(getDisplaySize().y * mOffSetFraction);
            mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
@@ -319,16 +256,15 @@ public class OneHandedController implements OneHanded {
        }
    }

    @Override
    public void stopOneHanded() {
    @VisibleForTesting
    void stopOneHanded() {
        if (mDisplayAreaOrganizer.isInOneHanded()) {
            mDisplayAreaOrganizer.scheduleOffset(0, 0);
            mTimeoutHandler.removeTimer();
        }
    }

    @Override
    public void stopOneHanded(int event) {
    private void stopOneHanded(int event) {
        if (!mTaskChangeToExit && event == OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT) {
            //Task change exit not enable, do nothing and return here.
            return;
@@ -341,18 +277,16 @@ public class OneHandedController implements OneHanded {
        stopOneHanded();
    }

    @Override
    public void setThreeButtonModeEnabled(boolean enabled) {
    private void setThreeButtonModeEnabled(boolean enabled) {
        mGestureHandler.onThreeButtonModeEnabled(enabled);
    }

    @Override
    public void registerTransitionCallback(OneHandedTransitionCallback callback) {
    @VisibleForTesting
    void registerTransitionCallback(OneHandedTransitionCallback callback) {
        mDisplayAreaOrganizer.registerTransitionCallback(callback);
    }

    @Override
    public void registerGestureCallback(OneHandedGestureEventCallback callback) {
    private void registerGestureCallback(OneHandedGestureEventCallback callback) {
        mGestureHandler.setGestureEventListener(callback);
    }

@@ -388,6 +322,80 @@ public class OneHandedController implements OneHanded {
                .getSettingsSwipeToNotificationEnabled(mContext.getContentResolver()));
    }

    private ContentObserver getObserver(Runnable onChangeRunnable) {
        return new ContentObserver(mMainHandler) {
            @Override
            public void onChange(boolean selfChange) {
                onChangeRunnable.run();
            }
        };
    }

    private void onEnabledSettingChanged() {
        final boolean enabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
                mContext.getContentResolver());
        OneHandedEvents.writeEvent(enabled
                ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_ON
                : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);

        setOneHandedEnabled(enabled);

        // Also checks swipe to notification settings since they all need gesture overlay.
        setEnabledGesturalOverlay(
                enabled || OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
                        mContext.getContentResolver()));
    }

    private void onTimeoutSettingChanged() {
        final int newTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout(
                mContext.getContentResolver());
        int metricsId = OneHandedEvents.OneHandedSettingsTogglesEvent.INVALID.getId();
        switch (newTimeout) {
            case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER:
                metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_NEVER;
                break;
            case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS:
                metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_4;
                break;
            case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS:
                metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_8;
                break;
            case OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS:
                metricsId = OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_TIMEOUT_SECONDS_12;
                break;
            default:
                // do nothing
                break;
        }
        OneHandedEvents.writeEvent(metricsId);

        if (mTimeoutHandler != null) {
            mTimeoutHandler.setTimeout(newTimeout);
        }
    }

    private void onTaskChangeExitSettingChanged() {
        final boolean enabled = OneHandedSettingsUtil.getSettingsTapsAppToExit(
                mContext.getContentResolver());
        OneHandedEvents.writeEvent(enabled
                ? OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_ON
                : OneHandedEvents.EVENT_ONE_HANDED_SETTINGS_APP_TAPS_EXIT_OFF);

        setTaskChangeToExit(enabled);
    }

    private void onSwipeToNotificationEnabledSettingChanged() {
        final boolean enabled =
                OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
                        mContext.getContentResolver());
        setSwipeToNotificationEnabled(enabled);

        // Also checks one handed mode settings since they all need gesture overlay.
        setEnabledGesturalOverlay(
                enabled || OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
                        mContext.getContentResolver()));
    }

    private void setupTimeoutListener() {
        mTimeoutHandler.registerTimeoutListener(timeoutTime -> {
            stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_TIMEOUT_OUT);
@@ -451,8 +459,7 @@ public class OneHandedController implements OneHanded {
        }
    }

    @Override
    public void dump(@NonNull PrintWriter pw) {
    private void dump(@NonNull PrintWriter pw) {
        final String innerPrefix = "  ";
        pw.println(TAG + "states: ");
        pw.print(innerPrefix + "mOffSetFraction=");
@@ -489,4 +496,68 @@ public class OneHandedController implements OneHanded {
            }
        }
    }

    @ExternalThread
    private class OneHandedImpl implements OneHanded {
        @Override
        public boolean isOneHandedEnabled() {
            // This is volatile so return directly
            return mIsOneHandedEnabled;
        }

        @Override
        public boolean isSwipeToNotificationEnabled() {
            // This is volatile so return directly
            return mIsSwipeToNotificationEnabled;
        }

        @Override
        public void startOneHanded() {
            mMainExecutor.execute(() -> {
                OneHandedController.this.startOneHanded();
            });
        }

        @Override
        public void stopOneHanded() {
            mMainExecutor.execute(() -> {
                OneHandedController.this.stopOneHanded();
            });
        }

        @Override
        public void stopOneHanded(int event) {
            mMainExecutor.execute(() -> {
                OneHandedController.this.stopOneHanded(event);
            });
        }

        @Override
        public void setThreeButtonModeEnabled(boolean enabled) {
            mMainExecutor.execute(() -> {
                OneHandedController.this.setThreeButtonModeEnabled(enabled);
            });
        }

        @Override
        public void registerTransitionCallback(OneHandedTransitionCallback callback) {
            mMainExecutor.execute(() -> {
                OneHandedController.this.registerTransitionCallback(callback);
            });
        }

        @Override
        public void registerGestureCallback(OneHandedGestureEventCallback callback) {
            mMainExecutor.execute(() -> {
                OneHandedController.this.registerGestureCallback(callback);
            });
        }

        @Override
        public void dump(@NonNull PrintWriter pw) {
            mMainExecutor.execute(() -> {
                OneHandedController.this.dump(pw);
            });
        }
    }
}
+70 −147

File changed.

Preview size limit exceeded, changes collapsed.

Loading