Move assist handles from ScreenDecorations to navigation bar
To improve the performance of display cutouts, we need to first move the assist handles out of ScreenDecorations so that we can remove the layer of ScreenDecorations later. Bug: 140781914 Test: atest ScreenDecorationsTest, atest AssistHandleBehaviorControllerTest Change-Id: I7c7cf8e0590d92aa32758c2983fc49387d18f7ad
This commit is contained in:
@@ -24,6 +24,21 @@
|
||||
android:layout_width="match_parent"
|
||||
android:background="@drawable/system_bar_background">
|
||||
|
||||
<com.android.systemui.CornerHandleView
|
||||
android:id="@+id/assist_hint_left"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="left|bottom"
|
||||
android:rotation="270"
|
||||
android:visibility="gone"/>
|
||||
<com.android.systemui.CornerHandleView
|
||||
android:id="@+id/assist_hint_right"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="right|bottom"
|
||||
android:rotation="180"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<com.android.systemui.statusbar.phone.NavigationBarInflaterView
|
||||
android:id="@+id/navigation_inflater"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -18,18 +18,6 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.android.systemui.CornerHandleView
|
||||
android:id="@+id/assist_hint_left"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="left|top"
|
||||
android:visibility="gone"/>
|
||||
<com.android.systemui.CornerHandleView
|
||||
android:id="@+id/assist_hint_right"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_gravity="right|bottom"
|
||||
android:visibility="gone"/>
|
||||
<ImageView
|
||||
android:id="@+id/left"
|
||||
android:layout_width="12dp"
|
||||
|
||||
@@ -25,9 +25,6 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
|
||||
import static com.android.systemui.tuner.TunablePadding.FLAG_END;
|
||||
import static com.android.systemui.tuner.TunablePadding.FLAG_START;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.Dimension;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Fragment;
|
||||
@@ -52,7 +49,6 @@ import android.os.SystemProperties;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.view.DisplayCutout;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.Gravity;
|
||||
@@ -64,9 +60,6 @@ import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
@@ -78,10 +71,7 @@ import com.android.systemui.fragments.FragmentHostManager;
|
||||
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
|
||||
import com.android.systemui.plugins.qs.QS;
|
||||
import com.android.systemui.qs.SecureSetting;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
|
||||
import com.android.systemui.statusbar.phone.NavigationBarTransitions;
|
||||
import com.android.systemui.statusbar.phone.NavigationModeController;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.tuner.TunablePadding;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
@@ -95,8 +85,7 @@ import java.util.List;
|
||||
* An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
|
||||
* for antialiasing and emulation purposes.
|
||||
*/
|
||||
public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
NavigationBarTransitions.DarkIntensityListener {
|
||||
public class ScreenDecorations extends SystemUI implements Tunable {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "ScreenDecorations";
|
||||
|
||||
@@ -120,15 +109,11 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
private float mDensity;
|
||||
private WindowManager mWindowManager;
|
||||
private int mRotation;
|
||||
private boolean mAssistHintVisible;
|
||||
private DisplayCutoutView mCutoutTop;
|
||||
private DisplayCutoutView mCutoutBottom;
|
||||
private SecureSetting mColorInversionSetting;
|
||||
private boolean mPendingRotationChange;
|
||||
private Handler mHandler;
|
||||
private boolean mAssistHintBlocked = false;
|
||||
private boolean mIsReceivingNavBarColor = false;
|
||||
private boolean mInGesturalMode;
|
||||
|
||||
/**
|
||||
* Converts a set of {@link Rect}s into a {@link Region}
|
||||
@@ -153,160 +138,6 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
mHandler.post(this::startOnScreenDecorationsThread);
|
||||
setupStatusBarPaddingIfNeeded();
|
||||
putComponent(ScreenDecorations.class, this);
|
||||
mInGesturalMode = QuickStepContract.isGesturalMode(
|
||||
Dependency.get(NavigationModeController.class)
|
||||
.addListener(this::handleNavigationModeChange));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void handleNavigationModeChange(int navigationMode) {
|
||||
if (!mHandler.getLooper().isCurrentThread()) {
|
||||
mHandler.post(() -> handleNavigationModeChange(navigationMode));
|
||||
return;
|
||||
}
|
||||
boolean inGesturalMode = QuickStepContract.isGesturalMode(navigationMode);
|
||||
if (mInGesturalMode != inGesturalMode) {
|
||||
mInGesturalMode = inGesturalMode;
|
||||
|
||||
if (mInGesturalMode && mOverlay == null) {
|
||||
setupDecorations();
|
||||
if (mOverlay != null) {
|
||||
updateLayoutParams();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an animator that animates the given view from start to end over durationMs. Start and
|
||||
* end represent total animation progress: 0 is the start, 1 is the end, 1.1 would be an
|
||||
* overshoot.
|
||||
*/
|
||||
Animator getHandleAnimator(View view, float start, float end, boolean isLeft, long durationMs,
|
||||
Interpolator interpolator) {
|
||||
// Note that lerp does allow overshoot, in cases where start and end are outside of [0,1].
|
||||
float scaleStart = MathUtils.lerp(2f, 1f, start);
|
||||
float scaleEnd = MathUtils.lerp(2f, 1f, end);
|
||||
Animator scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, scaleStart, scaleEnd);
|
||||
Animator scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, scaleStart, scaleEnd);
|
||||
float translationStart = MathUtils.lerp(0.2f, 0f, start);
|
||||
float translationEnd = MathUtils.lerp(0.2f, 0f, end);
|
||||
int xDirection = isLeft ? -1 : 1;
|
||||
Animator translateX = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
|
||||
xDirection * translationStart * view.getWidth(),
|
||||
xDirection * translationEnd * view.getWidth());
|
||||
Animator translateY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
|
||||
translationStart * view.getHeight(), translationEnd * view.getHeight());
|
||||
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.play(scaleX).with(scaleY);
|
||||
set.play(scaleX).with(translateX);
|
||||
set.play(scaleX).with(translateY);
|
||||
set.setDuration(durationMs);
|
||||
set.setInterpolator(interpolator);
|
||||
return set;
|
||||
}
|
||||
|
||||
private void fade(View view, boolean fadeIn, boolean isLeft) {
|
||||
if (fadeIn) {
|
||||
view.animate().cancel();
|
||||
view.setAlpha(1f);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
|
||||
// A piecewise spring-like interpolation.
|
||||
// End value in one animator call must match the start value in the next, otherwise
|
||||
// there will be a discontinuity.
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
Animator first = getHandleAnimator(view, 0, 1.1f, isLeft, 750,
|
||||
new PathInterpolator(0, 0.45f, .67f, 1f));
|
||||
Interpolator secondInterpolator = new PathInterpolator(0.33f, 0, 0.67f, 1f);
|
||||
Animator second = getHandleAnimator(view, 1.1f, 0.97f, isLeft, 400,
|
||||
secondInterpolator);
|
||||
Animator third = getHandleAnimator(view, 0.97f, 1.02f, isLeft, 400,
|
||||
secondInterpolator);
|
||||
Animator fourth = getHandleAnimator(view, 1.02f, 1f, isLeft, 400,
|
||||
secondInterpolator);
|
||||
anim.play(first).before(second);
|
||||
anim.play(second).before(third);
|
||||
anim.play(third).before(fourth);
|
||||
anim.start();
|
||||
} else {
|
||||
view.animate().cancel();
|
||||
view.animate()
|
||||
.setInterpolator(new AccelerateInterpolator(1.5f))
|
||||
.setDuration(250)
|
||||
.alpha(0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the visibility of the assist gesture handles.
|
||||
*
|
||||
* @param visible whether the handles should be shown
|
||||
*/
|
||||
public void setAssistHintVisible(boolean visible) {
|
||||
if (!mHandler.getLooper().isCurrentThread()) {
|
||||
mHandler.post(() -> setAssistHintVisible(visible));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAssistHintBlocked && visible) {
|
||||
if (VERBOSE) {
|
||||
Log.v(TAG, "Assist hint blocked, cannot make it visible");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mOverlay == null || mBottomOverlay == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAssistHintVisible != visible) {
|
||||
mAssistHintVisible = visible;
|
||||
|
||||
CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
|
||||
CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
|
||||
CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
|
||||
R.id.assist_hint_left);
|
||||
CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
|
||||
R.id.assist_hint_right);
|
||||
|
||||
switch (mRotation) {
|
||||
case RotationUtils.ROTATION_NONE:
|
||||
fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
|
||||
fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
|
||||
break;
|
||||
case RotationUtils.ROTATION_LANDSCAPE:
|
||||
fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
|
||||
fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
|
||||
break;
|
||||
case RotationUtils.ROTATION_SEASCAPE:
|
||||
fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
|
||||
fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
|
||||
break;
|
||||
case RotationUtils.ROTATION_UPSIDE_DOWN:
|
||||
fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
|
||||
fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateWindowVisibilities();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the assist hint from becoming visible even if `mAssistHintVisible` is true.
|
||||
*/
|
||||
public void setAssistHintBlocked(boolean blocked) {
|
||||
if (!mHandler.getLooper().isCurrentThread()) {
|
||||
mHandler.post(() -> setAssistHintBlocked(blocked));
|
||||
return;
|
||||
}
|
||||
|
||||
mAssistHintBlocked = blocked;
|
||||
if (mAssistHintVisible && mAssistHintBlocked) {
|
||||
hideAssistHandles();
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -316,15 +147,11 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
return thread.getThreadHandler();
|
||||
}
|
||||
|
||||
private boolean shouldHostHandles() {
|
||||
return mInGesturalMode;
|
||||
}
|
||||
|
||||
private void startOnScreenDecorationsThread() {
|
||||
mRotation = RotationUtils.getExactRotation(mContext);
|
||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||
updateRoundedCornerRadii();
|
||||
if (hasRoundedCorners() || shouldDrawCutout() || shouldHostHandles()) {
|
||||
if (hasRoundedCorners() || shouldDrawCutout()) {
|
||||
setupDecorations();
|
||||
}
|
||||
|
||||
@@ -501,26 +328,10 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
if (mOverlay != null) {
|
||||
updateLayoutParams();
|
||||
updateViews();
|
||||
if (mAssistHintVisible) {
|
||||
// If assist handles are visible, hide them without animation and then make them
|
||||
// show once again (with corrected rotation).
|
||||
hideAssistHandles();
|
||||
setAssistHintVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideAssistHandles() {
|
||||
if (mOverlay != null && mBottomOverlay != null) {
|
||||
mOverlay.findViewById(R.id.assist_hint_left).setVisibility(View.GONE);
|
||||
mOverlay.findViewById(R.id.assist_hint_right).setVisibility(View.GONE);
|
||||
mBottomOverlay.findViewById(R.id.assist_hint_left).setVisibility(View.GONE);
|
||||
mBottomOverlay.findViewById(R.id.assist_hint_right).setVisibility(View.GONE);
|
||||
mAssistHintVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRoundedCornerRadii() {
|
||||
final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.rounded_corner_radius);
|
||||
@@ -569,52 +380,12 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
updateView(bottomRight, Gravity.TOP | Gravity.LEFT, 0);
|
||||
}
|
||||
|
||||
updateAssistantHandleViews();
|
||||
mCutoutTop.setRotation(mRotation);
|
||||
mCutoutBottom.setRotation(mRotation);
|
||||
|
||||
updateWindowVisibilities();
|
||||
}
|
||||
|
||||
private void updateAssistantHandleViews() {
|
||||
View assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
|
||||
View assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
|
||||
View assistHintBottomLeft = mBottomOverlay.findViewById(R.id.assist_hint_left);
|
||||
View assistHintBottomRight = mBottomOverlay.findViewById(R.id.assist_hint_right);
|
||||
|
||||
final int assistHintVisibility = mAssistHintVisible ? View.VISIBLE : View.INVISIBLE;
|
||||
|
||||
if (mRotation == RotationUtils.ROTATION_NONE) {
|
||||
assistHintTopLeft.setVisibility(View.GONE);
|
||||
assistHintTopRight.setVisibility(View.GONE);
|
||||
assistHintBottomLeft.setVisibility(assistHintVisibility);
|
||||
assistHintBottomRight.setVisibility(assistHintVisibility);
|
||||
updateView(assistHintBottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
|
||||
updateView(assistHintBottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
|
||||
} else if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
|
||||
assistHintTopLeft.setVisibility(View.GONE);
|
||||
assistHintTopRight.setVisibility(assistHintVisibility);
|
||||
assistHintBottomLeft.setVisibility(View.GONE);
|
||||
assistHintBottomRight.setVisibility(assistHintVisibility);
|
||||
updateView(assistHintTopRight, Gravity.BOTTOM | Gravity.LEFT, 270);
|
||||
updateView(assistHintBottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
|
||||
} else if (mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
|
||||
assistHintTopLeft.setVisibility(assistHintVisibility);
|
||||
assistHintTopRight.setVisibility(assistHintVisibility);
|
||||
assistHintBottomLeft.setVisibility(View.GONE);
|
||||
assistHintBottomRight.setVisibility(View.GONE);
|
||||
updateView(assistHintTopLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
|
||||
updateView(assistHintTopRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
|
||||
} else if (mRotation == RotationUtils.ROTATION_SEASCAPE) {
|
||||
assistHintTopLeft.setVisibility(assistHintVisibility);
|
||||
assistHintTopRight.setVisibility(View.GONE);
|
||||
assistHintBottomLeft.setVisibility(assistHintVisibility);
|
||||
assistHintBottomRight.setVisibility(View.GONE);
|
||||
updateView(assistHintTopLeft, Gravity.BOTTOM | Gravity.RIGHT, 180);
|
||||
updateView(assistHintBottomLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateView(View v, int gravity, int rotation) {
|
||||
((FrameLayout.LayoutParams) v.getLayoutParams()).gravity = gravity;
|
||||
v.setRotation(rotation);
|
||||
@@ -629,10 +400,7 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
boolean visibleForCutout = shouldDrawCutout()
|
||||
&& overlay.findViewById(R.id.display_cutout).getVisibility() == View.VISIBLE;
|
||||
boolean visibleForRoundedCorners = hasRoundedCorners();
|
||||
boolean visibleForHandles = overlay.findViewById(R.id.assist_hint_left).getVisibility()
|
||||
== View.VISIBLE || overlay.findViewById(R.id.assist_hint_right).getVisibility()
|
||||
== View.VISIBLE;
|
||||
overlay.setVisibility(visibleForCutout || visibleForRoundedCorners || visibleForHandles
|
||||
overlay.setVisibility(visibleForCutout || visibleForRoundedCorners
|
||||
? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
@@ -766,31 +534,6 @@ public class ScreenDecorations extends SystemUI implements Tunable,
|
||||
view.setLayoutParams(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDarkIntensity(float darkIntensity) {
|
||||
if (!mHandler.getLooper().isCurrentThread()) {
|
||||
mHandler.post(() -> onDarkIntensity(darkIntensity));
|
||||
return;
|
||||
}
|
||||
if (mOverlay != null) {
|
||||
CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
|
||||
CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
|
||||
|
||||
assistHintTopLeft.updateDarkness(darkIntensity);
|
||||
assistHintTopRight.updateDarkness(darkIntensity);
|
||||
}
|
||||
|
||||
if (mBottomOverlay != null) {
|
||||
CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
|
||||
R.id.assist_hint_left);
|
||||
CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
|
||||
R.id.assist_hint_right);
|
||||
|
||||
assistHintBottomLeft.updateDarkness(darkIntensity);
|
||||
assistHintBottomRight.updateDarkness(darkIntensity);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class TunablePaddingTagListener implements FragmentListener {
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.DumpController;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.ScreenDecorations;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.statusbar.phone.NavigationModeController;
|
||||
|
||||
@@ -71,7 +70,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
private final Handler mHandler;
|
||||
private final Runnable mHideHandles = this::hideHandles;
|
||||
private final Runnable mShowAndGo = this::showAndGoInternal;
|
||||
private final Provider<ScreenDecorations> mScreenDecorations;
|
||||
private final Provider<AssistHandleViewController> mAssistHandleViewController;
|
||||
private final PhenotypeHelper mPhenotypeHelper;
|
||||
private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap;
|
||||
|
||||
@@ -90,7 +89,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
Context context,
|
||||
AssistUtils assistUtils,
|
||||
@Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
|
||||
Provider<ScreenDecorations> screenDecorations,
|
||||
Provider<AssistHandleViewController> assistHandleViewController,
|
||||
PhenotypeHelper phenotypeHelper,
|
||||
Map<AssistHandleBehavior, BehaviorController> behaviorMap,
|
||||
NavigationModeController navigationModeController,
|
||||
@@ -98,7 +97,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
mContext = context;
|
||||
mAssistUtils = assistUtils;
|
||||
mHandler = handler;
|
||||
mScreenDecorations = screenDecorations;
|
||||
mAssistHandleViewController = assistHandleViewController;
|
||||
mPhenotypeHelper = phenotypeHelper;
|
||||
mBehaviorMap = behaviorMap;
|
||||
|
||||
@@ -229,12 +228,13 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
}
|
||||
|
||||
if (handlesUnblocked(ignoreThreshold)) {
|
||||
ScreenDecorations screenDecorations = mScreenDecorations.get();
|
||||
if (screenDecorations == null) {
|
||||
Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable");
|
||||
mHandlesShowing = true;
|
||||
AssistHandleViewController assistHandleViewController =
|
||||
mAssistHandleViewController.get();
|
||||
if (assistHandleViewController == null) {
|
||||
Log.w(TAG, "Couldn't show handles, AssistHandleViewController unavailable");
|
||||
} else {
|
||||
mHandlesShowing = true;
|
||||
screenDecorations.setAssistHintVisible(true);
|
||||
assistHandleViewController.setAssistHintVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -244,13 +244,14 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
return;
|
||||
}
|
||||
|
||||
ScreenDecorations screenDecorations = mScreenDecorations.get();
|
||||
if (screenDecorations == null) {
|
||||
Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable");
|
||||
mHandlesShowing = false;
|
||||
mHandlesLastHiddenAt = SystemClock.elapsedRealtime();
|
||||
AssistHandleViewController assistHandleViewController =
|
||||
mAssistHandleViewController.get();
|
||||
if (assistHandleViewController == null) {
|
||||
Log.w(TAG, "Couldn't show handles, AssistHandleViewController unavailable");
|
||||
} else {
|
||||
mHandlesShowing = false;
|
||||
mHandlesLastHiddenAt = SystemClock.elapsedRealtime();
|
||||
screenDecorations.setAssistHintVisible(false);
|
||||
assistHandleViewController.setAssistHintVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.assist;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.CornerHandleView;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.phone.NavigationBarTransitions;
|
||||
|
||||
/**
|
||||
* A class for managing Assistant handle show, hide and animation.
|
||||
*/
|
||||
public class AssistHandleViewController implements NavigationBarTransitions.DarkIntensityListener {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final String TAG = "AssistHandleViewController";
|
||||
|
||||
private Handler mHandler;
|
||||
private CornerHandleView mAssistHintLeft;
|
||||
private CornerHandleView mAssistHintRight;
|
||||
|
||||
@VisibleForTesting
|
||||
boolean mAssistHintVisible;
|
||||
@VisibleForTesting
|
||||
boolean mAssistHintBlocked = false;
|
||||
|
||||
public AssistHandleViewController(Handler handler, View navBar) {
|
||||
mHandler = handler;
|
||||
mAssistHintLeft = navBar.findViewById(R.id.assist_hint_left);
|
||||
mAssistHintRight = navBar.findViewById(R.id.assist_hint_right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDarkIntensity(float darkIntensity) {
|
||||
mAssistHintLeft.updateDarkness(darkIntensity);
|
||||
mAssistHintRight.updateDarkness(darkIntensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the visibility of the assist gesture handles.
|
||||
*
|
||||
* @param visible whether the handles should be shown
|
||||
*/
|
||||
public void setAssistHintVisible(boolean visible) {
|
||||
if (!mHandler.getLooper().isCurrentThread()) {
|
||||
mHandler.post(() -> setAssistHintVisible(visible));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAssistHintBlocked && visible) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "Assist hint blocked, cannot make it visible");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAssistHintVisible != visible) {
|
||||
mAssistHintVisible = visible;
|
||||
fade(mAssistHintLeft, mAssistHintVisible, /* isLeft = */ true);
|
||||
fade(mAssistHintRight, mAssistHintVisible, /* isLeft = */ false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the assist hint from becoming visible even if `mAssistHintVisible` is true.
|
||||
*/
|
||||
public void setAssistHintBlocked(boolean blocked) {
|
||||
if (!mHandler.getLooper().isCurrentThread()) {
|
||||
mHandler.post(() -> setAssistHintBlocked(blocked));
|
||||
return;
|
||||
}
|
||||
|
||||
mAssistHintBlocked = blocked;
|
||||
if (mAssistHintVisible && mAssistHintBlocked) {
|
||||
hideAssistHandles();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideAssistHandles() {
|
||||
mAssistHintLeft.setVisibility(View.GONE);
|
||||
mAssistHintRight.setVisibility(View.GONE);
|
||||
mAssistHintVisible = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an animator that animates the given view from start to end over durationMs. Start and
|
||||
* end represent total animation progress: 0 is the start, 1 is the end, 1.1 would be an
|
||||
* overshoot.
|
||||
*/
|
||||
Animator getHandleAnimator(View view, float start, float end, boolean isLeft, long durationMs,
|
||||
Interpolator interpolator) {
|
||||
// Note that lerp does allow overshoot, in cases where start and end are outside of [0,1].
|
||||
float scaleStart = MathUtils.lerp(2f, 1f, start);
|
||||
float scaleEnd = MathUtils.lerp(2f, 1f, end);
|
||||
Animator scaleX = ObjectAnimator.ofFloat(view, View.SCALE_X, scaleStart, scaleEnd);
|
||||
Animator scaleY = ObjectAnimator.ofFloat(view, View.SCALE_Y, scaleStart, scaleEnd);
|
||||
float translationStart = MathUtils.lerp(0.2f, 0f, start);
|
||||
float translationEnd = MathUtils.lerp(0.2f, 0f, end);
|
||||
int xDirection = isLeft ? -1 : 1;
|
||||
Animator translateX = ObjectAnimator.ofFloat(view, View.TRANSLATION_X,
|
||||
xDirection * translationStart * view.getWidth(),
|
||||
xDirection * translationEnd * view.getWidth());
|
||||
Animator translateY = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
|
||||
translationStart * view.getHeight(), translationEnd * view.getHeight());
|
||||
|
||||
AnimatorSet set = new AnimatorSet();
|
||||
set.play(scaleX).with(scaleY);
|
||||
set.play(scaleX).with(translateX);
|
||||
set.play(scaleX).with(translateY);
|
||||
set.setDuration(durationMs);
|
||||
set.setInterpolator(interpolator);
|
||||
return set;
|
||||
}
|
||||
|
||||
private void fade(View view, boolean fadeIn, boolean isLeft) {
|
||||
if (fadeIn) {
|
||||
view.animate().cancel();
|
||||
view.setAlpha(1f);
|
||||
view.setVisibility(View.VISIBLE);
|
||||
|
||||
// A piecewise spring-like interpolation.
|
||||
// End value in one animator call must match the start value in the next, otherwise
|
||||
// there will be a discontinuity.
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
Animator first = getHandleAnimator(view, 0, 1.1f, isLeft, 750,
|
||||
new PathInterpolator(0, 0.45f, .67f, 1f));
|
||||
Interpolator secondInterpolator = new PathInterpolator(0.33f, 0, 0.67f, 1f);
|
||||
Animator second = getHandleAnimator(view, 1.1f, 0.97f, isLeft, 400,
|
||||
secondInterpolator);
|
||||
Animator third = getHandleAnimator(view, 0.97f, 1.02f, isLeft, 400,
|
||||
secondInterpolator);
|
||||
Animator fourth = getHandleAnimator(view, 1.02f, 1f, isLeft, 400,
|
||||
secondInterpolator);
|
||||
anim.play(first).before(second);
|
||||
anim.play(second).before(third);
|
||||
anim.play(third).before(fourth);
|
||||
anim.start();
|
||||
} else {
|
||||
view.animate().cancel();
|
||||
view.animate()
|
||||
.setInterpolator(new AccelerateInterpolator(1.5f))
|
||||
.setDuration(250)
|
||||
.alpha(0f);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,7 @@ import android.os.SystemClock;
|
||||
import androidx.slice.Clock;
|
||||
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.systemui.ScreenDecorations;
|
||||
import com.android.systemui.SysUiServiceProvider;
|
||||
import com.android.systemui.statusbar.NavigationBarController;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
@@ -69,8 +68,9 @@ public abstract class AssistModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
static ScreenDecorations provideScreenDecorations(Context context) {
|
||||
return SysUiServiceProvider.getComponent(context, ScreenDecorations.class);
|
||||
static AssistHandleViewController provideAssistHandleViewController(
|
||||
NavigationBarController navigationBarController) {
|
||||
return navigationBarController.getAssistHandlerViewController();
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
@@ -36,9 +36,9 @@ import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.ScreenDecorations;
|
||||
import com.android.systemui.SysUiServiceProvider;
|
||||
import com.android.systemui.assist.AssistHandleViewController;
|
||||
import com.android.systemui.assist.AssistManager;
|
||||
import com.android.systemui.statusbar.NavigationBarController;
|
||||
|
||||
/**
|
||||
* Default UiController implementation. Shows white edge lights along the bottom of the phone,
|
||||
@@ -144,9 +144,11 @@ public class DefaultUiController implements AssistManager.UiController {
|
||||
}
|
||||
|
||||
private void updateAssistHandleVisibility() {
|
||||
ScreenDecorations decorations = SysUiServiceProvider.getComponent(mRoot.getContext(),
|
||||
ScreenDecorations.class);
|
||||
decorations.setAssistHintBlocked(mInvocationInProgress);
|
||||
AssistHandleViewController controller = Dependency.get(NavigationBarController.class)
|
||||
.getAssistHandlerViewController();
|
||||
if (controller != null) {
|
||||
controller.setAssistHintBlocked(mInvocationInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
private void attach() {
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.statusbar.RegisterStatusBarResult;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.assist.AssistHandleViewController;
|
||||
import com.android.systemui.plugins.DarkIconDispatcher;
|
||||
import com.android.systemui.statusbar.CommandQueue.Callbacks;
|
||||
import com.android.systemui.statusbar.phone.AutoHideController;
|
||||
@@ -233,4 +234,9 @@ public class NavigationBarController implements Callbacks {
|
||||
public NavigationBarFragment getDefaultNavigationBarFragment() {
|
||||
return mNavigationBars.get(DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
/** @return {@link AssistHandleViewController} (only on the default display). */
|
||||
public AssistHandleViewController getAssistHandlerViewController() {
|
||||
return getDefaultNavigationBarFragment().getAssistHandlerViewController();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.ScreenDecorations;
|
||||
import com.android.systemui.SysUiServiceProvider;
|
||||
import com.android.systemui.assist.AssistHandleViewController;
|
||||
import com.android.systemui.assist.AssistManager;
|
||||
import com.android.systemui.fragments.FragmentHostManager;
|
||||
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
|
||||
@@ -174,7 +174,10 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
|
||||
public int mDisplayId;
|
||||
private boolean mIsOnDefaultDisplay;
|
||||
public boolean mHomeBlockedThisTouch;
|
||||
private ScreenDecorations mScreenDecorations;
|
||||
|
||||
/** Only for default display */
|
||||
@Nullable
|
||||
private AssistHandleViewController mAssistHandlerViewController;
|
||||
|
||||
private Handler mHandler = Dependency.get(Dependency.MAIN_HANDLER);
|
||||
|
||||
@@ -357,17 +360,22 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
|
||||
mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
|
||||
}
|
||||
setDisabled2Flags(mDisabledFlags2);
|
||||
|
||||
mScreenDecorations = SysUiServiceProvider.getComponent(getContext(),
|
||||
ScreenDecorations.class);
|
||||
getBarTransitions().addDarkIntensityListener(mScreenDecorations);
|
||||
if (mIsOnDefaultDisplay) {
|
||||
mAssistHandlerViewController =
|
||||
new AssistHandleViewController(mHandler, mNavigationBarView);
|
||||
getBarTransitions().addDarkIntensityListener(mAssistHandlerViewController);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (mNavigationBarView != null) {
|
||||
mNavigationBarView.getBarTransitions().removeDarkIntensityListener(mScreenDecorations);
|
||||
if (mIsOnDefaultDisplay) {
|
||||
mNavigationBarView.getBarTransitions()
|
||||
.removeDarkIntensityListener(mAssistHandlerViewController);
|
||||
mAssistHandlerViewController = null;
|
||||
}
|
||||
mNavigationBarView.getBarTransitions().destroy();
|
||||
mNavigationBarView.getLightTransitionsController().destroy(getContext());
|
||||
}
|
||||
@@ -1019,6 +1027,11 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
|
||||
delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AssistHandleViewController getAssistHandlerViewController() {
|
||||
return mAssistHandlerViewController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs transitions on navigation bar.
|
||||
*
|
||||
|
||||
@@ -45,7 +45,6 @@ import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -53,7 +52,6 @@ import com.android.systemui.R.dimen;
|
||||
import com.android.systemui.ScreenDecorations.TunablePaddingTagListener;
|
||||
import com.android.systemui.fragments.FragmentHostManager;
|
||||
import com.android.systemui.fragments.FragmentService;
|
||||
import com.android.systemui.statusbar.phone.NavigationModeController;
|
||||
import com.android.systemui.statusbar.phone.StatusBar;
|
||||
import com.android.systemui.statusbar.phone.StatusBarWindowView;
|
||||
import com.android.systemui.tuner.TunablePadding;
|
||||
@@ -80,7 +78,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
private TunerService mTunerService;
|
||||
private StatusBarWindowView mView;
|
||||
private TunablePaddingService mTunablePaddingService;
|
||||
private NavigationModeController mNavigationModeController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -90,8 +87,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
mTunablePaddingService = mDependency.injectMockDependency(TunablePaddingService.class);
|
||||
mTunerService = mDependency.injectMockDependency(TunerService.class);
|
||||
mFragmentService = mDependency.injectMockDependency(FragmentService.class);
|
||||
mNavigationModeController = mDependency.injectMockDependency(
|
||||
NavigationModeController.class);
|
||||
|
||||
mStatusBar = mock(StatusBar.class);
|
||||
mWindowManager = mock(WindowManager.class);
|
||||
@@ -212,54 +207,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
|
||||
verify(mWindowManager, times(2)).addView(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAssistHandles() {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.dimen.rounded_corner_radius, 0);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.dimen.rounded_corner_radius_top, 0);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
|
||||
mContext.getOrCreateTestableResources()
|
||||
.addOverride(dimen.rounded_corner_content_padding, 0);
|
||||
when(mNavigationModeController.addListener(any())).thenReturn(
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
|
||||
|
||||
mScreenDecorations.start();
|
||||
|
||||
// Add 2 windows for rounded corners (top and bottom).
|
||||
verify(mWindowManager, times(2)).addView(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelayedAssistHandles() {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.dimen.rounded_corner_radius, 0);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.dimen.rounded_corner_radius_top, 0);
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.dimen.rounded_corner_radius_bottom, 0);
|
||||
mContext.getOrCreateTestableResources()
|
||||
.addOverride(dimen.rounded_corner_content_padding, 0);
|
||||
when(mNavigationModeController.addListener(any())).thenReturn(
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON);
|
||||
|
||||
mScreenDecorations.start();
|
||||
|
||||
// No handles and no corners
|
||||
verify(mWindowManager, never()).addView(any(), any());
|
||||
|
||||
mScreenDecorations.handleNavigationModeChange(
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
|
||||
|
||||
// Add 2 windows for rounded corners (top and bottom).
|
||||
verify(mWindowManager, times(2)).addView(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasRoundedCornerOverlayFlagSet() {
|
||||
assertThat(mScreenDecorations.getWindowLayoutParams().privateFlags
|
||||
|
||||
@@ -38,7 +38,6 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.internal.app.AssistUtils;
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.systemui.DumpController;
|
||||
import com.android.systemui.ScreenDecorations;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.recents.OverviewProxyService;
|
||||
@@ -64,7 +63,6 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
|
||||
private AssistHandleBehaviorController mAssistHandleBehaviorController;
|
||||
|
||||
@Mock private ScreenDecorations mMockScreenDecorations;
|
||||
@Mock private AssistUtils mMockAssistUtils;
|
||||
@Mock private Handler mMockHandler;
|
||||
@Mock private PhenotypeHelper mMockPhenotypeHelper;
|
||||
@@ -74,6 +72,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
@Mock private AssistHandleBehaviorController.BehaviorController mMockTestBehavior;
|
||||
@Mock private NavigationModeController mMockNavigationModeController;
|
||||
@Mock private DumpController mMockDumpController;
|
||||
@Mock private AssistHandleViewController mMockAssistHandleViewController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -97,7 +96,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
mContext,
|
||||
mMockAssistUtils,
|
||||
mMockHandler,
|
||||
() -> mMockScreenDecorations,
|
||||
() -> mMockAssistHandleViewController,
|
||||
mMockPhenotypeHelper,
|
||||
behaviorMap,
|
||||
mMockNavigationModeController,
|
||||
@@ -114,14 +113,14 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.hide();
|
||||
|
||||
// Assert
|
||||
verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -129,13 +128,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.hide();
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,14 +142,14 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
|
||||
// Assert
|
||||
verify(mMockScreenDecorations).setAssistHintVisible(true);
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verify(mMockAssistHandleViewController).setAssistHintVisible(true);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -158,13 +157,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,13 +171,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -186,15 +185,15 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGo();
|
||||
|
||||
// Assert
|
||||
InOrder inOrder = inOrder(mMockScreenDecorations);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
InOrder inOrder = inOrder(mMockAssistHandleViewController);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(true);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
}
|
||||
|
||||
@@ -203,14 +202,14 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGo();
|
||||
|
||||
// Assert
|
||||
verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -221,13 +220,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS),
|
||||
anyLong())).thenReturn(10000L);
|
||||
mAssistHandleBehaviorController.showAndGo();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGo();
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -235,13 +234,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGo();
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -249,15 +248,15 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
|
||||
|
||||
// Assert
|
||||
InOrder inOrder = inOrder(mMockScreenDecorations);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
InOrder inOrder = inOrder(mMockAssistHandleViewController);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(true);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
}
|
||||
|
||||
@@ -266,14 +265,14 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
|
||||
|
||||
// Assert
|
||||
verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -281,16 +280,16 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
|
||||
mAssistHandleBehaviorController.showAndStay();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGoDelayed(1000, true);
|
||||
|
||||
// Assert
|
||||
InOrder inOrder = inOrder(mMockScreenDecorations);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true);
|
||||
inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false);
|
||||
InOrder inOrder = inOrder(mMockAssistHandleViewController);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(true);
|
||||
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
|
||||
inOrder.verifyNoMoreInteractions();
|
||||
}
|
||||
|
||||
@@ -302,13 +301,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS),
|
||||
anyLong())).thenReturn(10000L);
|
||||
mAssistHandleBehaviorController.showAndGo();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -316,13 +315,13 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
|
||||
// Arrange
|
||||
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
|
||||
mAssistHandleBehaviorController.hide();
|
||||
reset(mMockScreenDecorations);
|
||||
reset(mMockAssistHandleViewController);
|
||||
|
||||
// Act
|
||||
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
|
||||
|
||||
// Assert
|
||||
verifyNoMoreInteractions(mMockScreenDecorations);
|
||||
verifyNoMoreInteractions(mMockAssistHandleViewController);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.assist;
|
||||
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.view.View;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.CornerHandleView;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@RunWithLooper
|
||||
public class AssistHandleViewControllerTest extends SysuiTestCase {
|
||||
|
||||
private AssistHandleViewController mAssistHandleViewController;
|
||||
|
||||
@Mock private Handler mMockHandler;
|
||||
@Mock private Looper mMockLooper;
|
||||
@Mock private View mMockBarView;
|
||||
@Mock private CornerHandleView mMockAssistHint;
|
||||
@Mock private ViewPropertyAnimator mMockAnimator;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mMockBarView.findViewById(anyInt())).thenReturn(mMockAssistHint);
|
||||
when(mMockAssistHint.animate()).thenReturn(mMockAnimator);
|
||||
when(mMockAnimator.setInterpolator(any())).thenReturn(mMockAnimator);
|
||||
when(mMockAnimator.setDuration(anyLong())).thenReturn(mMockAnimator);
|
||||
doNothing().when(mMockAnimator).cancel();
|
||||
when(mMockHandler.getLooper()).thenReturn(mMockLooper);
|
||||
when(mMockLooper.isCurrentThread()).thenReturn(true);
|
||||
|
||||
mAssistHandleViewController = new AssistHandleViewController(mMockHandler, mMockBarView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetVisibleWithoutBlocked() {
|
||||
// Act
|
||||
mAssistHandleViewController.setAssistHintVisible(true);
|
||||
|
||||
// Assert
|
||||
assertTrue(mAssistHandleViewController.mAssistHintVisible);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetInvisibleWithoutBlocked() {
|
||||
// Arrange
|
||||
mAssistHandleViewController.setAssistHintVisible(true);
|
||||
|
||||
// Act
|
||||
mAssistHandleViewController.setAssistHintVisible(false);
|
||||
|
||||
// Assert
|
||||
assertFalse(mAssistHandleViewController.mAssistHintVisible);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetVisibleWithBlocked() {
|
||||
// Act
|
||||
mAssistHandleViewController.setAssistHintBlocked(true);
|
||||
mAssistHandleViewController.setAssistHintVisible(true);
|
||||
|
||||
// Assert
|
||||
assertFalse(mAssistHandleViewController.mAssistHintVisible);
|
||||
assertTrue(mAssistHandleViewController.mAssistHintBlocked);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user