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:
shawnlin
2019-09-13 14:13:13 +08:00
parent aeb356ca84
commit 87af538d38
12 changed files with 388 additions and 398 deletions

View File

@@ -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"

View File

@@ -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"

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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() {

View File

@@ -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();
}
}

View File

@@ -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.
*

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}