diff --git a/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png new file mode 100644 index 0000000000000..6c1f1cfdea7cc Binary files /dev/null and b/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png differ diff --git a/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png new file mode 100644 index 0000000000000..6983c3b880c9e Binary files /dev/null and b/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png differ diff --git a/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png new file mode 100644 index 0000000000000..3ff692f0c6fca Binary files /dev/null and b/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png differ diff --git a/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png new file mode 100644 index 0000000000000..75723fb2ea5a1 Binary files /dev/null and b/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png differ diff --git a/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png new file mode 100644 index 0000000000000..173abedae48a5 Binary files /dev/null and b/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png differ diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 8b6543ac73bdf..77d3f4513957d 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2838,4 +2838,9 @@ + + + Using one-handed mode + + To exit, swipe up from the bottom of the screen or tap anywhere above the app diff --git a/packages/SystemUI/res/xml/one_handed_tutorial.xml b/packages/SystemUI/res/xml/one_handed_tutorial.xml new file mode 100644 index 0000000000000..dc54caf0f14aa --- /dev/null +++ b/packages/SystemUI/res/xml/one_handed_tutorial.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java index c581ac6775322..264ace7493839 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java @@ -42,4 +42,10 @@ public interface OneHandedAnimationCallback { default void onOneHandedAnimationCancel( OneHandedAnimationController.OneHandedTransitionAnimator animator) { } + + /** + * Called when OneHanded animator is updating offset + */ + default void onTutorialAnimationUpdate(int offset) {} + } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java index 1926c44abcba7..2b07ac3f4d8ab 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java @@ -28,7 +28,9 @@ import androidx.annotation.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import javax.inject.Inject; @@ -121,7 +123,8 @@ public class OneHandedAnimationController { private T mEndValue; private T mCurrentValue; - private OneHandedAnimationCallback mOneHandedAnimationCallback; + private final List mOneHandedAnimationCallbacks = + new ArrayList<>(); private OneHandedSurfaceTransactionHelper mSurfaceTransactionHelper; private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; @@ -142,9 +145,11 @@ public class OneHandedAnimationController { @Override public void onAnimationStart(Animator animation) { mCurrentValue = mStartValue; - if (mOneHandedAnimationCallback != null) { - mOneHandedAnimationCallback.onOneHandedAnimationStart(this); - } + mOneHandedAnimationCallbacks.forEach( + (callback) -> { + callback.onOneHandedAnimationStart(this); + } + ); } @Override @@ -152,17 +157,21 @@ public class OneHandedAnimationController { mCurrentValue = mEndValue; final SurfaceControl.Transaction tx = newSurfaceControlTransaction(); onEndTransaction(mLeash, tx); - if (mOneHandedAnimationCallback != null) { - mOneHandedAnimationCallback.onOneHandedAnimationEnd(tx, this); - } + mOneHandedAnimationCallbacks.forEach( + (callback) -> { + callback.onOneHandedAnimationEnd(tx, this); + } + ); } @Override public void onAnimationCancel(Animator animation) { mCurrentValue = mEndValue; - if (mOneHandedAnimationCallback != null) { - mOneHandedAnimationCallback.onOneHandedAnimationCancel(this); - } + mOneHandedAnimationCallbacks.forEach( + (callback) -> { + callback.onOneHandedAnimationCancel(this); + } + ); } @Override @@ -173,6 +182,11 @@ public class OneHandedAnimationController { public void onAnimationUpdate(ValueAnimator animation) { applySurfaceControlTransaction(mLeash, newSurfaceControlTransaction(), animation.getAnimatedFraction()); + mOneHandedAnimationCallbacks.forEach( + (callback) -> { + callback.onTutorialAnimationUpdate(((Rect) mCurrentValue).top); + } + ); } void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) { @@ -192,9 +206,9 @@ public class OneHandedAnimationController { mSurfaceTransactionHelper = helper; } - OneHandedTransitionAnimator setOneHandedAnimationCallback( + OneHandedTransitionAnimator setOneHandedAnimationCallbacks( OneHandedAnimationCallback callback) { - mOneHandedAnimationCallback = callback; + mOneHandedAnimationCallbacks.add(callback); return this; } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java index c0b9258f39fdf..8550959aa2c47 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java @@ -82,6 +82,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen private OneHandedAnimationController mAnimationController; private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; + private OneHandedTutorialHandler mTutorialHandler; private List mTransitionCallbacks = new ArrayList<>(); @VisibleForTesting @@ -148,7 +149,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen @Inject public OneHandedDisplayAreaOrganizer(Context context, DisplayController displayController, - OneHandedAnimationController animationController) { + OneHandedAnimationController animationController, + OneHandedTutorialHandler tutorialHandler) { mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback); mAnimationController = animationController; mDisplayController = displayController; @@ -157,6 +159,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen mEnterExitAnimationDurationMs = context.getResources().getInteger( com.android.systemui.R.integer.config_one_handed_translate_animation_duration); mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; + mTutorialHandler = tutorialHandler; } @Override @@ -272,7 +275,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen mAnimationController.getAnimator(leash, fromBounds, toBounds); if (animator != null) { animator.setTransitionDirection(direction) - .setOneHandedAnimationCallback(mOneHandedAnimationCallback) + .setOneHandedAnimationCallbacks(mOneHandedAnimationCallback) + .setOneHandedAnimationCallbacks(mTutorialHandler.getAnimationCallback()) .setDuration(durationMs) .start(); } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java index 71c5f80203301..ded386159dca5 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java @@ -53,8 +53,8 @@ import javax.inject.Singleton; */ @Singleton public class OneHandedGestureHandler implements OneHandedTransitionCallback, - NavigationModeController.ModeChangedListener, - DisplayChangeController.OnDisplayChangingListener { + NavigationModeController.ModeChangedListener, + DisplayChangeController.OnDisplayChangingListener { private static final String TAG = "OneHandedGestureHandler"; private static final boolean DEBUG_GESTURE = false; @@ -87,8 +87,8 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, * Constructor of OneHandedGestureHandler, we only handle the gesture of * {@link Display#DEFAULT_DISPLAY} * - * @param context {@link Context} - * @param displayController {@link DisplayController} + * @param context {@link Context} + * @param displayController {@link DisplayController} * @param navigationModeController {@link NavigationModeController} */ @Inject @@ -103,7 +103,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, mDragDistThreshold = context.getResources().getDimensionPixelSize( R.dimen.gestures_onehanded_drag_threshold); final float slop = ViewConfiguration.get(context).getScaledTouchSlop(); - mSquaredSlop = slop * slop; + mSquaredSlop = slop * slop; updateIsEnabled(); } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java index 70a81aaed249a..51e5875868524 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java @@ -57,6 +57,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { private final OneHandedGestureHandler mGestureHandler; private final OneHandedTimeoutHandler mTimeoutHandler; private final OneHandedTouchHandler mTouchHandler; + private final OneHandedTutorialHandler mTutorialHandler; private final SysUiState mSysUiFlagContainer; private Context mContext; @@ -107,6 +108,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { DisplayController displayController, OneHandedDisplayAreaOrganizer displayAreaOrganizer, OneHandedTouchHandler touchHandler, + OneHandedTutorialHandler tutorialHandler, OneHandedGestureHandler gestureHandler, SysUiState sysUiState) { mContext = context; @@ -120,6 +122,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { context.getContentResolver()); mTimeoutHandler = OneHandedTimeoutHandler.get(); mTouchHandler = touchHandler; + mTutorialHandler = tutorialHandler; mGestureHandler = gestureHandler; updateOneHandedEnabled(); setupGestures(); @@ -230,6 +233,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable { mDisplayAreaOrganizer.registerTransitionCallback(mTransitionCallback); mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler); mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler); + mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler); } /** diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java index 3d4338c1e2200..d616a3a45b90d 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java @@ -58,6 +58,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa OneHandedTouchEventCallback mTouchEventCallback; private boolean mIsEnabled; + private boolean mIsOnStopTransitioning; private boolean mIsInOutsideRegion; @Inject @@ -96,8 +97,9 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: { mTimeoutHandler.resetTimer(); - if (mIsInOutsideRegion) { + if (mIsInOutsideRegion && !mIsOnStopTransitioning) { mTouchEventCallback.onStop(); + mIsOnStopTransitioning = true; } // Reset flag for next operation mIsInOutsideRegion = false; @@ -146,6 +148,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa @Override public void onStopFinished(Rect bounds) { mLastUpdatedBounds.set(bounds); + mIsOnStopTransitioning = false; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java new file mode 100644 index 0000000000000..8a67da53e6a2a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java @@ -0,0 +1,161 @@ +/* + * 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.systemui.onehanded; + +import android.content.Context; +import android.graphics.PixelFormat; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Handler; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; + +import com.android.systemui.Dumpable; +import com.android.systemui.R; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Manages the user tutorial handling for One Handed operations, including animations synchronized + * with one-handed translation. + * Refer {@link OneHandedGestureHandler} and {@link OneHandedTouchHandler} to see start and stop + * one handed gesture + */ +@Singleton +public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Dumpable { + private static final String TAG = "OneHandedTutorialHandler"; + private final Rect mLastUpdatedBounds = new Rect(); + private final WindowManager mWindowManager; + + private View mTutorialView; + private Point mDisplaySize = new Point(); + private Handler mUpdateHandler; + + /** + * Container of the tutorial panel showing at outside region when one handed starting + */ + private ViewGroup mTargetViewContainer; + private int mTutorialAreaHeight; + + private final OneHandedAnimationCallback mAnimationCallback = new OneHandedAnimationCallback() { + @Override + public void onTutorialAnimationUpdate(int offset) { + mUpdateHandler.post(() -> onAnimationUpdate(offset)); + } + }; + + @Inject + public OneHandedTutorialHandler(Context context) { + context.getDisplay().getRealSize(mDisplaySize); + mUpdateHandler = new Handler(); + mWindowManager = context.getSystemService(WindowManager.class); + mTargetViewContainer = new FrameLayout(context); + mTargetViewContainer.setClipChildren(false); + mTutorialAreaHeight = Math.round(mDisplaySize.y * context.getResources().getFraction( + R.fraction.config_one_handed_offset, 1, 1)); + mTutorialView = LayoutInflater.from(context).inflate(R.xml.one_handed_tutorial, null); + mTargetViewContainer.addView(mTutorialView); + createOrUpdateTutorialTarget(); + } + + @Override + public void onStartFinished(Rect bounds) { + mUpdateHandler.post(() -> updateFinished(View.VISIBLE, 0f)); + } + + @Override + public void onStopFinished(Rect bounds) { + mUpdateHandler.post(() -> updateFinished( + View.INVISIBLE, -mTargetViewContainer.getHeight())); + } + + private void updateFinished(int visible, float finalPosition) { + mTargetViewContainer.setVisibility(visible); + mTargetViewContainer.setTranslationY(finalPosition); + } + + /** + * Adds the tutorial target view to the WindowManager and update its layout, so it's ready + * to be animated in. + */ + private void createOrUpdateTutorialTarget() { + mUpdateHandler.post(() -> { + if (!mTargetViewContainer.isAttachedToWindow()) { + mTargetViewContainer.setVisibility(View.INVISIBLE); + + try { + mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams()); + } catch (IllegalStateException e) { + // This shouldn't happen, but if the target is already added, just update its + // layout params. + mWindowManager.updateViewLayout( + mTargetViewContainer, getTutorialTargetLayoutParams()); + } + } else { + mWindowManager.updateViewLayout(mTargetViewContainer, + getTutorialTargetLayoutParams()); + } + }); + } + + OneHandedAnimationCallback getAnimationCallback() { + return mAnimationCallback; + } + + /** + * Returns layout params for the dismiss target, using the latest display metrics. + */ + private WindowManager.LayoutParams getTutorialTargetLayoutParams() { + final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + mDisplaySize.x, mTutorialAreaHeight, 0, 0, + WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, + PixelFormat.TRANSLUCENT); + lp.gravity = Gravity.TOP | Gravity.LEFT; + lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; + lp.setFitInsetsTypes(0 /* types */); + lp.setTitle("one-handed-tutorial-overlay"); + + return lp; + } + + @Override + public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { + final String innerPrefix = " "; + pw.println(TAG + "states: "); + pw.print(innerPrefix + "mLastUpdatedBounds="); + pw.println(mLastUpdatedBounds); + } + + private void onAnimationUpdate(float value) { + mTargetViewContainer.setVisibility(View.VISIBLE); + mTargetViewContainer.setTransitionGroup(true); + mTargetViewContainer.setTranslationY(value - mTargetViewContainer.getHeight()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java index 583d0692565fd..73164b520b9d9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java @@ -44,6 +44,7 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase { private static final int TEST_BOUNDS_HEIGHT = 1000; OneHandedAnimationController mOneHandedAnimationController; + OneHandedTutorialHandler mTutorialHandler; @Mock private SurfaceControl mMockLeash; @@ -52,6 +53,7 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mTutorialHandler = new OneHandedTutorialHandler(mContext); mOneHandedAnimationController = new OneHandedAnimationController( new OneHandedSurfaceTransactionHelper(mContext)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java index 3231b2852e7c4..a989cd1f9c404 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java @@ -61,6 +61,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { DisplayAreaInfo mDisplayAreaInfo; Display mDisplay; OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer; + OneHandedTutorialHandler mTutorialHandler; OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator; WindowContainerToken mToken; SurfaceControl mLeash; @@ -97,14 +98,15 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase { mMockSurfaceTransactionHelper); when(mMockAnimator.isRunning()).thenReturn(true); when(mMockAnimator.setDuration(anyInt())).thenReturn(mFakeAnimator); - when(mMockAnimator.setOneHandedAnimationCallback(any())).thenReturn(mFakeAnimator); + when(mMockAnimator.setOneHandedAnimationCallbacks(any())).thenReturn(mFakeAnimator); when(mMockAnimator.setTransitionDirection(anyInt())).thenReturn(mFakeAnimator); when(mMockLeash.getWidth()).thenReturn(DISPLAY_WIDTH); when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT); mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(mContext, mMockDisplayController, - mMockAnimationController); + mMockAnimationController, + mTutorialHandler); mUpdateHandler = mDisplayAreaOrganizer.getUpdateHandler(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java index 3b284b14c36f4..694f51be4e30e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java @@ -48,6 +48,7 @@ import org.mockito.MockitoAnnotations; public class OneHandedGestureHandlerTest extends OneHandedTestCase { Instrumentation mInstrumentation; OneHandedTouchHandler mTouchHandler; + OneHandedTutorialHandler mTutorialHandler; OneHandedGestureHandler mGestureHandler; OneHandedManagerImpl mOneHandedManagerImpl; @Mock @@ -62,13 +63,15 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mInstrumentation = InstrumentationRegistry.getInstrumentation(); - mTouchHandler = Mockito.spy(new OneHandedTouchHandler()); + mTouchHandler = new OneHandedTouchHandler(); + mTutorialHandler = new OneHandedTutorialHandler(mContext); mGestureHandler = Mockito.spy(new OneHandedGestureHandler( mContext, mMockDisplayController, mMockNavigationModeController)); mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(), mMockDisplayController, mMockDisplayAreaOrganizer, mTouchHandler, + mTutorialHandler, mGestureHandler, mMockSysUiState); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java index 55bec54eacb8f..3418ebf75e0cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java @@ -57,6 +57,8 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { @Mock OneHandedTouchHandler mMockTouchHandler; @Mock + OneHandedTutorialHandler mMockTutorialHandler; + @Mock OneHandedGestureHandler mMockGestureHandler; @Mock SysUiState mMockSysUiState; @@ -69,6 +71,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { mMockDisplayController, mMockDisplayAreaOrganizer, mMockTouchHandler, + mMockTutorialHandler, mMockGestureHandler, mMockSysUiState); mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get()); @@ -84,7 +87,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase { final OneHandedAnimationController animationController = new OneHandedAnimationController( transactionHelper); OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer( - mContext, mMockDisplayController, animationController); + mContext, mMockDisplayController, animationController, mMockTutorialHandler); assertThat(displayAreaOrganizer.isInOneHanded()).isFalse(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java index 3a4ba6a213dc0..fdb28d3d43b5a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java @@ -46,6 +46,7 @@ import org.mockito.MockitoAnnotations; public class OneHandedTouchHandlerTest extends OneHandedTestCase { Instrumentation mInstrumentation; OneHandedTouchHandler mTouchHandler; + OneHandedTutorialHandler mTutorialHandler; OneHandedGestureHandler mGestureHandler; OneHandedManagerImpl mOneHandedManagerImpl; @Mock @@ -68,13 +69,15 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase { mMockDisplayController, mMockDisplayAreaOrganizer, mTouchHandler, + mTutorialHandler, mGestureHandler, mMockSysUiState); } @Test public void testOneHandedManager_registerForDisplayAreaOrganizer() { - verify(mMockDisplayAreaOrganizer, times(1)).registerTransitionCallback(mTouchHandler); + verify(mMockDisplayAreaOrganizer, times(1)) + .registerTransitionCallback(mTouchHandler); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java new file mode 100644 index 0000000000000..f4aa00eaf02fd --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java @@ -0,0 +1,80 @@ +/* + * 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.systemui.onehanded; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.app.Instrumentation; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.systemui.model.SysUiState; +import com.android.systemui.statusbar.phone.NavigationModeController; +import com.android.wm.shell.common.DisplayController; + +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; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class OneHandedTutorialHandlerTest extends OneHandedTestCase { + Instrumentation mInstrumentation; + OneHandedTouchHandler mTouchHandler; + OneHandedTutorialHandler mTutorialHandler; + OneHandedGestureHandler mGestureHandler; + OneHandedManagerImpl mOneHandedManagerImpl; + @Mock + DisplayController mMockDisplayController; + @Mock + NavigationModeController mMockNavigationModeController; + @Mock + OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; + @Mock + SysUiState mMockSysUiState; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mInstrumentation = InstrumentationRegistry.getInstrumentation(); + mTouchHandler = new OneHandedTouchHandler(); + mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext)); + mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController, + mMockNavigationModeController); + mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(), + mMockDisplayController, + mMockDisplayAreaOrganizer, + mTouchHandler, + mTutorialHandler, + mGestureHandler, + mMockSysUiState); + } + + @Test + public void testOneHandedManager_registerForDisplayAreaOrganizer() { + verify(mMockDisplayAreaOrganizer, times(1)) + .registerTransitionCallback(mTutorialHandler); + } +}