Fix One-handed tutorial looks janky on entering transition

According to systrace, one-handed-tutorial-overlay got
jank problem(SurfaceFlinger GPU Deadline Missed,
App Deadline Missed, Buffer stuffing).

1.setLayerType(LAYER_TYPE_HARDWARE) when create targetViewContainer
  setLayerType(LAYER_TYPE_NONE) when removeTutorialFromWindowManager
2.Rename isShowing() to isAttached()
3.Remove redundant float casting
4.Remove redundant increment param

Test: manual trigger OHM
Test: atest WMShellUnitTests
Bug: 193589897
Change-Id: Ieec397795b46dee9ca04375bfc26b09441688d08
This commit is contained in:
Bill Lin
2021-07-14 17:23:46 +08:00
parent 4162c032bf
commit 500e2b146d
3 changed files with 46 additions and 39 deletions

View File

@@ -163,6 +163,7 @@ public class OneHandedAnimationController {
mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onOneHandedAnimationEnd(tx, this)
);
mOneHandedAnimationCallbacks.clear();
}
@Override
@@ -171,6 +172,7 @@ public class OneHandedAnimationController {
mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onOneHandedAnimationCancel(this)
);
mOneHandedAnimationCallbacks.clear();
}
@Override
@@ -182,7 +184,7 @@ public class OneHandedAnimationController {
final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
applySurfaceControlTransaction(mLeash, tx, animation.getAnimatedFraction());
mOneHandedAnimationCallbacks.forEach(
(callback) -> callback.onAnimationUpdate(0f, (float) mCurrentValue)
(callback) -> callback.onAnimationUpdate(0f, mCurrentValue)
);
}
@@ -216,7 +218,7 @@ public class OneHandedAnimationController {
}
float getDestinationOffset() {
return ((float) mEndValue - (float) mStartValue);
return (mEndValue - mStartValue);
}
@TransitionDirection
@@ -302,7 +304,7 @@ public class OneHandedAnimationController {
@Override
public float getInterpolation(float input) {
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;
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 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,
* TargetViewContainer only be created and attach to window when
* shown counts < {@link MAX_TUTORIAL_SHOW_COUNT}, and detach TargetViewContainer from window
* after exiting one handed mode.
* TargetViewContainer only be created and always attach to window,
* detach TargetViewContainer from window after exiting one handed mode.
*/
public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
OneHandedState.OnStateChangedListener {
@@ -58,7 +59,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
private final float mTutorialHeightRatio;
private final WindowManager mWindowManager;
private boolean mIsShowing;
private @OneHandedState.State int mCurrentState;
private int mTutorialAreaHeight;
@@ -80,11 +80,10 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
mAnimationCallback = new OneHandedAnimationCallback() {
@Override
public void onAnimationUpdate(float xPos, float yPos) {
if (!isShowing()) {
if (!isAttached()) {
return;
}
mTargetViewContainer.setTransitionGroup(true);
mTargetViewContainer.setTranslationY(yPos - mTargetViewContainer.getHeight());
mTargetViewContainer.setTranslationY(yPos - mTutorialAreaHeight);
}
};
}
@@ -101,7 +100,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
// no - op
break;
case STATE_NONE:
removeTutorialFromWindowManager(true /* increment */);
removeTutorialFromWindowManager();
break;
default:
break;
@@ -124,13 +123,14 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
@VisibleForTesting
void createViewAndAttachToWindow(Context context) {
if (isShowing()) {
if (isAttached()) {
return;
}
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
mTargetViewContainer = new FrameLayout(context);
mTargetViewContainer.setClipChildren(false);
mTargetViewContainer.addView(mTutorialView);
mTargetViewContainer.setLayerType(LAYER_TYPE_HARDWARE, null);
attachTargetToWindow();
}
@@ -139,29 +139,27 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
* Adds the tutorial target view to the WindowManager and update its layout.
*/
private void attachTargetToWindow() {
if (!mTargetViewContainer.isAttachedToWindow()) {
try {
mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
mIsShowing = true;
} catch (IllegalStateException e) {
// This shouldn't happen, but if the target is already added, just update its
// layout params.
mWindowManager.updateViewLayout(
mTargetViewContainer, getTutorialTargetLayoutParams());
}
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());
}
}
@VisibleForTesting
void removeTutorialFromWindowManager(boolean increment) {
if (mTargetViewContainer != null && mTargetViewContainer.isAttachedToWindow()) {
mWindowManager.removeViewImmediate(mTargetViewContainer);
mIsShowing = false;
void removeTutorialFromWindowManager() {
if (!isAttached()) {
return;
}
mTargetViewContainer.setLayerType(LAYER_TYPE_NONE, null);
mWindowManager.removeViewImmediate(mTargetViewContainer);
mTargetViewContainer = null;
}
@Nullable OneHandedAnimationCallback getAnimationCallback() {
return isShowing() ? mAnimationCallback : null /* Disabled */;
return mAnimationCallback;
}
/**
@@ -183,15 +181,15 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
}
@VisibleForTesting
boolean isShowing() {
return mIsShowing;
boolean isAttached() {
return mTargetViewContainer != null && mTargetViewContainer.isAttachedToWindow();
}
/**
* onConfigurationChanged events for updating tutorial text.
*/
public void onConfigurationChanged() {
removeTutorialFromWindowManager(false /* increment */);
removeTutorialFromWindowManager();
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
createViewAndAttachToWindow(mContext);
}
@@ -200,8 +198,8 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
void dump(@NonNull PrintWriter pw) {
final String innerPrefix = " ";
pw.println(TAG);
pw.print(innerPrefix + "mIsShowing=");
pw.println(mIsShowing);
pw.print(innerPrefix + "isAttached=");
pw.println(isAttached());
pw.print(innerPrefix + "mCurrentState=");
pw.println(mCurrentState);
pw.print(innerPrefix + "mDisplayBounds=");

View File

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