Merge "Fix One-handed tutorial looks janky on entering transition" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-07-18 17:31:34 +00:00
committed by Android (Google) Code Review
3 changed files with 46 additions and 39 deletions

View File

@@ -163,6 +163,7 @@ public class OneHandedAnimationController {
mOneHandedAnimationCallbacks.forEach( mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onOneHandedAnimationEnd(tx, this) (callback) -> callback.onOneHandedAnimationEnd(tx, this)
); );
mOneHandedAnimationCallbacks.clear();
} }
@Override @Override
@@ -171,6 +172,7 @@ public class OneHandedAnimationController {
mOneHandedAnimationCallbacks.forEach( mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onOneHandedAnimationCancel(this) (callback) -> callback.onOneHandedAnimationCancel(this)
); );
mOneHandedAnimationCallbacks.clear();
} }
@Override @Override
@@ -182,7 +184,7 @@ public class OneHandedAnimationController {
final SurfaceControl.Transaction tx = newSurfaceControlTransaction(); final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
applySurfaceControlTransaction(mLeash, tx, animation.getAnimatedFraction()); applySurfaceControlTransaction(mLeash, tx, animation.getAnimatedFraction());
mOneHandedAnimationCallbacks.forEach( mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onAnimationUpdate(0f, (float) mCurrentValue) (callback) -> callback.onAnimationUpdate(0f, mCurrentValue)
); );
} }
@@ -216,7 +218,7 @@ public class OneHandedAnimationController {
} }
float getDestinationOffset() { float getDestinationOffset() {
return ((float) mEndValue - (float) mStartValue); return (mEndValue - mStartValue);
} }
@TransitionDirection @TransitionDirection
@@ -302,7 +304,7 @@ public class OneHandedAnimationController {
@Override @Override
public float getInterpolation(float input) { public float getInterpolation(float input) {
return (float) (Math.pow(2, -10 * input) * Math.sin(((input - 4.0f) / 4.0f) return (float) (Math.pow(2, -10 * input) * Math.sin(((input - 4.0f) / 4.0f)
* (2.0f * Math.PI) / 4.0f) + 1); * (2.0f * Math.PI) / 4.0f) + 1.0f);
} }
} }

View File

