Merge "3/ Update OneHanded to use shell main thread"
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,6 @@ import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSI
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
@@ -39,9 +37,9 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -64,17 +62,9 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
private static final String ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION =
|
||||
"persist.debug.one_handed_translate_animation_duration";
|
||||
|
||||
@VisibleForTesting
|
||||
static final int MSG_RESET_IMMEDIATE = 1;
|
||||
@VisibleForTesting
|
||||
static final int MSG_OFFSET_ANIMATE = 2;
|
||||
@VisibleForTesting
|
||||
static final int MSG_OFFSET_FINISH = 3;
|
||||
|
||||
private final Rect mLastVisualDisplayBounds = new Rect();
|
||||
private final Rect mDefaultDisplayBounds = new Rect();
|
||||
|
||||
private Handler mUpdateHandler;
|
||||
private boolean mIsInOneHanded;
|
||||
private int mEnterExitAnimationDurationMs;
|
||||
|
||||
@@ -101,8 +91,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
OneHandedAnimationController.OneHandedTransitionAnimator animator) {
|
||||
mAnimationController.removeAnimator(animator.getLeash());
|
||||
if (mAnimationController.isAnimatorsConsumed()) {
|
||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_OFFSET_FINISH,
|
||||
obtainArgsFromAnimator(animator)));
|
||||
finishOffset(animator.getDestinationOffset(),
|
||||
animator.getTransitionDirection());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,52 +101,22 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
OneHandedAnimationController.OneHandedTransitionAnimator animator) {
|
||||
mAnimationController.removeAnimator(animator.getLeash());
|
||||
if (mAnimationController.isAnimatorsConsumed()) {
|
||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_OFFSET_FINISH,
|
||||
obtainArgsFromAnimator(animator)));
|
||||
finishOffset(animator.getDestinationOffset(),
|
||||
animator.getTransitionDirection());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Handler.Callback mUpdateCallback = (msg) -> {
|
||||
SomeArgs args = (SomeArgs) msg.obj;
|
||||
final Rect currentBounds = args.arg1 != null ? (Rect) args.arg1 : mDefaultDisplayBounds;
|
||||
final WindowContainerTransaction wctFromRotate = (WindowContainerTransaction) args.arg2;
|
||||
final int yOffset = args.argi2;
|
||||
final int direction = args.argi3;
|
||||
|
||||
switch (msg.what) {
|
||||
case MSG_RESET_IMMEDIATE:
|
||||
resetWindowsOffset(wctFromRotate);
|
||||
mDefaultDisplayBounds.set(currentBounds);
|
||||
mLastVisualDisplayBounds.set(currentBounds);
|
||||
finishOffset(0, TRANSITION_DIRECTION_EXIT);
|
||||
break;
|
||||
case MSG_OFFSET_ANIMATE:
|
||||
final Rect toBounds = new Rect(mDefaultDisplayBounds.left,
|
||||
mDefaultDisplayBounds.top + yOffset,
|
||||
mDefaultDisplayBounds.right,
|
||||
mDefaultDisplayBounds.bottom + yOffset);
|
||||
offsetWindows(currentBounds, toBounds, direction, mEnterExitAnimationDurationMs);
|
||||
break;
|
||||
case MSG_OFFSET_FINISH:
|
||||
finishOffset(yOffset, direction);
|
||||
break;
|
||||
}
|
||||
args.recycle();
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor of OneHandedDisplayAreaOrganizer
|
||||
*/
|
||||
public OneHandedDisplayAreaOrganizer(Context context,
|
||||
DisplayController displayController,
|
||||
OneHandedAnimationController animationController,
|
||||
OneHandedTutorialHandler tutorialHandler, Executor executor,
|
||||
OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer) {
|
||||
super(executor);
|
||||
mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback);
|
||||
OneHandedTutorialHandler tutorialHandler,
|
||||
OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer,
|
||||
ShellExecutor mainExecutor) {
|
||||
super(mainExecutor);
|
||||
mAnimationController = animationController;
|
||||
mDisplayController = displayController;
|
||||
mDefaultDisplayBounds.set(getDisplayBounds());
|
||||
@@ -176,12 +136,10 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
@NonNull SurfaceControl leash) {
|
||||
Objects.requireNonNull(displayAreaInfo, "displayAreaInfo must not be null");
|
||||
Objects.requireNonNull(leash, "leash must not be null");
|
||||
synchronized (this) {
|
||||
if (mDisplayAreaMap.get(displayAreaInfo) == null) {
|
||||
// mDefaultDisplayBounds may out of date after removeDisplayChangingController()
|
||||
mDefaultDisplayBounds.set(getDisplayBounds());
|
||||
mDisplayAreaMap.put(displayAreaInfo, leash);
|
||||
}
|
||||
if (mDisplayAreaMap.get(displayAreaInfo) == null) {
|
||||
// mDefaultDisplayBounds may out of date after removeDisplayChangingController()
|
||||
mDefaultDisplayBounds.set(getDisplayBounds());
|
||||
mDisplayAreaMap.put(displayAreaInfo, leash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,13 +147,11 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
|
||||
Objects.requireNonNull(displayAreaInfo,
|
||||
"Requires valid displayArea, and displayArea must not be null");
|
||||
synchronized (this) {
|
||||
if (!mDisplayAreaMap.containsKey(displayAreaInfo)) {
|
||||
Log.w(TAG, "Unrecognized token: " + displayAreaInfo.token);
|
||||
return;
|
||||
}
|
||||
mDisplayAreaMap.remove(displayAreaInfo);
|
||||
if (!mDisplayAreaMap.containsKey(displayAreaInfo)) {
|
||||
Log.w(TAG, "Unrecognized token: " + displayAreaInfo.token);
|
||||
return;
|
||||
}
|
||||
mDisplayAreaMap.remove(displayAreaInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,7 +168,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
@Override
|
||||
public void unregisterOrganizer() {
|
||||
super.unregisterOrganizer();
|
||||
mUpdateHandler.post(() -> resetWindowsOffset(null));
|
||||
resetWindowsOffset(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,14 +186,10 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
final boolean isOrientationDiff = Math.abs(fromRotation - toRotation) % 2 == 1;
|
||||
|
||||
if (isOrientationDiff) {
|
||||
newBounds.set(newBounds.left, newBounds.top, newBounds.bottom, newBounds.right);
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = newBounds;
|
||||
args.arg2 = wct;
|
||||
args.argi1 = 0 /* xOffset */;
|
||||
args.argi2 = 0 /* yOffset */;
|
||||
args.argi3 = TRANSITION_DIRECTION_EXIT;
|
||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESET_IMMEDIATE, args));
|
||||
resetWindowsOffset(wct);
|
||||
mDefaultDisplayBounds.set(newBounds);
|
||||
mLastVisualDisplayBounds.set(newBounds);
|
||||
finishOffset(0, TRANSITION_DIRECTION_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,79 +198,65 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
* Directly perform manipulation/offset on the leash.
|
||||
*/
|
||||
public void scheduleOffset(int xOffset, int yOffset) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = getLastVisualDisplayBounds();
|
||||
args.argi1 = xOffset;
|
||||
args.argi2 = yOffset;
|
||||
args.argi3 = yOffset > 0 ? TRANSITION_DIRECTION_TRIGGER : TRANSITION_DIRECTION_EXIT;
|
||||
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_OFFSET_ANIMATE, args));
|
||||
}
|
||||
final Rect toBounds = new Rect(mDefaultDisplayBounds.left,
|
||||
mDefaultDisplayBounds.top + yOffset,
|
||||
mDefaultDisplayBounds.right,
|
||||
mDefaultDisplayBounds.bottom + yOffset);
|
||||
final Rect fromBounds = getLastVisualDisplayBounds() != null
|
||||
? getLastVisualDisplayBounds()
|
||||
: mDefaultDisplayBounds;
|
||||
final int direction = yOffset > 0
|
||||
? TRANSITION_DIRECTION_TRIGGER
|
||||
: TRANSITION_DIRECTION_EXIT;
|
||||
|
||||
private void offsetWindows(Rect fromBounds, Rect toBounds, int direction, int durationMs) {
|
||||
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
||||
throw new RuntimeException("Callers should call scheduleOffset() instead of this "
|
||||
+ "directly");
|
||||
}
|
||||
synchronized (this) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mDisplayAreaMap.forEach(
|
||||
(key, leash) -> {
|
||||
animateWindows(leash, fromBounds, toBounds, direction, durationMs);
|
||||
wct.setBounds(key.token, toBounds);
|
||||
});
|
||||
applyTransaction(wct);
|
||||
}
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mDisplayAreaMap.forEach(
|
||||
(key, leash) -> {
|
||||
animateWindows(leash, fromBounds, toBounds, direction,
|
||||
mEnterExitAnimationDurationMs);
|
||||
wct.setBounds(key.token, toBounds);
|
||||
});
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
private void resetWindowsOffset(WindowContainerTransaction wct) {
|
||||
synchronized (this) {
|
||||
final SurfaceControl.Transaction tx =
|
||||
mSurfaceControlTransactionFactory.getTransaction();
|
||||
mDisplayAreaMap.forEach(
|
||||
(key, leash) -> {
|
||||
final OneHandedAnimationController.OneHandedTransitionAnimator animator =
|
||||
mAnimationController.getAnimatorMap().remove(leash);
|
||||
if (animator != null && animator.isRunning()) {
|
||||
animator.cancel();
|
||||
}
|
||||
tx.setPosition(leash, 0, 0)
|
||||
.setWindowCrop(leash, -1/* reset */, -1/* reset */);
|
||||
// DisplayRotationController will applyTransaction() after finish rotating
|
||||
if (wct != null) {
|
||||
wct.setBounds(key.token, null/* reset */);
|
||||
}
|
||||
});
|
||||
tx.apply();
|
||||
}
|
||||
final SurfaceControl.Transaction tx =
|
||||
mSurfaceControlTransactionFactory.getTransaction();
|
||||
mDisplayAreaMap.forEach(
|
||||
(key, leash) -> {
|
||||
final OneHandedAnimationController.OneHandedTransitionAnimator animator =
|
||||
mAnimationController.getAnimatorMap().remove(leash);
|
||||
if (animator != null && animator.isRunning()) {
|
||||
animator.cancel();
|
||||
}
|
||||
tx.setPosition(leash, 0, 0)
|
||||
.setWindowCrop(leash, -1/* reset */, -1/* reset */);
|
||||
// DisplayRotationController will applyTransaction() after finish rotating
|
||||
if (wct != null) {
|
||||
wct.setBounds(key.token, null/* reset */);
|
||||
}
|
||||
});
|
||||
tx.apply();
|
||||
}
|
||||
|
||||
private void animateWindows(SurfaceControl leash, Rect fromBounds, Rect toBounds,
|
||||
@OneHandedAnimationController.TransitionDirection int direction, int durationMs) {
|
||||
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
||||
throw new RuntimeException("Callers should call scheduleOffset() instead of "
|
||||
+ "this directly");
|
||||
final OneHandedAnimationController.OneHandedTransitionAnimator animator =
|
||||
mAnimationController.getAnimator(leash, fromBounds, toBounds);
|
||||
if (animator != null) {
|
||||
animator.setTransitionDirection(direction)
|
||||
.addOneHandedAnimationCallback(mOneHandedAnimationCallback)
|
||||
.addOneHandedAnimationCallback(mTutorialHandler.getAnimationCallback())
|
||||
.addOneHandedAnimationCallback(
|
||||
mBackgroundPanelOrganizer.getOneHandedAnimationCallback())
|
||||
.setDuration(durationMs)
|
||||
.start();
|
||||
}
|
||||
mUpdateHandler.post(() -> {
|
||||
final OneHandedAnimationController.OneHandedTransitionAnimator animator =
|
||||
mAnimationController.getAnimator(leash, fromBounds, toBounds);
|
||||
if (animator != null) {
|
||||
animator.setTransitionDirection(direction)
|
||||
.addOneHandedAnimationCallback(mOneHandedAnimationCallback)
|
||||
.addOneHandedAnimationCallback(mTutorialHandler.getAnimationCallback())
|
||||
.addOneHandedAnimationCallback(
|
||||
mBackgroundPanelOrganizer.getOneHandedAnimationCallback())
|
||||
.setDuration(durationMs)
|
||||
.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void finishOffset(int offset,
|
||||
@VisibleForTesting
|
||||
void finishOffset(int offset,
|
||||
@OneHandedAnimationController.TransitionDirection int direction) {
|
||||
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
|
||||
throw new RuntimeException(
|
||||
"Callers should call scheduleOffset() instead of this directly.");
|
||||
}
|
||||
// Only finishOffset() can update mIsInOneHanded to ensure the state is handle in sequence,
|
||||
// the flag *MUST* be updated before dispatch mTransitionCallbacks
|
||||
mIsInOneHanded = (offset > 0 || direction == TRANSITION_DIRECTION_TRIGGER);
|
||||
@@ -361,11 +299,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
return new Rect(0, 0, realSize.x, realSize.y);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setUpdateHandler(Handler updateHandler) {
|
||||
mUpdateHandler = updateHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register transition callback
|
||||
*/
|
||||
@@ -373,16 +306,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
mTransitionCallbacks.add(callback);
|
||||
}
|
||||
|
||||
private SomeArgs obtainArgsFromAnimator(
|
||||
OneHandedAnimationController.OneHandedTransitionAnimator animator) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = animator.getDestinationBounds();
|
||||
args.argi1 = 0 /* xOffset */;
|
||||
args.argi2 = animator.getDestinationOffset();
|
||||
args.argi3 = animator.getTransitionDirection();
|
||||
return args;
|
||||
}
|
||||
|
||||
void dump(@NonNull PrintWriter pw) {
|
||||
final String innerPrefix = " ";
|
||||
pw.println(TAG + "states: ");
|
||||
|
||||
@@ -41,6 +41,7 @@ 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;
|
||||
|
||||
/**
|
||||
* The class manage swipe up and down gesture for 3-Button mode navigation,
|
||||
@@ -70,7 +71,8 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
|
||||
InputMonitor mInputMonitor;
|
||||
@VisibleForTesting
|
||||
InputEventReceiver mInputEventReceiver;
|
||||
private DisplayController mDisplayController;
|
||||
private final DisplayController mDisplayController;
|
||||
private final ShellExecutor mMainExecutor;
|
||||
@VisibleForTesting
|
||||
@Nullable
|
||||
OneHandedGestureEventCallback mGestureEventCallback;
|
||||
@@ -84,8 +86,10 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
|
||||
* @param context {@link Context}
|
||||
* @param displayController {@link DisplayController}
|
||||
*/
|
||||
public OneHandedGestureHandler(Context context, DisplayController displayController) {
|
||||
public OneHandedGestureHandler(Context context, DisplayController displayController,
|
||||
ShellExecutor mainExecutor) {
|
||||
mDisplayController = displayController;
|
||||
mMainExecutor = mainExecutor;
|
||||
displayController.addDisplayChangingController(this);
|
||||
mNavGestureHeight = context.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.navigation_bar_gesture_larger_height);
|
||||
@@ -93,6 +97,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
|
||||
R.dimen.gestures_onehanded_drag_threshold);
|
||||
final float slop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
mSquaredSlop = slop * slop;
|
||||
|
||||
updateIsEnabled();
|
||||
}
|
||||
|
||||
@@ -217,7 +222,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
|
||||
mInputMonitor = InputManager.getInstance().monitorGestureInput(
|
||||
"onehanded-gesture-offset", DEFAULT_DISPLAY);
|
||||
mInputEventReceiver = new EventReceiver(
|
||||
mInputMonitor.getInputChannel(), Looper.getMainLooper());
|
||||
mInputMonitor.getInputChannel(), mMainExecutor.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,6 +238,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
|
||||
mRotation = toRotation;
|
||||
}
|
||||
|
||||
// TODO: Use BatchedInputEventReceiver
|
||||
private class EventReceiver extends InputEventReceiver {
|
||||
EventReceiver(InputChannel channel, Looper looper) {
|
||||
super(channel, looper);
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.wm.shell.onehanded;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
|
||||
/**
|
||||
* Similar to {@link com.android.internal.os.BackgroundThread}, this is a shared singleton
|
||||
* foreground thread for each process for updating one handed.
|
||||
*/
|
||||
public class OneHandedThread extends HandlerThread {
|
||||
private static OneHandedThread sInstance;
|
||||
private static Handler sHandler;
|
||||
|
||||
private OneHandedThread() {
|
||||
super("OneHanded");
|
||||
}
|
||||
|
||||
private static void ensureThreadLocked() {
|
||||
if (sInstance == null) {
|
||||
sInstance = new OneHandedThread();
|
||||
sInstance.start();
|
||||
sHandler = new Handler(sInstance.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the static update thread instance
|
||||
*/
|
||||
public static OneHandedThread get() {
|
||||
synchronized (OneHandedThread.class) {
|
||||
ensureThreadLocked();
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the static update thread handler instance
|
||||
*/
|
||||
public static Handler getHandler() {
|
||||
synchronized (OneHandedThread.class) {
|
||||
ensureThreadLocked();
|
||||
return sHandler;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,12 +19,12 @@ package com.android.wm.shell.onehanded;
|
||||
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -35,18 +35,15 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class OneHandedTimeoutHandler {
|
||||
private static final String TAG = "OneHandedTimeoutHandler";
|
||||
private static boolean sIsDragging = false;
|
||||
// Default timeout is ONE_HANDED_TIMEOUT_MEDIUM
|
||||
private static @OneHandedSettingsUtil.OneHandedTimeout int sTimeout =
|
||||
ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
|
||||
private static long sTimeoutMs = TimeUnit.SECONDS.toMillis(sTimeout);
|
||||
private static OneHandedTimeoutHandler sInstance;
|
||||
private static List<TimeoutListener> sListeners = new ArrayList<>();
|
||||
|
||||
@VisibleForTesting
|
||||
static final int ONE_HANDED_TIMEOUT_STOP_MSG = 1;
|
||||
@VisibleForTesting
|
||||
static Handler sHandler;
|
||||
private final ShellExecutor mMainExecutor;
|
||||
|
||||
// Default timeout is ONE_HANDED_TIMEOUT_MEDIUM
|
||||
private @OneHandedSettingsUtil.OneHandedTimeout int mTimeout =
|
||||
ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
|
||||
private long mTimeoutMs = TimeUnit.SECONDS.toMillis(mTimeout);
|
||||
private final Runnable mTimeoutRunnable = this::onStop;
|
||||
private List<TimeoutListener> mListeners = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Get the current config of timeout
|
||||
@@ -54,7 +51,7 @@ public class OneHandedTimeoutHandler {
|
||||
* @return timeout of current config
|
||||
*/
|
||||
public @OneHandedSettingsUtil.OneHandedTimeout int getTimeout() {
|
||||
return sTimeout;
|
||||
return mTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,32 +66,36 @@ public class OneHandedTimeoutHandler {
|
||||
void onTimeout(int timeoutTime);
|
||||
}
|
||||
|
||||
public OneHandedTimeoutHandler(ShellExecutor mainExecutor) {
|
||||
mMainExecutor = mainExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specific timeout of {@link OneHandedSettingsUtil.OneHandedTimeout}
|
||||
*/
|
||||
public static void setTimeout(@OneHandedSettingsUtil.OneHandedTimeout int timeout) {
|
||||
sTimeout = timeout;
|
||||
sTimeoutMs = TimeUnit.SECONDS.toMillis(sTimeout);
|
||||
public void setTimeout(@OneHandedSettingsUtil.OneHandedTimeout int timeout) {
|
||||
mTimeout = timeout;
|
||||
mTimeoutMs = TimeUnit.SECONDS.toMillis(mTimeout);
|
||||
resetTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the timer when one handed trigger or user is operating in some conditions
|
||||
*/
|
||||
public static void removeTimer() {
|
||||
sHandler.removeMessages(ONE_HANDED_TIMEOUT_STOP_MSG);
|
||||
public void removeTimer() {
|
||||
mMainExecutor.removeCallbacks(mTimeoutRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the timer when one handed trigger or user is operating in some conditions
|
||||
*/
|
||||
public static void resetTimer() {
|
||||
public void resetTimer() {
|
||||
removeTimer();
|
||||
if (sTimeout == OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER) {
|
||||
if (mTimeout == OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER) {
|
||||
return;
|
||||
}
|
||||
if (sTimeout != OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER) {
|
||||
sHandler.sendEmptyMessageDelayed(ONE_HANDED_TIMEOUT_STOP_MSG, sTimeoutMs);
|
||||
if (mTimeout != OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER) {
|
||||
mMainExecutor.executeDelayed(mTimeoutRunnable, mTimeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,47 +104,19 @@ public class OneHandedTimeoutHandler {
|
||||
*
|
||||
* @param listener the listener be sent events when times up
|
||||
*/
|
||||
public static void registerTimeoutListener(TimeoutListener listener) {
|
||||
sListeners.add(listener);
|
||||
public void registerTimeoutListener(TimeoutListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor due to Singleton pattern
|
||||
*/
|
||||
private OneHandedTimeoutHandler() {
|
||||
@VisibleForTesting
|
||||
boolean hasScheduledTimeout() {
|
||||
return mMainExecutor.hasCallback(mTimeoutRunnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton pattern to get {@link OneHandedTimeoutHandler} instance
|
||||
*
|
||||
* @return the static update thread instance
|
||||
*/
|
||||
public static OneHandedTimeoutHandler get() {
|
||||
synchronized (OneHandedTimeoutHandler.class) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new OneHandedTimeoutHandler();
|
||||
}
|
||||
if (sHandler == null) {
|
||||
sHandler = new Handler(Looper.myLooper()) {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == ONE_HANDED_TIMEOUT_STOP_MSG) {
|
||||
onStop();
|
||||
}
|
||||
}
|
||||
};
|
||||
if (sTimeout != OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER) {
|
||||
sHandler.sendEmptyMessageDelayed(ONE_HANDED_TIMEOUT_STOP_MSG, sTimeoutMs);
|
||||
}
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void onStop() {
|
||||
for (int i = sListeners.size() - 1; i >= 0; i--) {
|
||||
final TimeoutListener listener = sListeners.get(i);
|
||||
listener.onTimeout(sTimeout);
|
||||
private void onStop() {
|
||||
for (int i = mListeners.size() - 1; i >= 0; i--) {
|
||||
final TimeoutListener listener = mListeners.get(i);
|
||||
listener.onTimeout(mTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +124,9 @@ public class OneHandedTimeoutHandler {
|
||||
final String innerPrefix = " ";
|
||||
pw.println(TAG + "states: ");
|
||||
pw.print(innerPrefix + "sTimeout=");
|
||||
pw.println(sTimeout);
|
||||
pw.println(mTimeout);
|
||||
pw.print(innerPrefix + "sListeners=");
|
||||
pw.println(sListeners);
|
||||
pw.println(mListeners);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import android.view.MotionEvent;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
@@ -41,7 +43,8 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback {
|
||||
private static final String TAG = "OneHandedTouchHandler";
|
||||
private final Rect mLastUpdatedBounds = new Rect();
|
||||
|
||||
private OneHandedTimeoutHandler mTimeoutHandler;
|
||||
private final OneHandedTimeoutHandler mTimeoutHandler;
|
||||
private final ShellExecutor mMainExecutor;
|
||||
|
||||
@VisibleForTesting
|
||||
InputMonitor mInputMonitor;
|
||||
@@ -54,8 +57,10 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback {
|
||||
private boolean mIsOnStopTransitioning;
|
||||
private boolean mIsInOutsideRegion;
|
||||
|
||||
public OneHandedTouchHandler() {
|
||||
mTimeoutHandler = OneHandedTimeoutHandler.get();
|
||||
public OneHandedTouchHandler(OneHandedTimeoutHandler timeoutHandler,
|
||||
ShellExecutor mainExecutor) {
|
||||
mTimeoutHandler = timeoutHandler;
|
||||
mMainExecutor = mainExecutor;
|
||||
updateIsEnabled();
|
||||
}
|
||||
|
||||
@@ -128,7 +133,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback {
|
||||
mInputMonitor = InputManager.getInstance().monitorGestureInput(
|
||||
"onehanded-touch", DEFAULT_DISPLAY);
|
||||
mInputEventReceiver = new EventReceiver(
|
||||
mInputMonitor.getInputChannel(), Looper.getMainLooper());
|
||||
mInputMonitor.getInputChannel(), mMainExecutor.getLooper());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +155,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback {
|
||||
pw.println(mLastUpdatedBounds);
|
||||
}
|
||||
|
||||
// TODO: Use BatchedInputEventReceiver
|
||||
private class EventReceiver extends InputEventReceiver {
|
||||
EventReceiver(InputChannel channel, Looper looper) {
|
||||
super(channel, looper);
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
import android.view.Gravity;
|
||||
@@ -36,6 +35,7 @@ import android.widget.FrameLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -57,7 +57,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
|
||||
|
||||
private View mTutorialView;
|
||||
private Point mDisplaySize = new Point();
|
||||
private Handler mUpdateHandler;
|
||||
private ContentResolver mContentResolver;
|
||||
private boolean mCanShowTutorial;
|
||||
private String mStartOneHandedDescription;
|
||||
@@ -82,69 +81,67 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback {
|
||||
private final OneHandedAnimationCallback mAnimationCallback = new OneHandedAnimationCallback() {
|
||||
@Override
|
||||
public void onTutorialAnimationUpdate(int offset) {
|
||||
mUpdateHandler.post(() -> onAnimationUpdate(offset));
|
||||
onAnimationUpdate(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOneHandedAnimationStart(
|
||||
OneHandedAnimationController.OneHandedTransitionAnimator animator) {
|
||||
mUpdateHandler.post(() -> {
|
||||
final Rect startValue = (Rect) animator.getStartValue();
|
||||
if (mTriggerState == ONE_HANDED_TRIGGER_STATE.UNSET) {
|
||||
mTriggerState = (startValue.top == 0)
|
||||
? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING;
|
||||
if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) {
|
||||
createTutorialTarget();
|
||||
}
|
||||
final Rect startValue = (Rect) animator.getStartValue();
|
||||
if (mTriggerState == ONE_HANDED_TRIGGER_STATE.UNSET) {
|
||||
mTriggerState = (startValue.top == 0)
|
||||
? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING;
|
||||
if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) {
|
||||
createTutorialTarget();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public OneHandedTutorialHandler(Context context) {
|
||||
public OneHandedTutorialHandler(Context context, ShellExecutor mainExecutor) {
|
||||
context.getDisplay().getRealSize(mDisplaySize);
|
||||
mPackageName = context.getPackageName();
|
||||
mContentResolver = context.getContentResolver();
|
||||
mUpdateHandler = new Handler();
|
||||
mWindowManager = context.getSystemService(WindowManager.class);
|
||||
mAccessibilityManager = (AccessibilityManager)
|
||||
context.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||
mTargetViewContainer = new FrameLayout(context);
|
||||
mTargetViewContainer.setClipChildren(false);
|
||||
|
||||
mStartOneHandedDescription = context.getResources().getString(
|
||||
R.string.accessibility_action_start_one_handed);
|
||||
mStopOneHandedDescription = context.getResources().getString(
|
||||
R.string.accessibility_action_stop_one_handed);
|
||||
mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
|
||||
Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)
|
||||
? false : true;
|
||||
final float offsetPercentageConfig = context.getResources().getFraction(
|
||||
R.fraction.config_one_handed_offset, 1, 1);
|
||||
final int sysPropPercentageConfig = SystemProperties.getInt(
|
||||
ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
|
||||
mTutorialAreaHeight = Math.round(mDisplaySize.y * (sysPropPercentageConfig / 100.0f));
|
||||
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
|
||||
mTargetViewContainer.addView(mTutorialView);
|
||||
mCanShowTutorial = (Settings.Secure.getInt(mContentResolver,
|
||||
Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT)
|
||||
? false : true;
|
||||
mStartOneHandedDescription = context.getResources().getString(
|
||||
R.string.accessibility_action_start_one_handed);
|
||||
mStopOneHandedDescription = context.getResources().getString(
|
||||
R.string.accessibility_action_stop_one_handed);
|
||||
|
||||
mainExecutor.execute(() -> {
|
||||
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial,
|
||||
null);
|
||||
mTargetViewContainer = new FrameLayout(context);
|
||||
mTargetViewContainer.setClipChildren(false);
|
||||
mTargetViewContainer.addView(mTutorialView);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartFinished(Rect bounds) {
|
||||
mUpdateHandler.post(() -> {
|
||||
updateFinished(View.VISIBLE, 0f);
|
||||
updateTutorialCount();
|
||||
announcementForScreenReader(true);
|
||||
mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
|
||||
});
|
||||
updateFinished(View.VISIBLE, 0f);
|
||||
updateTutorialCount();
|
||||
announcementForScreenReader(true);
|
||||
mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopFinished(Rect bounds) {
|
||||
mUpdateHandler.post(() -> {
|
||||
updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight());
|
||||
announcementForScreenReader(false);
|
||||
removeTutorialFromWindowManager();
|
||||
mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
|
||||
});
|
||||
updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight());
|
||||
announcementForScreenReader(false);
|
||||
removeTutorialFromWindowManager();
|
||||
mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET;
|
||||
}
|
||||
|
||||
private void updateFinished(int visible, float finalPosition) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
private List<AccessibilityNodeInfo> mAccessibilityNodeInfoList;
|
||||
|
||||
private final Context mContext;
|
||||
private final ShellExecutor mShellMainExcutor;
|
||||
private final ShellExecutor mMainExcutor;
|
||||
private final @NonNull PipBoundsState mPipBoundsState;
|
||||
private final PipMotionHelper mMotionHelper;
|
||||
private final PipTaskOrganizer mTaskOrganizer;
|
||||
@@ -72,9 +72,9 @@ public class PipAccessibilityInteractionConnection {
|
||||
@NonNull PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
|
||||
PipTaskOrganizer taskOrganizer, PipSnapAlgorithm snapAlgorithm,
|
||||
AccessibilityCallbacks callbacks, Runnable updateMovementBoundCallback,
|
||||
ShellExecutor shellMainExcutor) {
|
||||
ShellExecutor mainExcutor) {
|
||||
mContext = context;
|
||||
mShellMainExcutor = shellMainExcutor;
|
||||
mMainExcutor = mainExcutor;
|
||||
mPipBoundsState = pipBoundsState;
|
||||
mMotionHelper = motionHelper;
|
||||
mTaskOrganizer = taskOrganizer;
|
||||
@@ -271,7 +271,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec,
|
||||
Bundle arguments) throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
mMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this
|
||||
.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, bounds,
|
||||
interactionId, callback, flags, interrogatingPid, interrogatingTid,
|
||||
@@ -285,7 +285,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
mMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.findAccessibilityNodeInfosByViewId(
|
||||
accessibilityNodeId, viewId, bounds, interactionId, callback, flags,
|
||||
interrogatingPid, interrogatingTid, spec);
|
||||
@@ -298,7 +298,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
mMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.findAccessibilityNodeInfosByText(
|
||||
accessibilityNodeId, text, bounds, interactionId, callback, flags,
|
||||
interrogatingPid, interrogatingTid, spec);
|
||||
@@ -310,7 +310,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
mMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.findFocus(accessibilityNodeId, focusType,
|
||||
bounds, interactionId, callback, flags, interrogatingPid, interrogatingTid,
|
||||
spec);
|
||||
@@ -322,7 +322,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid, MagnificationSpec spec)
|
||||
throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
mMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.focusSearch(accessibilityNodeId,
|
||||
direction,
|
||||
bounds, interactionId, callback, flags, interrogatingPid, interrogatingTid,
|
||||
@@ -335,7 +335,7 @@ public class PipAccessibilityInteractionConnection {
|
||||
Bundle arguments, int interactionId,
|
||||
IAccessibilityInteractionConnectionCallback callback, int flags,
|
||||
int interrogatingPid, long interrogatingTid) throws RemoteException {
|
||||
mShellMainExcutor.execute(() -> {
|
||||
mMainExcutor.execute(() -> {
|
||||
PipAccessibilityInteractionConnection.this.performAccessibilityAction(
|
||||
accessibilityNodeId, action, arguments, interactionId, callback, flags,
|
||||
interrogatingPid, interrogatingTid);
|
||||
|
||||
@@ -25,6 +25,8 @@ import android.view.SurfaceControl;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -49,11 +51,14 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase {
|
||||
@Mock
|
||||
private SurfaceControl mMockLeash;
|
||||
|
||||
@Mock
|
||||
private ShellExecutor mMainExecutor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mTutorialHandler = new OneHandedTutorialHandler(mContext);
|
||||
mTutorialHandler = new OneHandedTutorialHandler(mContext, mMainExecutor);
|
||||
mOneHandedAnimationController = new OneHandedAnimationController(mContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.om.IOverlayManager;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
@@ -33,6 +34,7 @@ import android.view.Display;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -45,7 +47,6 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
Display mDisplay;
|
||||
OneHandedController mOneHandedController;
|
||||
@@ -69,11 +70,16 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
IOverlayManager mMockOverlayManager;
|
||||
@Mock
|
||||
TaskStackListenerImpl mMockTaskStackListener;
|
||||
@Mock
|
||||
ShellExecutor mMockShellMainExecutor;
|
||||
@Mock
|
||||
Handler mMockShellMainHandler;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mDisplay = mContext.getDisplay();
|
||||
mTimeoutHandler = Mockito.spy(new OneHandedTimeoutHandler(mMockShellMainExecutor));
|
||||
OneHandedController oneHandedController = new OneHandedController(
|
||||
mContext,
|
||||
mMockDisplayController,
|
||||
@@ -82,10 +88,12 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
mMockTouchHandler,
|
||||
mMockTutorialHandler,
|
||||
mMockGestureHandler,
|
||||
mTimeoutHandler,
|
||||
mMockOverlayManager,
|
||||
mMockTaskStackListener);
|
||||
mMockTaskStackListener,
|
||||
mMockShellMainExecutor,
|
||||
mMockShellMainHandler);
|
||||
mOneHandedController = Mockito.spy(oneHandedController);
|
||||
mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get());
|
||||
|
||||
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
|
||||
when(mMockDisplayAreaOrganizer.isInOneHanded()).thenReturn(false);
|
||||
@@ -97,7 +105,7 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
mContext);
|
||||
OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer(
|
||||
mContext, mMockDisplayController, animationController, mMockTutorialHandler,
|
||||
Runnable::run, mMockBackgroundOrganizer);
|
||||
mMockBackgroundOrganizer, mMockShellMainExecutor);
|
||||
|
||||
assertThat(displayAreaOrganizer.isInOneHanded()).isFalse();
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ import android.window.WindowContainerTransaction;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -53,7 +54,6 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
static final int DISPLAY_WIDTH = 1000;
|
||||
static final int DISPLAY_HEIGHT = 1000;
|
||||
@@ -82,9 +82,8 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
WindowContainerTransaction mMockWindowContainerTransaction;
|
||||
@Mock
|
||||
OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
|
||||
|
||||
Handler mSpyUpdateHandler;
|
||||
Handler.Callback mUpdateCallback = (msg) -> false;
|
||||
@Mock
|
||||
ShellExecutor mMockShellMainExecutor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
@@ -110,19 +109,17 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
when(mMockLeash.getWidth()).thenReturn(DISPLAY_WIDTH);
|
||||
when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT);
|
||||
|
||||
mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(mContext,
|
||||
mDisplayAreaOrganizer = spy(new OneHandedDisplayAreaOrganizer(mContext,
|
||||
mMockDisplayController,
|
||||
mMockAnimationController,
|
||||
mTutorialHandler,
|
||||
Runnable::run, mMockBackgroundOrganizer);
|
||||
mSpyUpdateHandler = spy(new Handler(OneHandedThread.get().getLooper(), mUpdateCallback));
|
||||
mDisplayAreaOrganizer.setUpdateHandler(mSpyUpdateHandler);
|
||||
mMockBackgroundOrganizer,
|
||||
mMockShellMainExecutor));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnDisplayAreaAppeared() {
|
||||
mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mMockAnimationController, never()).getAnimator(any(), any(), any());
|
||||
}
|
||||
@@ -130,31 +127,18 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
@Test
|
||||
public void testOnDisplayAreaVanished() {
|
||||
mDisplayAreaOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
|
||||
mTestableLooper.processAllMessages();
|
||||
mDisplayAreaOrganizer.onDisplayAreaVanished(mDisplayAreaInfo);
|
||||
|
||||
assertThat(mDisplayAreaOrganizer.mDisplayAreaMap).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScheduleOffset() {
|
||||
final int xOffSet = 0;
|
||||
final int yOffSet = 100;
|
||||
mDisplayAreaOrganizer.scheduleOffset(xOffSet, yOffSet);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRotation_portrait_0_to_landscape_90() {
|
||||
when(mMockLeash.isValid()).thenReturn(false);
|
||||
// Rotate 0 -> 90
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_90,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -163,9 +147,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 0 -> 270
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_270,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,9 +156,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 180 -> 90
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_90,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -185,9 +165,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 180 -> 270
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_270,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -196,9 +174,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 90 -> 0
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_0,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -207,9 +183,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 90 -> 180
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_180,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -218,9 +192,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 270 -> 0
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_0,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -229,9 +201,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 270 -> 180
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_180,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -240,9 +210,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 0 -> 0
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_0,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,9 +219,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 0 -> 180
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_0, Surface.ROTATION_180,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -262,9 +228,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 180 -> 180
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_180,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -273,9 +237,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 180 -> 0
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_180, Surface.ROTATION_0,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -284,9 +246,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 90 -> 90
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_90,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -295,9 +255,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 90 -> 270
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_90, Surface.ROTATION_270,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -306,9 +264,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 270 -> 270
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_270,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -317,8 +273,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
// Rotate 270 -> 90
|
||||
mDisplayAreaOrganizer.onRotateDisplay(Surface.ROTATION_270, Surface.ROTATION_90,
|
||||
mMockWindowContainerTransaction);
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mSpyUpdateHandler, never()).sendMessage(any());
|
||||
verify(mDisplayAreaOrganizer, never()).finishOffset(anyInt(), anyInt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.testing.TestableLooper;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
@@ -36,17 +37,20 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedGestureHandlerTest extends OneHandedTestCase {
|
||||
OneHandedTutorialHandler mTutorialHandler;
|
||||
OneHandedGestureHandler mGestureHandler;
|
||||
@Mock
|
||||
DisplayController mMockDisplayController;
|
||||
@Mock
|
||||
ShellExecutor mMockShellMainExecutor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTutorialHandler = new OneHandedTutorialHandler(mContext);
|
||||
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
|
||||
mTutorialHandler = new OneHandedTutorialHandler(mContext, mMockShellMainExecutor);
|
||||
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
|
||||
mMockShellMainExecutor);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.junit.runner.RunWith;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedSettingsUtilTest extends OneHandedTestCase {
|
||||
ContentResolver mContentResolver;
|
||||
ContentObserver mContentObserver;
|
||||
|
||||
@@ -20,43 +20,46 @@ import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TI
|
||||
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS;
|
||||
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER;
|
||||
import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS;
|
||||
import static com.android.wm.shell.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedTimeoutHandlerTest extends OneHandedTestCase {
|
||||
OneHandedTimeoutHandler mTimeoutHandler;
|
||||
private OneHandedTimeoutHandler mTimeoutHandler;
|
||||
private ShellExecutor mMainExecutor;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeoutHandler_isNotNull() {
|
||||
assertThat(OneHandedTimeoutHandler.get()).isNotNull();
|
||||
mMainExecutor = new TestShellExecutor();
|
||||
mTimeoutHandler = Mockito.spy(new OneHandedTimeoutHandler(mMainExecutor));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimeoutHandler_getTimeout_defaultMedium() {
|
||||
assertThat(OneHandedTimeoutHandler.get().getTimeout()).isEqualTo(
|
||||
assertThat(mTimeoutHandler.getTimeout()).isEqualTo(
|
||||
ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
|
||||
}
|
||||
|
||||
@@ -64,28 +67,29 @@ public class OneHandedTimeoutHandlerTest extends OneHandedTestCase {
|
||||
public void testTimeoutHandler_setNewTime_resetTimer() {
|
||||
mTimeoutHandler.setTimeout(ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
|
||||
verify(mTimeoutHandler).resetTimer();
|
||||
assertThat(mTimeoutHandler.sHandler.hasMessages(ONE_HANDED_TIMEOUT_STOP_MSG)).isNotNull();
|
||||
assertTrue(mTimeoutHandler.hasScheduledTimeout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetTimeoutNever_neverResetTimer() {
|
||||
mTimeoutHandler.setTimeout(ONE_HANDED_TIMEOUT_NEVER);
|
||||
assertThat(!mTimeoutHandler.sHandler.hasMessages(ONE_HANDED_TIMEOUT_STOP_MSG)).isNotNull();
|
||||
assertFalse(mTimeoutHandler.hasScheduledTimeout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetTimeoutShort() {
|
||||
mTimeoutHandler.setTimeout(ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS);
|
||||
verify(mTimeoutHandler).resetTimer();
|
||||
assertThat(mTimeoutHandler.sHandler.hasMessages(ONE_HANDED_TIMEOUT_STOP_MSG)).isNotNull();
|
||||
assertThat(mTimeoutHandler.getTimeout()).isEqualTo(ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS);
|
||||
assertTrue(mTimeoutHandler.hasScheduledTimeout());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetTimeoutMedium() {
|
||||
mTimeoutHandler.setTimeout(ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
|
||||
verify(mTimeoutHandler).resetTimer();
|
||||
assertThat(mTimeoutHandler.sHandler.hasMessages(
|
||||
ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS)).isNotNull();
|
||||
assertThat(mTimeoutHandler.getTimeout()).isEqualTo(ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS);
|
||||
assertTrue(mTimeoutHandler.hasScheduledTimeout());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,10 +100,38 @@ public class OneHandedTimeoutHandlerTest extends OneHandedTestCase {
|
||||
|
||||
@Test
|
||||
public void testDragging_shouldRemoveAndSendEmptyMessageDelay() {
|
||||
final boolean isDragging = true;
|
||||
mTimeoutHandler.setTimeout(ONE_HANDED_TIMEOUT_LONG_IN_SECONDS);
|
||||
mTimeoutHandler.resetTimer();
|
||||
TestableLooper.get(this).processAllMessages();
|
||||
assertThat(mTimeoutHandler.sHandler.hasMessages(ONE_HANDED_TIMEOUT_STOP_MSG)).isNotNull();
|
||||
assertTrue(mTimeoutHandler.hasScheduledTimeout());
|
||||
}
|
||||
|
||||
private class TestShellExecutor implements ShellExecutor {
|
||||
private ArrayList<Runnable> mExecuted = new ArrayList<>();
|
||||
private ArrayList<Runnable> mDelayed = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
mExecuted.add(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeDelayed(Runnable r, long delayMillis) {
|
||||
mDelayed.add(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCallbacks(Runnable r) {
|
||||
mDelayed.remove(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCallback(Runnable r) {
|
||||
return mDelayed.contains(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Looper getLooper() {
|
||||
return Looper.myLooper();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,22 +23,30 @@ import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedTouchHandlerTest extends OneHandedTestCase {
|
||||
OneHandedTouchHandler mTouchHandler;
|
||||
private OneHandedTouchHandler mTouchHandler;
|
||||
|
||||
@Mock
|
||||
private OneHandedTimeoutHandler mTimeoutHandler;
|
||||
|
||||
@Mock
|
||||
private ShellExecutor mMainExecutor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTouchHandler = new OneHandedTouchHandler();
|
||||
mTouchHandler = new OneHandedTouchHandler(mTimeoutHandler, mMainExecutor);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,12 +19,14 @@ package com.android.wm.shell.onehanded;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.om.IOverlayManager;
|
||||
import android.os.Handler;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.TaskStackListenerImpl;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -35,12 +37,12 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
|
||||
@Mock
|
||||
OneHandedTouchHandler mTouchHandler;
|
||||
OneHandedTutorialHandler mTutorialHandler;
|
||||
OneHandedGestureHandler mGestureHandler;
|
||||
OneHandedTimeoutHandler mTimeoutHandler;
|
||||
OneHandedController mOneHandedController;
|
||||
@Mock
|
||||
DisplayController mMockDisplayController;
|
||||
@@ -52,12 +54,18 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
|
||||
IOverlayManager mMockOverlayManager;
|
||||
@Mock
|
||||
TaskStackListenerImpl mMockTaskStackListener;
|
||||
@Mock
|
||||
ShellExecutor mMockShellMainExecutor;
|
||||
@Mock
|
||||
Handler mMockShellMainHandler;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTutorialHandler = new OneHandedTutorialHandler(mContext);
|
||||
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController);
|
||||
mTutorialHandler = new OneHandedTutorialHandler(mContext, mMockShellMainExecutor);
|
||||
mTimeoutHandler = new OneHandedTimeoutHandler(mMockShellMainExecutor);
|
||||
mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
|
||||
mMockShellMainExecutor);
|
||||
mOneHandedController = new OneHandedController(
|
||||
getContext(),
|
||||
mMockDisplayController,
|
||||
@@ -66,8 +74,11 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
|
||||
mTouchHandler,
|
||||
mTutorialHandler,
|
||||
mGestureHandler,
|
||||
mTimeoutHandler,
|
||||
mMockOverlayManager,
|
||||
mMockTaskStackListener);
|
||||
mMockTaskStackListener,
|
||||
mMockShellMainExecutor,
|
||||
mMockShellMainHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -45,9 +45,9 @@ public class TvWMShellModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
|
||||
DisplayController displayController, @ShellMainThread ShellExecutor shellMainExecutor,
|
||||
DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor,
|
||||
TransactionPool transactionPool) {
|
||||
return new DisplayImeController(wmService, displayController, shellMainExecutor,
|
||||
return new DisplayImeController(wmService, displayController, mainExecutor,
|
||||
transactionPool);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.SystemUI;
|
||||
import com.android.systemui.dagger.SysUISingleton;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.keyguard.ScreenLifecycle;
|
||||
import com.android.systemui.model.SysUiState;
|
||||
import com.android.systemui.navigationbar.NavigationModeController;
|
||||
@@ -67,6 +68,7 @@ import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -86,18 +88,21 @@ public final class WMShell extends SystemUI
|
||||
| SYSUI_STATE_BUBBLES_EXPANDED
|
||||
| SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
|
||||
// Shell interfaces
|
||||
private final Optional<Pip> mPipOptional;
|
||||
private final Optional<LegacySplitScreen> mSplitScreenOptional;
|
||||
private final Optional<OneHanded> mOneHandedOptional;
|
||||
private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional;
|
||||
private final Optional<ShellCommandHandler> mShellCommandHandler;
|
||||
|
||||
private final CommandQueue mCommandQueue;
|
||||
private final ConfigurationController mConfigurationController;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final NavigationModeController mNavigationModeController;
|
||||
private final ScreenLifecycle mScreenLifecycle;
|
||||
private final SysUiState mSysUiState;
|
||||
private final Optional<Pip> mPipOptional;
|
||||
private final Optional<LegacySplitScreen> mSplitScreenOptional;
|
||||
private final Optional<OneHanded> mOneHandedOptional;
|
||||
private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional;
|
||||
private final ProtoTracer mProtoTracer;
|
||||
private final Optional<ShellCommandHandler> mShellCommandHandler;
|
||||
private final Executor mSysUiMainExecutor;
|
||||
|
||||
private boolean mIsSysUiStateValid;
|
||||
private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback;
|
||||
@@ -105,18 +110,20 @@ public final class WMShell extends SystemUI
|
||||
private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback;
|
||||
|
||||
@Inject
|
||||
public WMShell(Context context, CommandQueue commandQueue,
|
||||
public WMShell(Context context,
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<LegacySplitScreen> splitScreenOptional,
|
||||
Optional<OneHanded> oneHandedOptional,
|
||||
Optional<HideDisplayCutout> hideDisplayCutoutOptional,
|
||||
Optional<ShellCommandHandler> shellCommandHandler,
|
||||
CommandQueue commandQueue,
|
||||
ConfigurationController configurationController,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor,
|
||||
NavigationModeController navigationModeController,
|
||||
ScreenLifecycle screenLifecycle,
|
||||
SysUiState sysUiState,
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<LegacySplitScreen> splitScreenOptional,
|
||||
Optional<OneHanded> oneHandedOptional,
|
||||
Optional<HideDisplayCutout> hideDisplayCutoutOptional,
|
||||
ProtoTracer protoTracer,
|
||||
Optional<ShellCommandHandler> shellCommandHandler) {
|
||||
@Main Executor sysUiMainExecutor) {
|
||||
super(context);
|
||||
mCommandQueue = commandQueue;
|
||||
mConfigurationController = configurationController;
|
||||
@@ -129,12 +136,13 @@ public final class WMShell extends SystemUI
|
||||
mOneHandedOptional = oneHandedOptional;
|
||||
mHideDisplayCutoutOptional = hideDisplayCutoutOptional;
|
||||
mProtoTracer = protoTracer;
|
||||
mProtoTracer.add(this);
|
||||
mShellCommandHandler = shellCommandHandler;
|
||||
mSysUiMainExecutor = sysUiMainExecutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
mProtoTracer.add(this);
|
||||
mCommandQueue.addCallback(this);
|
||||
mPipOptional.ifPresent(this::initPip);
|
||||
mSplitScreenOptional.ifPresent(this::initSplitScreen);
|
||||
@@ -213,34 +221,43 @@ public final class WMShell extends SystemUI
|
||||
oneHanded.registerTransitionCallback(new OneHandedTransitionCallback() {
|
||||
@Override
|
||||
public void onStartFinished(Rect bounds) {
|
||||
mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
|
||||
true).commitUpdate(DEFAULT_DISPLAY);
|
||||
mSysUiMainExecutor.execute(() -> {
|
||||
mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
|
||||
true).commitUpdate(DEFAULT_DISPLAY);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopFinished(Rect bounds) {
|
||||
mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
|
||||
false).commitUpdate(DEFAULT_DISPLAY);
|
||||
mSysUiMainExecutor.execute(() -> {
|
||||
mSysUiState.setFlag(SYSUI_STATE_ONE_HANDED_ACTIVE,
|
||||
false).commitUpdate(DEFAULT_DISPLAY);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
oneHanded.registerGestureCallback(new OneHandedGestureEventCallback() {
|
||||
@Override
|
||||
public void onStart() {
|
||||
if (oneHanded.isOneHandedEnabled()) {
|
||||
oneHanded.startOneHanded();
|
||||
} else if (oneHanded.isSwipeToNotificationEnabled()) {
|
||||
mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
|
||||
}
|
||||
mSysUiMainExecutor.execute(() -> {
|
||||
if (oneHanded.isOneHandedEnabled()) {
|
||||
oneHanded.startOneHanded();
|
||||
} else if (oneHanded.isSwipeToNotificationEnabled()) {
|
||||
mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
if (oneHanded.isOneHandedEnabled()) {
|
||||
oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
|
||||
} else if (oneHanded.isSwipeToNotificationEnabled()) {
|
||||
mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
|
||||
}
|
||||
mSysUiMainExecutor.execute(() -> {
|
||||
if (oneHanded.isOneHandedEnabled()) {
|
||||
oneHanded.stopOneHanded(
|
||||
OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_GESTURE_OUT);
|
||||
} else if (oneHanded.isSwipeToNotificationEnabled()) {
|
||||
mCommandQueue.handleSystemKey(KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -110,9 +110,9 @@ public abstract class WMShellBaseModule {
|
||||
@ShellMainThread
|
||||
public static Handler provideShellMainHandler(@Main Handler sysuiMainHandler) {
|
||||
if (ENABLE_SHELL_MAIN_THREAD) {
|
||||
HandlerThread shellMainThread = new HandlerThread("wmshell.main");
|
||||
shellMainThread.start();
|
||||
return shellMainThread.getThreadHandler();
|
||||
HandlerThread mainThread = new HandlerThread("wmshell.main");
|
||||
mainThread.start();
|
||||
return mainThread.getThreadHandler();
|
||||
}
|
||||
return sysuiMainHandler;
|
||||
}
|
||||
@@ -123,10 +123,10 @@ public abstract class WMShellBaseModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
@ShellMainThread
|
||||
public static ShellExecutor provideShellMainExecutor(@ShellMainThread Handler shellMainHandler,
|
||||
public static ShellExecutor provideShellMainExecutor(@ShellMainThread Handler mainHandler,
|
||||
@Main ShellExecutor sysuiMainExecutor) {
|
||||
if (ENABLE_SHELL_MAIN_THREAD) {
|
||||
return new HandlerExecutor(shellMainHandler);
|
||||
return new HandlerExecutor(mainHandler);
|
||||
}
|
||||
return sysuiMainExecutor;
|
||||
}
|
||||
@@ -177,7 +177,7 @@ public abstract class WMShellBaseModule {
|
||||
Optional<AppPairs> appPairsOptional,
|
||||
FullscreenTaskListener fullscreenTaskListener,
|
||||
Transitions transitions,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return ShellInitImpl.create(displayImeController,
|
||||
dragAndDropController,
|
||||
shellTaskOrganizer,
|
||||
@@ -185,7 +185,7 @@ public abstract class WMShellBaseModule {
|
||||
appPairsOptional,
|
||||
fullscreenTaskListener,
|
||||
transitions,
|
||||
shellMainExecutor);
|
||||
mainExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,10 +201,10 @@ public abstract class WMShellBaseModule {
|
||||
Optional<OneHanded> oneHandedOptional,
|
||||
Optional<HideDisplayCutout> hideDisplayCutout,
|
||||
Optional<AppPairs> appPairsOptional,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return Optional.of(ShellCommandHandlerImpl.create(shellTaskOrganizer,
|
||||
legacySplitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
|
||||
appPairsOptional, shellMainExecutor));
|
||||
appPairsOptional, mainExecutor));
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -216,8 +216,8 @@ public abstract class WMShellBaseModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static DisplayController provideDisplayController(Context context,
|
||||
IWindowManager wmService, @ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
return new DisplayController(context, wmService, shellMainExecutor);
|
||||
IWindowManager wmService, @ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new DisplayController(context, wmService, mainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -236,8 +236,8 @@ public abstract class WMShellBaseModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static WindowManagerShellWrapper provideWindowManagerShellWrapper(
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
return new WindowManagerShellWrapper(shellMainExecutor);
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new WindowManagerShellWrapper(mainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -277,8 +277,8 @@ public abstract class WMShellBaseModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static SyncTransactionQueue provideSyncTransactionQueue(TransactionPool pool,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
return new SyncTransactionQueue(pool, shellMainExecutor);
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new SyncTransactionQueue(pool, mainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -299,8 +299,8 @@ public abstract class WMShellBaseModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static TaskStackListenerImpl providerTaskStackListenerImpl(
|
||||
@ShellMainThread Handler shellMainHandler) {
|
||||
return new TaskStackListenerImpl(shellMainHandler);
|
||||
@ShellMainThread Handler mainHandler) {
|
||||
return new TaskStackListenerImpl(mainHandler);
|
||||
}
|
||||
|
||||
@BindsOptionalOf
|
||||
@@ -319,20 +319,22 @@ public abstract class WMShellBaseModule {
|
||||
LauncherApps launcherApps,
|
||||
UiEventLogger uiEventLogger,
|
||||
ShellTaskOrganizer organizer,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return Optional.of(BubbleController.create(context, null /* synchronizer */,
|
||||
floatingContentCoordinator, statusBarService, windowManager,
|
||||
windowManagerShellWrapper, launcherApps, uiEventLogger, organizer,
|
||||
shellMainExecutor));
|
||||
mainExecutor));
|
||||
}
|
||||
|
||||
// Needs the shell main handler for ContentObserver callbacks
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static Optional<OneHanded> provideOneHandedController(Context context,
|
||||
DisplayController displayController, TaskStackListenerImpl taskStackListener,
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
@ShellMainThread ShellExecutor mainExecutor,
|
||||
@ShellMainThread Handler mainHandler) {
|
||||
return Optional.ofNullable(OneHandedController.create(context, displayController,
|
||||
taskStackListener, mainExecutor));
|
||||
taskStackListener, mainExecutor, mainHandler));
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
||||
@@ -62,9 +62,9 @@ public class WMShellModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static DisplayImeController provideDisplayImeController(IWindowManager wmService,
|
||||
DisplayController displayController, @ShellMainThread ShellExecutor shellMainExecutor,
|
||||
DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor,
|
||||
TransactionPool transactionPool) {
|
||||
return new DisplayImeController(wmService, displayController, shellMainExecutor,
|
||||
return new DisplayImeController(wmService, displayController, mainExecutor,
|
||||
transactionPool);
|
||||
}
|
||||
|
||||
@@ -96,11 +96,11 @@ public class WMShellModule {
|
||||
PhonePipMenuController phonePipMenuController, PipTaskOrganizer pipTaskOrganizer,
|
||||
PipTouchHandler pipTouchHandler, WindowManagerShellWrapper windowManagerShellWrapper,
|
||||
TaskStackListenerImpl taskStackListener,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return Optional.ofNullable(PipController.create(context, displayController,
|
||||
pipAppOpsListener, pipBoundsAlgorithm, pipBoundsState, pipMediaController,
|
||||
phonePipMenuController, pipTaskOrganizer, pipTouchHandler,
|
||||
windowManagerShellWrapper, taskStackListener, shellMainExecutor));
|
||||
windowManagerShellWrapper, taskStackListener, mainExecutor));
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@@ -131,10 +131,10 @@ public class WMShellModule {
|
||||
PipTaskOrganizer pipTaskOrganizer,
|
||||
FloatingContentCoordinator floatingContentCoordinator,
|
||||
PipUiEventLogger pipUiEventLogger,
|
||||
@ShellMainThread ShellExecutor shellMainExecutor) {
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new PipTouchHandler(context, menuPhoneController, pipBoundsAlgorithm,
|
||||
pipBoundsState, pipTaskOrganizer, floatingContentCoordinator, pipUiEventLogger,
|
||||
shellMainExecutor);
|
||||
mainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.CommandQueue;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
import com.android.wm.shell.ShellCommandHandler;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
|
||||
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
||||
import com.android.wm.shell.onehanded.OneHanded;
|
||||
@@ -63,22 +64,22 @@ public class WMShellTest extends SysuiTestCase {
|
||||
@Mock SysUiState mSysUiState;
|
||||
@Mock Pip mPip;
|
||||
@Mock PipTouchHandler mPipTouchHandler;
|
||||
@Mock
|
||||
LegacySplitScreen mLegacySplitScreen;
|
||||
@Mock LegacySplitScreen mLegacySplitScreen;
|
||||
@Mock OneHanded mOneHanded;
|
||||
@Mock HideDisplayCutout mHideDisplayCutout;
|
||||
@Mock ProtoTracer mProtoTracer;
|
||||
@Mock ShellCommandHandler mShellCommandHandler;
|
||||
@Mock ShellExecutor mSysUiMainExecutor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController,
|
||||
mWMShell = new WMShell(mContext, Optional.of(mPip), Optional.of(mLegacySplitScreen),
|
||||
Optional.of(mOneHanded), Optional.of(mHideDisplayCutout),
|
||||
Optional.of(mShellCommandHandler), mCommandQueue, mConfigurationController,
|
||||
mKeyguardUpdateMonitor, mNavigationModeController,
|
||||
mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mLegacySplitScreen),
|
||||
Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), mProtoTracer,
|
||||
Optional.of(mShellCommandHandler));
|
||||
mScreenLifecycle, mSysUiState, mProtoTracer, mSysUiMainExecutor);
|
||||
|
||||
when(mPip.getPipTouchHandler()).thenReturn(mPipTouchHandler);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user