Implement Tutorial panel for one handed
To educate users using one-handed mode showing tutorial at top region when one handed triggered Bug: 151800576 Test: manual Change-Id: I255a08bf4527554ee8970c3baaf85b8956b2ca83
This commit is contained in:
BIN
packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png
Normal file
BIN
packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png
Normal file
BIN
packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
BIN
packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png
Normal file
BIN
packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png
Normal file
BIN
packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
BIN
packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png
Normal file
BIN
packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
@@ -2838,4 +2838,9 @@
|
||||
<string name="udfps_hbm_enable_command" translatable="false"></string>
|
||||
<!-- Device-specific payload for disabling the high-brightness mode -->
|
||||
<string name="udfps_hbm_disable_command" translatable="false"></string>
|
||||
|
||||
<!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
|
||||
<string name="one_handed_tutorial_title">Using one-handed mode</string>
|
||||
<!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
|
||||
<string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string>
|
||||
</resources>
|
||||
|
||||
67
packages/SystemUI/res/xml/one_handed_tutorial.xml
Normal file
67
packages/SystemUI/res/xml/one_handed_tutorial.xml
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ 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
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/one_handed_tutorial_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal | center_vertical"
|
||||
android:background="@android:color/transparent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/one_handed_tutorial_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:src="@drawable/one_handed_tutorial"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/one_handed_tutorial_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAlignment="center"
|
||||
android:fontFamily="google-sans-medium"
|
||||
android:text="@string/one_handed_tutorial_title"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/one_handed_tutorial_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_marginStart="86dp"
|
||||
android:layout_marginEnd="86dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:fontFamily="roboto-regular"
|
||||
android:text="@string/one_handed_tutorial_description"
|
||||
android:textAlignment="center"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="normal"
|
||||
android:alpha="0.7"
|
||||
android:textColor="@android:color/white"/>
|
||||
</LinearLayout>
|
||||
@@ -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) {}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<OneHandedAnimationCallback> 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<T> setOneHandedAnimationCallback(
|
||||
OneHandedTransitionAnimator<T> setOneHandedAnimationCallbacks(
|
||||
OneHandedAnimationCallback callback) {
|
||||
mOneHandedAnimationCallback = callback;
|
||||
mOneHandedAnimationCallbacks.add(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
|
||||
private OneHandedAnimationController mAnimationController;
|
||||
private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
|
||||
mSurfaceControlTransactionFactory;
|
||||
private OneHandedTutorialHandler mTutorialHandler;
|
||||
private List<OneHandedTransitionCallback> 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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user