@@ -16,6 +16,8 @@
package com.android.wm.shell.onehanded; package com.android.wm.shell.onehanded;
import static android.view.View.LAYER_TYPE_HARDWARE;
import static android.view.View.LAYER_TYPE_NONE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE; import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
@@ -45,9 +47,8 @@ import java.io.PrintWriter;
/** /**
* Handles tutorial visibility and synchronized transition for One Handed operations, * Handles tutorial visibility and synchronized transition for One Handed operations,
* TargetViewContainer only be created and attach to window when * TargetViewContainer only be created and always attach to window,
* shown counts < {@link MAX_TUTORIAL_SHOW_COUNT}, and detach TargetViewContainer from window * detach TargetViewContainer from window after exiting one handed mode.
* after exiting one handed mode.
*/ */
public class OneHandedTutorialHandler implements OneHandedTransitionCallback, public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
OneHandedState.OnStateChangedListener { OneHandedState.OnStateChangedListener {
@@ -58,7 +59,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
private final float mTutorialHeightRatio; private final float mTutorialHeightRatio;
private final WindowManager mWindowManager; private final WindowManager mWindowManager;
private boolean mIsShowing;
private @OneHandedState.State int mCurrentState; private @OneHandedState.State int mCurrentState;
private int mTutorialAreaHeight; private int mTutorialAreaHeight;
@@ -80,11 +80,10 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
mAnimationCallback = new OneHandedAnimationCallback() { mAnimationCallback = new OneHandedAnimationCallback() {
@Override @Override
public void onAnimationUpdate(float xPos, float yPos) { public void onAnimationUpdate(float xPos, float yPos) {
if (!isShowing()) { if (!isAttached()) {
return; return;
} }
mTargetViewContainer.setTransitionGroup(true); mTargetViewContainer.setTranslationY(yPos - mTutorialAreaHeight);
mTargetViewContainer.setTranslationY(yPos - mTargetViewContainer.getHeight());
} }
}; };
} }
@@ -101,7 +100,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
// no - op // no - op
break; break;
case STATE_NONE: case STATE_NONE:
removeTutorialFromWindowManager(true /* increment */); removeTutorialFromWindowManager();
break; break;
default: default:
break; break;
@@ -124,13 +123,14 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
@VisibleForTesting @VisibleForTesting
void createViewAndAttachToWindow(Context context) { void createViewAndAttachToWindow(Context context) {
if (isShowing()) { if (isAttached()) {
return; return;
} }
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null); mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
mTargetViewContainer = new FrameLayout(context); mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setClipChildren(false); mTargetViewContainer.setClipChildren(false);
mTargetViewContainer.addView(mTutorialView); mTargetViewContainer.addView(mTutorialView);
mTargetViewContainer.setLayerType(LAYER_TYPE_HARDWARE, null);
attachTargetToWindow(); attachTargetToWindow();
} }
@@ -139,29 +139,27 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
* Adds the tutorial target view to the WindowManager and update its layout. * Adds the tutorial target view to the WindowManager and update its layout.
*/ */
private void attachTargetToWindow() { private void attachTargetToWindow() {
if (!mTargetViewContainer.isAttachedToWindow()) {
try { try {
mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams()); mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
mIsShowing = true;
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// This shouldn't happen, but if the target is already added, just update its // This shouldn't happen, but if the target is already added, just update its
// layout params. // layout params.
mWindowManager.updateViewLayout( mWindowManager.updateViewLayout(mTargetViewContainer, getTutorialTargetLayoutParams());
mTargetViewContainer, getTutorialTargetLayoutParams());
}
} }
} }
@VisibleForTesting @VisibleForTesting
void removeTutorialFromWindowManager(boolean increment) { void removeTutorialFromWindowManager() {
if (mTargetViewContainer != null && mTargetViewContainer.isAttachedToWindow()) { if (!isAttached()) {
mWindowManager.removeViewImmediate(mTargetViewContainer); return;
mIsShowing = false;
} }
mTargetViewContainer.setLayerType(LAYER_TYPE_NONE, null);
mWindowManager.removeViewImmediate(mTargetViewContainer);
mTargetViewContainer = null;
} }
@Nullable OneHandedAnimationCallback getAnimationCallback() { @Nullable OneHandedAnimationCallback getAnimationCallback() {
return isShowing() ? mAnimationCallback : null /* Disabled */; return mAnimationCallback;
} }
/** /**
@@ -183,15 +181,15 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
} }
@VisibleForTesting @VisibleForTesting
boolean isShowing() { boolean isAttached() {
return mIsShowing; return mTargetViewContainer != null && mTargetViewContainer.isAttachedToWindow();
} }
/** /**
* onConfigurationChanged events for updating tutorial text. * onConfigurationChanged events for updating tutorial text.
*/ */
public void onConfigurationChanged() { public void onConfigurationChanged() {
removeTutorialFromWindowManager(false /* increment */); removeTutorialFromWindowManager();
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) { if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
createViewAndAttachToWindow(mContext); createViewAndAttachToWindow(mContext);
} }
@@ -200,8 +198,8 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
void dump(@NonNull PrintWriter pw) { void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " "; final String innerPrefix = " ";
pw.println(TAG); pw.println(TAG);
pw.print(innerPrefix + "mIsShowing="); pw.print(innerPrefix + "isAttached=");
pw.println(mIsShowing); pw.println(isAttached());
pw.print(innerPrefix + "mCurrentState="); pw.print(innerPrefix + "mCurrentState=");
pw.println(mCurrentState); pw.println(mCurrentState);
pw.print(innerPrefix + "mDisplayBounds="); pw.print(innerPrefix + "mDisplayBounds=");

View File

@@ -77,7 +77,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
@Test @Test
public void testOnStateChangedEntering_createViewAndAttachToWindow() { public void testOnStateChangedEntering_createViewAndAttachToWindow() {
when(mSpiedTutorialHandler.isShowing()).thenReturn(true); when(mSpiedTutorialHandler.isAttached()).thenReturn(true);
try { try {
mSpiedTutorialHandler.onStateChanged(STATE_ENTERING); mSpiedTutorialHandler.onStateChanged(STATE_ENTERING);
} catch (ClassCastException e) { } catch (ClassCastException e) {
@@ -89,23 +89,27 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
@Test @Test
public void testOnStateChangedNone_removeViewAndAttachToWindow() { public void testOnStateChangedNone_removeViewAndAttachToWindow() {
when(mSpiedTutorialHandler.isShowing()).thenReturn(true); when(mSpiedTutorialHandler.isAttached()).thenReturn(true);
try { try {
mSpiedTutorialHandler.onStateChanged(STATE_NONE); mSpiedTutorialHandler.onStateChanged(STATE_NONE);
} catch (ClassCastException e) { } catch (ClassCastException e) {
// no-op, just assert removeTutorialFromWindowManager() to be called // no-op, just assert removeTutorialFromWindowManager() to be called
} catch (NullPointerException e) {
// no-op, just assert removeTutorialFromWindowManager() to be called
} }
verify(mSpiedTutorialHandler).removeTutorialFromWindowManager(true); verify(mSpiedTutorialHandler).removeTutorialFromWindowManager();
} }
@Test @Test
public void testOnStateChangedNone_shouldNotAttachWindow() { public void testOnStateChangedNone_shouldNotAttachWindow() {
when(mSpiedTutorialHandler.isShowing()).thenReturn(true); when(mSpiedTutorialHandler.isAttached()).thenReturn(true);
try { try {
mSpiedTutorialHandler.onStateChanged(STATE_NONE); mSpiedTutorialHandler.onStateChanged(STATE_NONE);
} catch (ClassCastException e) { } catch (ClassCastException e) {
// no-op, just assert setTutorialShownCountIncrement() never be called // no-op, just assert setTutorialShownCountIncrement() never be called
} catch (NullPointerException e) {
// no-op, just assert setTutorialShownCountIncrement() never be called
} }
verify(mSpiedTutorialHandler, never()).createViewAndAttachToWindow(any()); verify(mSpiedTutorialHandler, never()).createViewAndAttachToWindow(any());
@@ -113,7 +117,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
@Test @Test
public void testOnConfigurationChanged_shouldUpdateViewContent() { public void testOnConfigurationChanged_shouldUpdateViewContent() {
when(mSpiedTutorialHandler.isShowing()).thenReturn(true); when(mSpiedTutorialHandler.isAttached()).thenReturn(true);
try { try {
mSpiedTutorialHandler.onStateChanged(STATE_ENTERING); mSpiedTutorialHandler.onStateChanged(STATE_ENTERING);
} catch (ClassCastException e) { } catch (ClassCastException e) {
@@ -122,9 +126,12 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
try { try {
mSpiedTutorialHandler.onConfigurationChanged(); mSpiedTutorialHandler.onConfigurationChanged();
} catch (ClassCastException e) { } catch (ClassCastException e) {
// no-op, just assert removeTutorialFromWindowManager() be called } catch (NullPointerException e) {
// no-op, just assert removeTutorialFromWindowManager() be called,
// and createViewAndAttachToWindow() be called twice
} }
verify(mSpiedTutorialHandler).removeTutorialFromWindowManager(false); verify(mSpiedTutorialHandler).createViewAndAttachToWindow(any());
verify(mSpiedTutorialHandler).removeTutorialFromWindowManager();
} }
} }