Merge "[2/n] Makes EduAnimationController generic" into tm-qpr-dev

This commit is contained in:
Massimo Carli
2022-12-23 10:05:21 +00:00
committed by Android (Google) Code Review
6 changed files with 81 additions and 34 deletions

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.wm.shell.compatui.letterboxedu; package com.android.wm.shell.compatui;
import static com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation; import static com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
import static com.android.internal.R.styleable.WindowAnimation_windowExitAnimation; import static com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
@@ -38,10 +38,15 @@ import android.view.animation.Animation;
import com.android.internal.policy.TransitionAnimation; import com.android.internal.policy.TransitionAnimation;
/** /**
* Controls the enter/exit animations of the letterbox education. * Controls the enter/exit a dialog.
*
* @param <T> The {@link DialogContainerSupplier} to use
*/ */
class LetterboxEduAnimationController { public class DialogAnimationController<T extends DialogContainerSupplier> {
private static final String TAG = "LetterboxEduAnimation";
// The alpha of a background is a number between 0 (fully transparent) to 255 (fully opaque).
// 204 is simply 255 * 0.8.
static final int BACKGROUND_DIM_ALPHA = 204;
// If shell transitions are enabled, startEnterAnimation will be called after all transitions // If shell transitions are enabled, startEnterAnimation will be called after all transitions
// have finished, and therefore the start delay should be shorter. // have finished, and therefore the start delay should be shorter.
@@ -49,6 +54,7 @@ class LetterboxEduAnimationController {
private final TransitionAnimation mTransitionAnimation; private final TransitionAnimation mTransitionAnimation;
private final String mPackageName; private final String mPackageName;
private final String mTag;
@AnyRes @AnyRes
private final int mAnimStyleResId; private final int mAnimStyleResId;
@@ -57,23 +63,24 @@ class LetterboxEduAnimationController {
@Nullable @Nullable
private Animator mBackgroundDimAnimator; private Animator mBackgroundDimAnimator;
LetterboxEduAnimationController(Context context) { public DialogAnimationController(Context context, String tag) {
mTransitionAnimation = new TransitionAnimation(context, /* debug= */ false, TAG); mTransitionAnimation = new TransitionAnimation(context, /* debug= */ false, tag);
mAnimStyleResId = (new ContextThemeWrapper(context, mAnimStyleResId = (new ContextThemeWrapper(context,
android.R.style.ThemeOverlay_Material_Dialog).getTheme()).obtainStyledAttributes( android.R.style.ThemeOverlay_Material_Dialog).getTheme()).obtainStyledAttributes(
com.android.internal.R.styleable.Window).getResourceId( com.android.internal.R.styleable.Window).getResourceId(
com.android.internal.R.styleable.Window_windowAnimationStyle, 0); com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
mPackageName = context.getPackageName(); mPackageName = context.getPackageName();
mTag = tag;
} }
/** /**
* Starts both background dim fade-in animation and the dialog enter animation. * Starts both background dim fade-in animation and the dialog enter animation.
*/ */
void startEnterAnimation(@NonNull LetterboxEduDialogLayout layout, Runnable endCallback) { public void startEnterAnimation(@NonNull T layout, Runnable endCallback) {
// Cancel any previous animation if it's still running. // Cancel any previous animation if it's still running.
cancelAnimation(); cancelAnimation();
final View dialogContainer = layout.getDialogContainer(); final View dialogContainer = layout.getDialogContainerView();
mDialogAnimation = loadAnimation(WindowAnimation_windowEnterAnimation); mDialogAnimation = loadAnimation(WindowAnimation_windowEnterAnimation);
if (mDialogAnimation == null) { if (mDialogAnimation == null) {
endCallback.run(); endCallback.run();
@@ -86,8 +93,8 @@ class LetterboxEduAnimationController {
endCallback.run(); endCallback.run();
})); }));
mBackgroundDimAnimator = getAlphaAnimator(layout.getBackgroundDim(), mBackgroundDimAnimator = getAlphaAnimator(layout.getBackgroundDimDrawable(),
/* endAlpha= */ LetterboxEduDialogLayout.BACKGROUND_DIM_ALPHA, /* endAlpha= */ BACKGROUND_DIM_ALPHA,
mDialogAnimation.getDuration()); mDialogAnimation.getDuration());
mBackgroundDimAnimator.addListener(getDimAnimatorListener()); mBackgroundDimAnimator.addListener(getDimAnimatorListener());
@@ -101,11 +108,11 @@ class LetterboxEduAnimationController {
/** /**
* Starts both the background dim fade-out animation and the dialog exit animation. * Starts both the background dim fade-out animation and the dialog exit animation.
*/ */
void startExitAnimation(@NonNull LetterboxEduDialogLayout layout, Runnable endCallback) { public void startExitAnimation(@NonNull T layout, Runnable endCallback) {
// Cancel any previous animation if it's still running. // Cancel any previous animation if it's still running.
cancelAnimation(); cancelAnimation();
final View dialogContainer = layout.getDialogContainer(); final View dialogContainer = layout.getDialogContainerView();
mDialogAnimation = loadAnimation(WindowAnimation_windowExitAnimation); mDialogAnimation = loadAnimation(WindowAnimation_windowExitAnimation);
if (mDialogAnimation == null) { if (mDialogAnimation == null) {
endCallback.run(); endCallback.run();
@@ -119,8 +126,8 @@ class LetterboxEduAnimationController {
endCallback.run(); endCallback.run();
})); }));
mBackgroundDimAnimator = getAlphaAnimator(layout.getBackgroundDim(), /* endAlpha= */ 0, mBackgroundDimAnimator = getAlphaAnimator(layout.getBackgroundDimDrawable(),
mDialogAnimation.getDuration()); /* endAlpha= */ 0, mDialogAnimation.getDuration());
mBackgroundDimAnimator.addListener(getDimAnimatorListener()); mBackgroundDimAnimator.addListener(getDimAnimatorListener());
dialogContainer.startAnimation(mDialogAnimation); dialogContainer.startAnimation(mDialogAnimation);
@@ -130,7 +137,7 @@ class LetterboxEduAnimationController {
/** /**
* Cancels all animations and resets the state of the controller. * Cancels all animations and resets the state of the controller.
*/ */
void cancelAnimation() { public void cancelAnimation() {
if (mDialogAnimation != null) { if (mDialogAnimation != null) {
mDialogAnimation.cancel(); mDialogAnimation.cancel();
mDialogAnimation = null; mDialogAnimation = null;
@@ -145,7 +152,7 @@ class LetterboxEduAnimationController {
Animation animation = mTransitionAnimation.loadAnimationAttr(mPackageName, mAnimStyleResId, Animation animation = mTransitionAnimation.loadAnimationAttr(mPackageName, mAnimStyleResId,
animAttr, /* translucent= */ false); animAttr, /* translucent= */ false);
if (animation == null) { if (animation == null) {
Log.e(TAG, "Failed to load animation " + animAttr); Log.e(mTag, "Failed to load animation " + animAttr);
} }
return animation; return animation;
} }

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2022 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.compatui;
import android.graphics.drawable.Drawable;
import android.view.View;
/**
* A component which can provide a {@link View} to use as a container for a Dialog
*/
public interface DialogContainerSupplier {
/**
* @return The {@link View} to use as a container for a Dialog
*/
View getDialogContainerView();
/**
* @return The {@link Drawable} to use as background of the dialog.
*/
Drawable getBackgroundDimDrawable();
}

View File

@@ -26,6 +26,7 @@ import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.wm.shell.R; import com.android.wm.shell.R;
import com.android.wm.shell.compatui.DialogContainerSupplier;
/** /**
* Container for Letterbox Education Dialog and background dim. * Container for Letterbox Education Dialog and background dim.
@@ -33,11 +34,7 @@ import com.android.wm.shell.R;
* <p>This layout should fill the entire task and the background around the dialog acts as the * <p>This layout should fill the entire task and the background around the dialog acts as the
* background dim which dismisses the dialog when clicked. * background dim which dismisses the dialog when clicked.
*/ */
class LetterboxEduDialogLayout extends ConstraintLayout { class LetterboxEduDialogLayout extends ConstraintLayout implements DialogContainerSupplier {
// The alpha of a background is a number between 0 (fully transparent) to 255 (fully opaque).
// 204 is simply 255 * 0.8.
static final int BACKGROUND_DIM_ALPHA = 204;
private View mDialogContainer; private View mDialogContainer;
private TextView mDialogTitle; private TextView mDialogTitle;
@@ -60,18 +57,20 @@ class LetterboxEduDialogLayout extends ConstraintLayout {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
} }
View getDialogContainer() { @Override
public View getDialogContainerView() {
return mDialogContainer; return mDialogContainer;
} }
@Override
public Drawable getBackgroundDimDrawable() {
return mBackgroundDim;
}
TextView getDialogTitle() { TextView getDialogTitle() {
return mDialogTitle; return mDialogTitle;
} }
Drawable getBackgroundDim() {
return mBackgroundDim;
}
/** /**
* Register a callback for the dismiss button and background dim. * Register a callback for the dismiss button and background dim.
* *

View File

@@ -37,6 +37,7 @@ import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.DockStateReader; import com.android.wm.shell.common.DockStateReader;
import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.CompatUIWindowManagerAbstract; import com.android.wm.shell.compatui.CompatUIWindowManagerAbstract;
import com.android.wm.shell.compatui.DialogAnimationController;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
/** /**
@@ -63,7 +64,7 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
*/ */
private final SharedPreferences mSharedPreferences; private final SharedPreferences mSharedPreferences;
private final LetterboxEduAnimationController mAnimationController; private final DialogAnimationController<LetterboxEduDialogLayout> mAnimationController;
private final Transitions mTransitions; private final Transitions mTransitions;
@@ -96,14 +97,17 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
DisplayLayout displayLayout, Transitions transitions, DisplayLayout displayLayout, Transitions transitions,
Runnable onDismissCallback, DockStateReader dockStateReader) { Runnable onDismissCallback, DockStateReader dockStateReader) {
this(context, taskInfo, syncQueue, taskListener, displayLayout, transitions, this(context, taskInfo, syncQueue, taskListener, displayLayout, transitions,
onDismissCallback, new LetterboxEduAnimationController(context), dockStateReader); onDismissCallback,
new DialogAnimationController<>(context, /* tag */ "LetterboxEduWindowManager"),
dockStateReader);
} }
@VisibleForTesting @VisibleForTesting
LetterboxEduWindowManager(Context context, TaskInfo taskInfo, LetterboxEduWindowManager(Context context, TaskInfo taskInfo,
SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener, SyncTransactionQueue syncQueue, ShellTaskOrganizer.TaskListener taskListener,
DisplayLayout displayLayout, Transitions transitions, Runnable onDismissCallback, DisplayLayout displayLayout, Transitions transitions, Runnable onDismissCallback,
LetterboxEduAnimationController animationController, DockStateReader dockStateReader) { DialogAnimationController<LetterboxEduDialogLayout> animationController,
DockStateReader dockStateReader) {
super(context, taskInfo, syncQueue, taskListener, displayLayout); super(context, taskInfo, syncQueue, taskListener, displayLayout);
mTransitions = transitions; mTransitions = transitions;
mOnDismissCallback = onDismissCallback; mOnDismissCallback = onDismissCallback;
@@ -160,7 +164,7 @@ public class LetterboxEduWindowManager extends CompatUIWindowManagerAbstract {
if (mLayout == null) { if (mLayout == null) {
return; return;
} }
final View dialogContainer = mLayout.getDialogContainer(); final View dialogContainer = mLayout.getDialogContainerView();
MarginLayoutParams marginParams = (MarginLayoutParams) dialogContainer.getLayoutParams(); MarginLayoutParams marginParams = (MarginLayoutParams) dialogContainer.getLayoutParams();
final Rect taskBounds = getTaskBounds(); final Rect taskBounds = getTaskBounds();

View File

@@ -68,11 +68,11 @@ public class LetterboxEduDialogLayoutTest extends ShellTestCase {
@Test @Test
public void testOnFinishInflate() { public void testOnFinishInflate() {
assertEquals(mLayout.getDialogContainer(), assertEquals(mLayout.getDialogContainerView(),
mLayout.findViewById(R.id.letterbox_education_dialog_container)); mLayout.findViewById(R.id.letterbox_education_dialog_container));
assertEquals(mLayout.getDialogTitle(), assertEquals(mLayout.getDialogTitle(),
mLayout.findViewById(R.id.letterbox_education_dialog_title)); mLayout.findViewById(R.id.letterbox_education_dialog_title));
assertEquals(mLayout.getBackgroundDim(), mLayout.getBackground()); assertEquals(mLayout.getBackgroundDimDrawable(), mLayout.getBackground());
assertEquals(mLayout.getBackground().getAlpha(), 0); assertEquals(mLayout.getBackground().getAlpha(), 0);
} }

View File

@@ -56,6 +56,7 @@ import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.common.DockStateReader; import com.android.wm.shell.common.DockStateReader;
import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.compatui.DialogAnimationController;
import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.transition.Transitions;
import org.junit.After; import org.junit.After;
@@ -98,7 +99,7 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase {
@Captor @Captor
private ArgumentCaptor<Runnable> mRunOnIdleCaptor; private ArgumentCaptor<Runnable> mRunOnIdleCaptor;
@Mock private LetterboxEduAnimationController mAnimationController; @Mock private DialogAnimationController<LetterboxEduDialogLayout> mAnimationController;
@Mock private SyncTransactionQueue mSyncTransactionQueue; @Mock private SyncTransactionQueue mSyncTransactionQueue;
@Mock private ShellTaskOrganizer.TaskListener mTaskListener; @Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private SurfaceControlViewHost mViewHost; @Mock private SurfaceControlViewHost mViewHost;
@@ -366,7 +367,7 @@ public class LetterboxEduWindowManagerTest extends ShellTestCase {
assertThat(params.width).isEqualTo(expectedWidth); assertThat(params.width).isEqualTo(expectedWidth);
assertThat(params.height).isEqualTo(expectedHeight); assertThat(params.height).isEqualTo(expectedHeight);
MarginLayoutParams dialogParams = MarginLayoutParams dialogParams =
(MarginLayoutParams) layout.getDialogContainer().getLayoutParams(); (MarginLayoutParams) layout.getDialogContainerView().getLayoutParams();
int verticalMargin = (int) mContext.getResources().getDimension( int verticalMargin = (int) mContext.getResources().getDimension(
R.dimen.letterbox_education_dialog_margin); R.dimen.letterbox_education_dialog_margin);
assertThat(dialogParams.topMargin).isEqualTo(verticalMargin + expectedExtraTopMargin); assertThat(dialogParams.topMargin).isEqualTo(verticalMargin + expectedExtraTopMargin);