Merge "Remove Assistant corner handles" into sc-dev

This commit is contained in:
Govinda Wasserman
2021-03-31 15:49:18 +00:00
committed by Android (Google) Code Review
22 changed files with 4 additions and 2748 deletions

View File

@@ -19,27 +19,11 @@
<com.android.systemui.navigationbar.NavigationBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/navigation_bar_view"
android:layout_height="match_parent"
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.navigationbar.NavigationBarInflaterView
android:id="@+id/navigation_inflater"
android:layout_width="match_parent"

View File

@@ -1,191 +0,0 @@
/*
* 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;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.ContextThemeWrapper;
import android.view.View;
import com.android.settingslib.Utils;
/**
* CornerHandleView draws an inset arc intended to be displayed within the screen decoration
* corners.
*/
public class CornerHandleView extends View {
private static final float STROKE_DP_LARGE = 2f;
private static final float STROKE_DP_SMALL = 1.95f;
// Radius to use if none is available.
private static final int FALLBACK_RADIUS_DP = 15;
private static final float MARGIN_DP = 8;
private static final int MAX_ARC_DEGREES = 90;
// Arc length along the phone's perimeter used to measure the desired angle.
private static final float ARC_LENGTH_DP = 31f;
private Paint mPaint;
private int mLightColor;
private int mDarkColor;
private Path mPath;
private boolean mRequiresInvalidate;
public CornerHandleView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(getStrokePx());
final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
Context lightContext = new ContextThemeWrapper(mContext, dualToneLightTheme);
Context darkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme);
mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);
updatePath();
}
@Override
public void setAlpha(float alpha) {
super.setAlpha(alpha);
if (alpha > 0f && mRequiresInvalidate) {
mRequiresInvalidate = false;
invalidate();
}
}
private void updatePath() {
mPath = new Path();
float marginPx = getMarginPx();
float radiusPx = getInnerRadiusPx();
float halfStrokePx = getStrokePx() / 2f;
float angle = getAngle();
float startAngle = 180 + ((90 - angle) / 2);
RectF circle = new RectF(marginPx + halfStrokePx,
marginPx + halfStrokePx,
marginPx + 2 * radiusPx - halfStrokePx,
marginPx + 2 * radiusPx - halfStrokePx);
if (angle >= 90f) {
float innerCircumferenceDp = convertPixelToDp(radiusPx * 2 * (float) Math.PI,
mContext);
float arcDp = innerCircumferenceDp * getAngle() / 360f;
// Add additional "arms" to the two ends of the arc. The length computation is
// hand-tuned.
float lineLengthPx = convertDpToPixel((ARC_LENGTH_DP - arcDp - MARGIN_DP) / 2,
mContext);
mPath.moveTo(marginPx + halfStrokePx, marginPx + radiusPx + lineLengthPx);
mPath.lineTo(marginPx + halfStrokePx, marginPx + radiusPx);
mPath.arcTo(circle, startAngle, angle);
mPath.moveTo(marginPx + radiusPx, marginPx + halfStrokePx);
mPath.lineTo(marginPx + radiusPx + lineLengthPx, marginPx + halfStrokePx);
} else {
mPath.arcTo(circle, startAngle, angle);
}
}
/**
* Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
* appropriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
// Handle color is same as home handle color.
int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
mLightColor, mDarkColor);
if (mPaint.getColor() != color) {
mPaint.setColor(color);
if (getVisibility() == VISIBLE && getAlpha() > 0) {
invalidate();
} else {
// If we are currently invisible, then invalidate when we are next made visible
mRequiresInvalidate = true;
}
}
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(mPath, mPaint);
}
private static float convertDpToPixel(float dp, Context context) {
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi
/ DisplayMetrics.DENSITY_DEFAULT);
}
private static float convertPixelToDp(float px, Context context) {
return px * DisplayMetrics.DENSITY_DEFAULT
/ ((float) context.getResources().getDisplayMetrics().densityDpi);
}
private float getAngle() {
// Measure a length of ARC_LENGTH_DP along the *screen's* perimeter, get the angle and cap
// it at 90.
float circumferenceDp = convertPixelToDp((
getOuterRadiusPx()) * 2 * (float) Math.PI, mContext);
float angleDeg = (ARC_LENGTH_DP / circumferenceDp) * 360;
if (angleDeg > MAX_ARC_DEGREES) {
angleDeg = MAX_ARC_DEGREES;
}
return angleDeg;
}
private float getMarginPx() {
return convertDpToPixel(MARGIN_DP, mContext);
}
private float getInnerRadiusPx() {
return getOuterRadiusPx() - getMarginPx();
}
private float getOuterRadiusPx() {
// Attempt to get the bottom corner radius, otherwise fall back on the generic or top
// values. If none are available, use the FALLBACK_RADIUS_DP.
int radius = getResources().getDimensionPixelSize(
com.android.systemui.R.dimen.config_rounded_mask_size_bottom);
if (radius == 0) {
radius = getResources().getDimensionPixelSize(
com.android.systemui.R.dimen.config_rounded_mask_size);
}
if (radius == 0) {
radius = getResources().getDimensionPixelSize(
com.android.systemui.R.dimen.config_rounded_mask_size_top);
}
if (radius == 0) {
radius = (int) convertDpToPixel(FALLBACK_RADIUS_DP, mContext);
}
return radius;
}
private float getStrokePx() {
// Use a slightly smaller stroke if we need to cover the full corner angle.
return convertDpToPixel((getAngle() < 90) ? STROKE_DP_LARGE : STROKE_DP_SMALL,
getContext());
}
}

View File

@@ -1,25 +0,0 @@
/*
* 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;
public enum AssistHandleBehavior {
TEST,
OFF,
LIKE_HOME,
REMINDER_EXP;
}

View File

@@ -1,336 +0,0 @@
/*
* 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 com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME;
import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.shared.system.QuickStepContract;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import dagger.Lazy;
/**
* A class for managing Assistant handle logic.
*
* Controls when visual handles for Assistant gesture affordance should be shown or hidden using an
* {@link AssistHandleBehavior}.
*/
@SysUISingleton
public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable {
private static final String TAG = "AssistHandleBehavior";
private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = 0;
private static final long DEFAULT_SHOW_AND_GO_DURATION_MS = TimeUnit.SECONDS.toMillis(3);
private static final String SETTINGS_SECURE_USER_SETUP_COMPLETE = "user_setup_complete";
/**
* This is the default behavior that will be used once the system is up. It will be set once the
* behavior dependencies are available. This ensures proper behavior lifecycle.
*/
private static final AssistHandleBehavior DEFAULT_BEHAVIOR = AssistHandleBehavior.REMINDER_EXP;
private final Context mContext;
private final AssistUtils mAssistUtils;
private final Handler mHandler;
private final Runnable mHideHandles = this::hideHandles;
private final Runnable mShowAndGo = this::showAndGoInternal;
private final Provider<AssistHandleViewController> mAssistHandleViewController;
private final DeviceConfigHelper mDeviceConfigHelper;
private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap;
private final Lazy<AccessibilityManager> mA11yManager;
private boolean mHandlesShowing = false;
private long mHandlesLastHiddenAt;
private long mShowAndGoEndsAt;
/**
* This should always be initialized as {@link AssistHandleBehavior#OFF} to ensure proper
* behavior lifecycle.
*/
private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF;
private boolean mInGesturalMode;
@Inject
AssistHandleBehaviorController(
Context context,
AssistUtils assistUtils,
@Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
Provider<AssistHandleViewController> assistHandleViewController,
DeviceConfigHelper deviceConfigHelper,
Map<AssistHandleBehavior, BehaviorController> behaviorMap,
NavigationModeController navigationModeController,
Lazy<AccessibilityManager> a11yManager,
DumpManager dumpManager) {
mContext = context;
mAssistUtils = assistUtils;
mHandler = handler;
mAssistHandleViewController = assistHandleViewController;
mDeviceConfigHelper = deviceConfigHelper;
mBehaviorMap = behaviorMap;
mA11yManager = a11yManager;
mInGesturalMode = QuickStepContract.isGesturalMode(
navigationModeController.addListener(this::handleNavigationModeChange));
setBehavior(getBehaviorMode());
mDeviceConfigHelper.addOnPropertiesChangedListener(
mHandler::post,
(properties) -> {
if (properties.getKeyset().contains(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE)) {
setBehavior(properties.getString(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null));
}
});
dumpManager.registerDumpable(TAG, this);
}
@Override // AssistHandleCallbacks
public void hide() {
clearPendingCommands();
mHandler.post(mHideHandles);
}
@Override // AssistHandleCallbacks
public void showAndGo() {
clearPendingCommands();
mHandler.post(mShowAndGo);
}
private void showAndGoInternal() {
maybeShowHandles(/* ignoreThreshold = */ false);
long showAndGoDuration = getShowAndGoDuration();
mShowAndGoEndsAt = SystemClock.elapsedRealtime() + showAndGoDuration;
mHandler.postDelayed(mHideHandles, showAndGoDuration);
}
@Override // AssistHandleCallbacks
public void showAndGoDelayed(long delayMs, boolean hideIfShowing) {
clearPendingCommands();
if (hideIfShowing) {
mHandler.post(mHideHandles);
}
mHandler.postDelayed(mShowAndGo, delayMs);
}
@Override // AssistHandleCallbacks
public void showAndStay() {
clearPendingCommands();
mHandler.post(() -> maybeShowHandles(/* ignoreThreshold = */ true));
}
public long getShowAndGoRemainingTimeMs() {
return Long.max(mShowAndGoEndsAt - SystemClock.elapsedRealtime(), 0);
}
public boolean areHandlesShowing() {
return mHandlesShowing;
}
void onAssistantGesturePerformed() {
mBehaviorMap.get(mCurrentBehavior).onAssistantGesturePerformed();
}
void onAssistHandlesRequested() {
if (mInGesturalMode) {
mBehaviorMap.get(mCurrentBehavior).onAssistHandlesRequested();
}
}
void setBehavior(AssistHandleBehavior behavior) {
if (mCurrentBehavior == behavior) {
return;
}
if (!mBehaviorMap.containsKey(behavior)) {
Log.e(TAG, "Unsupported behavior requested: " + behavior.toString());
return;
}
if (mInGesturalMode) {
mBehaviorMap.get(mCurrentBehavior).onModeDeactivated();
mBehaviorMap.get(behavior).onModeActivated(mContext, /* callbacks = */ this);
}
mCurrentBehavior = behavior;
}
private void setBehavior(@Nullable String behavior) {
try {
setBehavior(AssistHandleBehavior.valueOf(behavior));
} catch (IllegalArgumentException | NullPointerException e) {
Log.e(TAG, "Invalid behavior: " + behavior);
}
}
private boolean handlesUnblocked(boolean ignoreThreshold) {
if (!isUserSetupComplete()) {
return false;
}
long timeSinceHidden = SystemClock.elapsedRealtime() - mHandlesLastHiddenAt;
boolean notThrottled = ignoreThreshold || timeSinceHidden >= getShownFrequencyThreshold();
ComponentName assistantComponent =
mAssistUtils.getAssistComponentForUser(KeyguardUpdateMonitor.getCurrentUser());
return notThrottled && assistantComponent != null;
}
private long getShownFrequencyThreshold() {
return mDeviceConfigHelper.getLong(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS,
DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS);
}
private long getShowAndGoDuration() {
long configuredTime = mDeviceConfigHelper.getLong(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS,
DEFAULT_SHOW_AND_GO_DURATION_MS);
return mA11yManager.get().getRecommendedTimeoutMillis(
(int) configuredTime, AccessibilityManager.FLAG_CONTENT_ICONS);
}
private String getBehaviorMode() {
return mDeviceConfigHelper.getString(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE,
DEFAULT_BEHAVIOR.toString());
}
private void maybeShowHandles(boolean ignoreThreshold) {
if (mHandlesShowing) {
return;
}
if (handlesUnblocked(ignoreThreshold)) {
mHandlesShowing = true;
AssistHandleViewController assistHandleViewController =
mAssistHandleViewController.get();
if (assistHandleViewController == null) {
Log.w(TAG, "Couldn't show handles, AssistHandleViewController unavailable");
} else {
assistHandleViewController.setAssistHintVisible(true);
}
}
}
private void hideHandles() {
if (!mHandlesShowing) {
return;
}
mHandlesShowing = false;
mHandlesLastHiddenAt = SystemClock.elapsedRealtime();
AssistHandleViewController assistHandleViewController =
mAssistHandleViewController.get();
if (assistHandleViewController == null) {
Log.w(TAG, "Couldn't show handles, AssistHandleViewController unavailable");
} else {
assistHandleViewController.setAssistHintVisible(false);
}
}
private void handleNavigationModeChange(int navigationMode) {
boolean inGesturalMode = QuickStepContract.isGesturalMode(navigationMode);
if (mInGesturalMode == inGesturalMode) {
return;
}
mInGesturalMode = inGesturalMode;
if (mInGesturalMode) {
mBehaviorMap.get(mCurrentBehavior).onModeActivated(mContext, /* callbacks = */ this);
} else {
mBehaviorMap.get(mCurrentBehavior).onModeDeactivated();
hide();
}
}
private void clearPendingCommands() {
mHandler.removeCallbacks(mHideHandles);
mHandler.removeCallbacks(mShowAndGo);
mShowAndGoEndsAt = 0;
}
private boolean isUserSetupComplete() {
return Settings.Secure.getInt(
mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
}
@VisibleForTesting
void setInGesturalModeForTest(boolean inGesturalMode) {
mInGesturalMode = inGesturalMode;
}
@Override // Dumpable
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Current AssistHandleBehaviorController State:");
pw.println(" mHandlesShowing=" + mHandlesShowing);
pw.println(" mHandlesLastHiddenAt=" + mHandlesLastHiddenAt);
pw.println(" mInGesturalMode=" + mInGesturalMode);
pw.println(" Phenotype Flags:");
pw.println(" "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS + "(a11y modded)"
+ "="
+ getShowAndGoDuration());
pw.println(" "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS
+ "="
+ getShownFrequencyThreshold());
pw.println(" "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE
+ "="
+ getBehaviorMode());
pw.println(" mCurrentBehavior=" + mCurrentBehavior.toString());
mBehaviorMap.get(mCurrentBehavior).dump(pw, " ");
}
interface BehaviorController {
void onModeActivated(Context context, AssistHandleCallbacks callbacks);
default void onModeDeactivated() {}
default void onAssistantGesturePerformed() {}
default void onAssistHandlesRequested() {}
default void dump(PrintWriter pw, String prefix) {}
}
}

View File

@@ -1,41 +0,0 @@
/*
* 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;
/** Callback for controlling Assistant handle behavior. */
public interface AssistHandleCallbacks {
/** Hide the Assistant handles. */
void hide();
/**
* Show the Assistant handles for the configured duration and then hide them.
*
* Won't show if the handles have been shown within the configured timeout.
*/
void showAndGo();
/**
* Same as show and go, but will not do anything until a delay has elapsed.
*
* Will be cancelled if another command is given during the delay.
*/
void showAndGoDelayed(long delayMs, boolean hideIfShowing);
/** Show the Assistant handles. */
void showAndStay();
}

View File

@@ -1,172 +0,0 @@
/*
* 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.content.Context;
import androidx.annotation.Nullable;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import java.io.PrintWriter;
import javax.inject.Inject;
import dagger.Lazy;
/**
* Assistant Handle behavior that makes Assistant handles show/hide when the home handle is
* shown/hidden, respectively.
*/
@SysUISingleton
final class AssistHandleLikeHomeBehavior implements BehaviorController {
private final StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onDozingChanged(boolean isDozing) {
handleDozingChanged(isDozing);
}
};
private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
new WakefulnessLifecycle.Observer() {
@Override
public void onStartedWakingUp() {
handleWakefullnessChanged(/* isAwake = */ false);
}
@Override
public void onFinishedWakingUp() {
handleWakefullnessChanged(/* isAwake = */ true);
}
@Override
public void onStartedGoingToSleep() {
handleWakefullnessChanged(/* isAwake = */ false);
}
@Override
public void onFinishedGoingToSleep() {
handleWakefullnessChanged(/* isAwake = */ false);
}
};
private final SysUiState.SysUiStateCallback mSysUiStateCallback =
this::handleSystemUiStateChange;
private final Lazy<StatusBarStateController> mStatusBarStateController;
private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
private final Lazy<SysUiState> mSysUiFlagContainer;
private boolean mIsDozing;
private boolean mIsAwake;
private boolean mIsHomeHandleHiding;
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
@Inject
AssistHandleLikeHomeBehavior(
Lazy<StatusBarStateController> statusBarStateController,
Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
Lazy<SysUiState> sysUiFlagContainer) {
mStatusBarStateController = statusBarStateController;
mWakefulnessLifecycle = wakefulnessLifecycle;
mSysUiFlagContainer = sysUiFlagContainer;
}
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
mAssistHandleCallbacks = callbacks;
mIsDozing = mStatusBarStateController.get().isDozing();
mStatusBarStateController.get().addCallback(mStatusBarStateListener);
mIsAwake = mWakefulnessLifecycle.get().getWakefulness()
== WakefulnessLifecycle.WAKEFULNESS_AWAKE;
mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
callbackForCurrentState();
}
@Override
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
}
private static boolean isHomeHandleHiding(int sysuiStateFlags) {
return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
}
private void handleDozingChanged(boolean isDozing) {
if (mIsDozing == isDozing) {
return;
}
mIsDozing = isDozing;
callbackForCurrentState();
}
private void handleWakefullnessChanged(boolean isAwake) {
if (mIsAwake == isAwake) {
return;
}
mIsAwake = isAwake;
callbackForCurrentState();
}
private void handleSystemUiStateChange(int sysuiStateFlags) {
boolean isHomeHandleHiding = isHomeHandleHiding(sysuiStateFlags);
if (mIsHomeHandleHiding == isHomeHandleHiding) {
return;
}
mIsHomeHandleHiding = isHomeHandleHiding;
callbackForCurrentState();
}
private void callbackForCurrentState() {
if (mAssistHandleCallbacks == null) {
return;
}
if (mIsHomeHandleHiding || !isFullyAwake()) {
mAssistHandleCallbacks.hide();
} else {
mAssistHandleCallbacks.showAndStay();
}
}
private boolean isFullyAwake() {
return mIsAwake && !mIsDozing;
}
@Override
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "Current AssistHandleLikeHomeBehavior State:");
pw.println(prefix + " mIsDozing=" + mIsDozing);
pw.println(prefix + " mIsAwake=" + mIsAwake);
pw.println(prefix + " mIsHomeHandleHiding=" + mIsHomeHandleHiding);
}
}

View File

@@ -1,38 +0,0 @@
/*
* 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.content.Context;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.dagger.SysUISingleton;
import javax.inject.Inject;
/** Assistant handle behavior that hides the Assistant handles. */
@SysUISingleton
final class AssistHandleOffBehavior implements BehaviorController {
@Inject
AssistHandleOffBehavior() {
}
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
callbacks.hide();
}
}

View File

@@ -1,662 +0,0 @@
/*
* 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 com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME;
import static com.android.systemui.assist.AssistModule.UPTIME_NAME;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import androidx.annotation.Nullable;
import androidx.slice.Clock;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.statusbar.StatusBarState;
import java.io.PrintWriter;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import dagger.Lazy;
/**
* Assistant handle behavior that hides the handles when the phone is dozing or in immersive mode,
* shows the handles when on lockscreen, and shows the handles temporarily when changing tasks or
* entering overview.
*/
@SysUISingleton
final class AssistHandleReminderExpBehavior implements BehaviorController {
private static final Uri LEARNING_TIME_ELAPSED_URI =
Settings.Secure.getUriFor(Settings.Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS);
private static final Uri LEARNING_EVENT_COUNT_URI =
Settings.Secure.getUriFor(Settings.Secure.ASSIST_HANDLES_LEARNING_EVENT_COUNT);
private static final String LEARNED_HINT_LAST_SHOWN_KEY =
"reminder_exp_learned_hint_last_shown";
private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(10);
private static final int DEFAULT_LEARNING_COUNT = 10;
private static final long DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = 150;
private static final long DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS =
TimeUnit.SECONDS.toMillis(1);
private static final long DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS =
TimeUnit.SECONDS.toMillis(3);
private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false;
private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false;
private static final boolean DEFAULT_SUPPRESS_ON_APPS = true;
private static final boolean DEFAULT_SHOW_WHEN_TAUGHT = false;
private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
Intent.ACTION_PACKAGE_ADDED,
Intent.ACTION_PACKAGE_CHANGED,
Intent.ACTION_PACKAGE_REMOVED
};
private final StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
handleStatusBarStateChanged(newState);
}
@Override
public void onDozingChanged(boolean isDozing) {
handleDozingChanged(isDozing);
}
};
private final TaskStackChangeListener mTaskStackChangeListener =
new TaskStackChangeListener() {
@Override
public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
handleTaskStackTopChanged(taskInfo.taskId, taskInfo.topActivity);
}
@Override
public void onTaskCreated(int taskId, ComponentName componentName) {
handleTaskStackTopChanged(taskId, componentName);
}
};
private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
new OverviewProxyService.OverviewProxyListener() {
@Override
public void onOverviewShown(boolean fromHome) {
handleOverviewShown();
}
};
private final SysUiState.SysUiStateCallback mSysUiStateCallback =
this::handleSystemUiStateChanged;
private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
new WakefulnessLifecycle.Observer() {
@Override
public void onStartedWakingUp() {
handleWakefullnessChanged(/* isAwake = */ false);
}
@Override
public void onFinishedWakingUp() {
handleWakefullnessChanged(/* isAwake = */ true);
}
@Override
public void onStartedGoingToSleep() {
handleWakefullnessChanged(/* isAwake = */ false);
}
@Override
public void onFinishedGoingToSleep() {
handleWakefullnessChanged(/* isAwake = */ false);
}
};
private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mDefaultHome = getCurrentDefaultHome();
}
};
private final BootCompleteCache.BootCompleteListener mBootCompleteListener =
new BootCompleteCache.BootCompleteListener() {
@Override
public void onBootComplete() {
mDefaultHome = getCurrentDefaultHome();
}
};
private final IntentFilter mDefaultHomeIntentFilter;
private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches;
private final Clock mClock;
private final Handler mHandler;
private final DeviceConfigHelper mDeviceConfigHelper;
private final Lazy<StatusBarStateController> mStatusBarStateController;
private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
private final Lazy<TaskStackChangeListeners> mTaskStackChangeListeners;
private final Lazy<OverviewProxyService> mOverviewProxyService;
private final Lazy<SysUiState> mSysUiFlagContainer;
private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;
private final Lazy<BroadcastDispatcher> mBroadcastDispatcher;
private final Lazy<BootCompleteCache> mBootCompleteCache;
private boolean mOnLockscreen;
private boolean mIsDozing;
private boolean mIsAwake;
private int mRunningTaskId;
private boolean mIsNavBarHidden;
private boolean mIsLauncherShowing;
private int mConsecutiveTaskSwitches;
@Nullable private ContentObserver mSettingObserver;
/** Whether user has learned the gesture. */
private boolean mIsLearned;
private long mLastLearningTimestamp;
/** Uptime while in this behavior. */
private long mLearningTimeElapsed;
/** Number of successful Assistant invocations while in this behavior. */
private int mLearningCount;
private long mLearnedHintLastShownEpochDay;
@Nullable private Context mContext;
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
@Nullable private ComponentName mDefaultHome;
@Inject
AssistHandleReminderExpBehavior(
@Named(UPTIME_NAME) Clock clock,
@Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
DeviceConfigHelper deviceConfigHelper,
Lazy<StatusBarStateController> statusBarStateController,
Lazy<ActivityManagerWrapper> activityManagerWrapper,
Lazy<TaskStackChangeListeners> taskStackChangeListeners,
Lazy<OverviewProxyService> overviewProxyService,
Lazy<SysUiState> sysUiFlagContainer,
Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
Lazy<PackageManagerWrapper> packageManagerWrapper,
Lazy<BroadcastDispatcher> broadcastDispatcher,
Lazy<BootCompleteCache> bootCompleteCache) {
mClock = clock;
mHandler = handler;
mDeviceConfigHelper = deviceConfigHelper;
mStatusBarStateController = statusBarStateController;
mActivityManagerWrapper = activityManagerWrapper;
mTaskStackChangeListeners = taskStackChangeListeners;
mOverviewProxyService = overviewProxyService;
mSysUiFlagContainer = sysUiFlagContainer;
mWakefulnessLifecycle = wakefulnessLifecycle;
mPackageManagerWrapper = packageManagerWrapper;
mDefaultHomeIntentFilter = new IntentFilter();
for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
mDefaultHomeIntentFilter.addAction(action);
}
mBroadcastDispatcher = broadcastDispatcher;
mBootCompleteCache = bootCompleteCache;
}
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
mContext = context;
mAssistHandleCallbacks = callbacks;
mConsecutiveTaskSwitches = 0;
mBootCompleteCache.get().addListener(mBootCompleteListener);
mDefaultHome = getCurrentDefaultHome();
mBroadcastDispatcher.get()
.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState());
mIsDozing = mStatusBarStateController.get().isDozing();
mStatusBarStateController.get().addCallback(mStatusBarStateListener);
ActivityManager.RunningTaskInfo runningTaskInfo =
mActivityManagerWrapper.get().getRunningTask();
mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
mTaskStackChangeListeners.get().registerTaskStackListener(mTaskStackChangeListener);
mOverviewProxyService.get().addCallback(mOverviewProxyListener);
mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
mIsAwake = mWakefulnessLifecycle.get().getWakefulness()
== WakefulnessLifecycle.WAKEFULNESS_AWAKE;
mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
mLearningTimeElapsed = Settings.Secure.getLong(
context.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS,
/* default = */ 0);
mLearningCount = Settings.Secure.getInt(
context.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_EVENT_COUNT,
/* default = */ 0);
mSettingObserver = new SettingsObserver(context, mHandler);
context.getContentResolver().registerContentObserver(
LEARNING_TIME_ELAPSED_URI,
/* notifyForDescendants = */ true,
mSettingObserver);
context.getContentResolver().registerContentObserver(
LEARNING_EVENT_COUNT_URI,
/* notifyForDescendants = */ true,
mSettingObserver);
mLearnedHintLastShownEpochDay = Settings.Secure.getLong(
context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0);
mLastLearningTimestamp = mClock.currentTimeMillis();
callbackForCurrentState(/* justUnlocked = */ false);
}
@Override
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
if (mContext != null) {
mBroadcastDispatcher.get().unregisterReceiver(mDefaultHomeBroadcastReceiver);
mBootCompleteCache.get().removeListener(mBootCompleteListener);
mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
mSettingObserver = null;
// putString in order to use overrideableByRestore
Settings.Secure.putString(
mContext.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS,
Long.toString(0L),
/* overrideableByRestore = */ true);
// putString in order to use overrideableByRestore
Settings.Secure.putString(
mContext.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_EVENT_COUNT,
Integer.toString(0),
/* overrideableByRestore = */ true);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
mContext = null;
}
mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
mTaskStackChangeListeners.get().unregisterTaskStackListener(mTaskStackChangeListener);
mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
}
@Override
public void onAssistantGesturePerformed() {
if (mContext == null) {
return;
}
// putString in order to use overrideableByRestore
Settings.Secure.putString(
mContext.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_EVENT_COUNT,
Integer.toString(++mLearningCount),
/* overrideableByRestore = */ true);
}
@Override
public void onAssistHandlesRequested() {
if (mAssistHandleCallbacks != null
&& isFullyAwake()
&& !mIsNavBarHidden
&& !mOnLockscreen) {
mAssistHandleCallbacks.showAndGo();
}
}
@Nullable
private ComponentName getCurrentDefaultHome() {
List<ResolveInfo> homeActivities = new ArrayList<>();
ComponentName defaultHome = mPackageManagerWrapper.get().getHomeActivities(homeActivities);
if (defaultHome != null) {
return defaultHome;
}
int topPriority = Integer.MIN_VALUE;
ComponentName topComponent = null;
for (ResolveInfo resolveInfo : homeActivities) {
if (resolveInfo.priority > topPriority) {
topComponent = resolveInfo.activityInfo.getComponentName();
topPriority = resolveInfo.priority;
} else if (resolveInfo.priority == topPriority) {
topComponent = null;
}
}
return topComponent;
}
private void handleStatusBarStateChanged(int newState) {
boolean onLockscreen = onLockscreen(newState);
if (mOnLockscreen == onLockscreen) {
return;
}
resetConsecutiveTaskSwitches();
mOnLockscreen = onLockscreen;
callbackForCurrentState(!onLockscreen);
}
private void handleDozingChanged(boolean isDozing) {
if (mIsDozing == isDozing) {
return;
}
resetConsecutiveTaskSwitches();
mIsDozing = isDozing;
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleWakefullnessChanged(boolean isAwake) {
if (mIsAwake == isAwake) {
return;
}
resetConsecutiveTaskSwitches();
mIsAwake = isAwake;
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleTaskStackTopChanged(int taskId, @Nullable ComponentName taskComponentName) {
if (mRunningTaskId == taskId || taskComponentName == null) {
return;
}
mRunningTaskId = taskId;
mIsLauncherShowing = taskComponentName.equals(mDefaultHome);
if (mIsLauncherShowing) {
resetConsecutiveTaskSwitches();
} else {
rescheduleConsecutiveTaskSwitchesReset();
mConsecutiveTaskSwitches++;
}
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleSystemUiStateChanged(int sysuiStateFlags) {
boolean isNavBarHidden =
(sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
if (mIsNavBarHidden == isNavBarHidden) {
return;
}
resetConsecutiveTaskSwitches();
mIsNavBarHidden = isNavBarHidden;
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleOverviewShown() {
resetConsecutiveTaskSwitches();
callbackForCurrentState(/* justUnlocked = */ false);
}
private boolean onLockscreen(int statusBarState) {
return statusBarState == StatusBarState.KEYGUARD
|| statusBarState == StatusBarState.SHADE_LOCKED;
}
private void callbackForCurrentState(boolean justUnlocked) {
updateLearningStatus();
if (mIsLearned) {
callbackForLearnedState(justUnlocked);
} else {
callbackForUnlearnedState();
}
}
private void callbackForLearnedState(boolean justUnlocked) {
if (mAssistHandleCallbacks == null) {
return;
}
if (!isFullyAwake() || mIsNavBarHidden || mOnLockscreen || !getShowWhenTaught()) {
mAssistHandleCallbacks.hide();
} else if (justUnlocked) {
long currentEpochDay = LocalDate.now().toEpochDay();
if (mLearnedHintLastShownEpochDay < currentEpochDay) {
if (mContext != null) {
Settings.Secure.putLong(
mContext.getContentResolver(),
LEARNED_HINT_LAST_SHOWN_KEY,
currentEpochDay);
}
mLearnedHintLastShownEpochDay = currentEpochDay;
mAssistHandleCallbacks.showAndGo();
}
}
}
private void callbackForUnlearnedState() {
if (mAssistHandleCallbacks == null) {
return;
}
if (!isFullyAwake() || mIsNavBarHidden || isSuppressed()) {
mAssistHandleCallbacks.hide();
} else if (mOnLockscreen) {
mAssistHandleCallbacks.showAndStay();
} else if (mIsLauncherShowing) {
mAssistHandleCallbacks.showAndGo();
} else if (mConsecutiveTaskSwitches == 1) {
mAssistHandleCallbacks.showAndGoDelayed(
getShowAndGoDelayedShortDelayMs(), /* hideIfShowing = */ false);
} else {
mAssistHandleCallbacks.showAndGoDelayed(
getShowAndGoDelayedLongDelayMs(), /* hideIfShowing = */ true);
}
}
private boolean isSuppressed() {
if (mOnLockscreen) {
return getSuppressOnLockscreen();
} else if (mIsLauncherShowing) {
return getSuppressOnLauncher();
} else {
return getSuppressOnApps();
}
}
private void updateLearningStatus() {
if (mContext == null) {
return;
}
long currentTimestamp = mClock.currentTimeMillis();
mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
mLastLearningTimestamp = currentTimestamp;
mIsLearned =
mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();
// putString in order to use overrideableByRestore
mHandler.post(() -> Settings.Secure.putString(
mContext.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS,
Long.toString(mLearningTimeElapsed),
/* overrideableByRestore = */ true));
}
private void resetConsecutiveTaskSwitches() {
mHandler.removeCallbacks(mResetConsecutiveTaskSwitches);
mConsecutiveTaskSwitches = 0;
}
private void rescheduleConsecutiveTaskSwitchesReset() {
mHandler.removeCallbacks(mResetConsecutiveTaskSwitches);
mHandler.postDelayed(mResetConsecutiveTaskSwitches, getShowAndGoDelayResetTimeoutMs());
}
private boolean isFullyAwake() {
return mIsAwake && !mIsDozing;
}
private long getLearningTimeMs() {
return mDeviceConfigHelper.getLong(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS,
DEFAULT_LEARNING_TIME_MS);
}
private int getLearningCount() {
return mDeviceConfigHelper.getInt(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT,
DEFAULT_LEARNING_COUNT);
}
private long getShowAndGoDelayedShortDelayMs() {
return mDeviceConfigHelper.getLong(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS,
DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS);
}
private long getShowAndGoDelayedLongDelayMs() {
return mDeviceConfigHelper.getLong(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS,
DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS);
}
private long getShowAndGoDelayResetTimeoutMs() {
return mDeviceConfigHelper.getLong(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS,
DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS);
}
private boolean getSuppressOnLockscreen() {
return mDeviceConfigHelper.getBoolean(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN,
DEFAULT_SUPPRESS_ON_LOCKSCREEN);
}
private boolean getSuppressOnLauncher() {
return mDeviceConfigHelper.getBoolean(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER,
DEFAULT_SUPPRESS_ON_LAUNCHER);
}
private boolean getSuppressOnApps() {
return mDeviceConfigHelper.getBoolean(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS,
DEFAULT_SUPPRESS_ON_APPS);
}
private boolean getShowWhenTaught() {
return mDeviceConfigHelper.getBoolean(
SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT,
DEFAULT_SHOW_WHEN_TAUGHT);
}
@Override
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "Current AssistHandleReminderExpBehavior State:");
pw.println(prefix + " mOnLockscreen=" + mOnLockscreen);
pw.println(prefix + " mIsDozing=" + mIsDozing);
pw.println(prefix + " mIsAwake=" + mIsAwake);
pw.println(prefix + " mRunningTaskId=" + mRunningTaskId);
pw.println(prefix + " mDefaultHome=" + mDefaultHome);
pw.println(prefix + " mIsNavBarHidden=" + mIsNavBarHidden);
pw.println(prefix + " mIsLauncherShowing=" + mIsLauncherShowing);
pw.println(prefix + " mConsecutiveTaskSwitches=" + mConsecutiveTaskSwitches);
pw.println(prefix + " mIsLearned=" + mIsLearned);
pw.println(prefix + " mLastLearningTimestamp=" + mLastLearningTimestamp);
pw.println(prefix + " mLearningTimeElapsed=" + mLearningTimeElapsed);
pw.println(prefix + " mLearningCount=" + mLearningCount);
pw.println(prefix + " mLearnedHintLastShownEpochDay=" + mLearnedHintLastShownEpochDay);
pw.println(
prefix + " mAssistHandleCallbacks present: " + (mAssistHandleCallbacks != null));
pw.println(prefix + " Phenotype Flags:");
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS
+ "="
+ getLearningTimeMs());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT
+ "="
+ getLearningCount());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS
+ "="
+ getShowAndGoDelayedShortDelayMs());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS
+ "="
+ getShowAndGoDelayedLongDelayMs());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS
+ "="
+ getShowAndGoDelayResetTimeoutMs());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN
+ "="
+ getSuppressOnLockscreen());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER
+ "="
+ getSuppressOnLauncher());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS
+ "="
+ getSuppressOnApps());
pw.println(prefix + " "
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT
+ "="
+ getShowWhenTaught());
}
private final class SettingsObserver extends ContentObserver {
private final Context mContext;
SettingsObserver(Context context, Handler handler) {
super(handler);
mContext = context;
}
@Override
public void onChange(boolean selfChange, @Nullable Uri uri) {
if (LEARNING_TIME_ELAPSED_URI.equals(uri)) {
mLastLearningTimestamp = mClock.currentTimeMillis();
mLearningTimeElapsed = Settings.Secure.getLong(
mContext.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS,
/* default = */ 0);
} else if (LEARNING_EVENT_COUNT_URI.equals(uri)) {
mLearningCount = Settings.Secure.getInt(
mContext.getContentResolver(),
Settings.Secure.ASSIST_HANDLES_LEARNING_EVENT_COUNT,
/* default = */ 0);
}
super.onChange(selfChange, uri);
}
}
}

View File

@@ -1,191 +0,0 @@
/*
* 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.navigationbar.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;
private int mBottomOffset;
@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);
}
/**
* Set the bottom offset.
*
* @param bottomOffset the bottom offset to translate.
*/
public void setBottomOffset(int bottomOffset) {
if (mBottomOffset != bottomOffset) {
mBottomOffset = bottomOffset;
if (mAssistHintVisible) {
// If assist handles are visible, hide them without animation and then make them
// show once again (with corrected bottom offset).
hideAssistHandles();
setAssistHintVisible(true);
}
}
}
/**
* 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() + mBottomOffset,
translationEnd * view.getHeight() + mBottomOffset);
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

@@ -37,8 +37,7 @@ open class AssistLogger @Inject constructor(
protected val context: Context,
protected val uiEventLogger: UiEventLogger,
private val assistUtils: AssistUtils,
private val phoneStateMonitor: PhoneStateMonitor,
private val assistHandleBehaviorController: AssistHandleBehaviorController
private val phoneStateMonitor: PhoneStateMonitor
) {
private val instanceIdSequence = InstanceIdSequence(INSTANCE_ID_MAX)
@@ -82,7 +81,7 @@ open class AssistLogger @Inject constructor(
assistComponentFinal.flattenToString(),
getOrCreateInstanceId().id,
deviceStateFinal,
assistHandleBehaviorController.areHandlesShowing())
false)
reportAssistantInvocationExtraData()
}

View File

@@ -87,7 +87,6 @@ public class AssistManager {
private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state";
protected static final String ACTION_KEY = "action";
protected static final String SHOW_ASSIST_HANDLES_ACTION = "show_assist_handles";
protected static final String SET_ASSIST_GESTURE_CONSTRAINED_ACTION =
"set_assist_gesture_constrained";
protected static final String CONSTRAINED_KEY = "should_constrain";
@@ -119,7 +118,6 @@ public class AssistManager {
protected final Context mContext;
private final AssistDisclosure mAssistDisclosure;
private final PhoneStateMonitor mPhoneStateMonitor;
private final AssistHandleBehaviorController mHandleController;
private final UiController mUiController;
protected final Lazy<SysUiState> mSysUiState;
protected final AssistLogger mAssistLogger;
@@ -148,7 +146,6 @@ public class AssistManager {
DeviceProvisionedController controller,
Context context,
AssistUtils assistUtils,
AssistHandleBehaviorController handleController,
CommandQueue commandQueue,
PhoneStateMonitor phoneStateMonitor,
OverviewProxyService overviewProxyService,
@@ -162,7 +159,6 @@ public class AssistManager {
mAssistUtils = assistUtils;
mAssistDisclosure = new AssistDisclosure(context, new Handler());
mPhoneStateMonitor = phoneStateMonitor;
mHandleController = handleController;
mAssistLogger = assistLogger;
mOrbController = new AssistOrbController(configurationController, context);
@@ -216,9 +212,7 @@ public class AssistManager {
}
String action = hints.getString(ACTION_KEY);
if (SHOW_ASSIST_HANDLES_ACTION.equals(action)) {
requestAssistHandles();
} else if (SET_ASSIST_GESTURE_CONSTRAINED_ACTION.equals(action)) {
if (SET_ASSIST_GESTURE_CONSTRAINED_ACTION.equals(action)) {
mSysUiState.get()
.setFlag(
SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
@@ -249,9 +243,6 @@ public class AssistManager {
args = new Bundle();
}
int legacyInvocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
if (legacyInvocationType == INVOCATION_TYPE_GESTURE) {
mHandleController.onAssistantGesturePerformed();
}
int legacyDeviceState = mPhoneStateMonitor.getPhoneState();
args.putInt(INVOCATION_PHONE_STATE_KEY, legacyDeviceState);
args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
@@ -278,10 +269,6 @@ public class AssistManager {
mUiController.onGestureCompletion(velocity);
}
protected void requestAssistHandles() {
mHandleController.onAssistHandlesRequested();
}
public void hideAssist() {
mAssistUtils.hideCurrentSession();
}
@@ -362,10 +349,6 @@ public class AssistManager {
return mAssistUtils.isSessionRunning();
}
protected AssistHandleBehaviorController getHandleBehaviorController() {
return mHandleController;
}
@Nullable
public ComponentName getAssistInfoForUser(int userId) {
return mAssistUtils.getAssistComponentForUser(userId);
@@ -389,10 +372,6 @@ public class AssistManager {
});
}
public long getAssistHandleShowAndGoRemainingDurationMs() {
return mHandleController.getShowAndGoRemainingTimeMs();
}
/** Returns the logging flags for the given Assistant invocation type. */
public int toLoggingSubType(int invocationType) {
return toLoggingSubType(invocationType, mPhoneStateMonitor.getPhoneState());
@@ -409,7 +388,7 @@ public class AssistManager {
// Note that this logic will break if the number of Assistant invocation types exceeds 7.
// There are currently 5 invocation types, but we will be migrating to the new logging
// framework in the next update.
int subType = mHandleController.areHandlesShowing() ? 0 : 1;
int subType = 0;
subType |= invocationType << 1;
subType |= phoneState << 4;
return subType;

View File

@@ -21,15 +21,10 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import androidx.annotation.Nullable;
import androidx.slice.Clock;
import com.android.internal.app.AssistUtils;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.navigationbar.NavigationBarController;
import java.util.EnumMap;
import java.util.Map;
import javax.inject.Named;
@@ -53,28 +48,6 @@ public abstract class AssistModule {
return backgroundHandlerThread.getThreadHandler();
}
@Provides
@SysUISingleton
static Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController>
provideAssistHandleBehaviorControllerMap(
AssistHandleOffBehavior offBehavior,
AssistHandleLikeHomeBehavior likeHomeBehavior,
AssistHandleReminderExpBehavior reminderExpBehavior) {
Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> map =
new EnumMap<>(AssistHandleBehavior.class);
map.put(AssistHandleBehavior.OFF, offBehavior);
map.put(AssistHandleBehavior.LIKE_HOME, likeHomeBehavior);
map.put(AssistHandleBehavior.REMINDER_EXP, reminderExpBehavior);
return map;
}
@Provides
@Nullable
static AssistHandleViewController provideAssistHandleViewController(
NavigationBarController navigationBarController) {
return navigationBarController.getAssistHandlerViewController();
}
@Provides
@SysUISingleton
static AssistUtils provideAssistUtils(Context context) {

View File

@@ -37,12 +37,10 @@ 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.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistLogger;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.assist.AssistantSessionEvent;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.navigationbar.NavigationBarController;
import java.util.Locale;
@@ -113,7 +111,6 @@ public class DefaultUiController implements AssistManager.UiController {
if (!mInvocationInProgress) {
attach();
mInvocationInProgress = true;
updateAssistHandleVisibility();
}
setProgressInternal(type, progress);
}
@@ -136,7 +133,6 @@ public class DefaultUiController implements AssistManager.UiController {
}
mInvocationLightsView.hide();
mInvocationInProgress = false;
updateAssistHandleVisibility();
}
protected void logInvocationProgressMetrics(
@@ -174,17 +170,6 @@ public class DefaultUiController implements AssistManager.UiController {
}
}
private void updateAssistHandleVisibility() {
NavigationBarController navigationBarController =
Dependency.get(NavigationBarController.class);
AssistHandleViewController controller =
navigationBarController == null
? null : navigationBarController.getAssistHandlerViewController();
if (controller != null) {
controller.setAssistHintBlocked(mInvocationInProgress);
}
}
private void attach() {
if (!mAttached) {
mWindowManager.addView(mRoot, mLayoutParams);

View File

@@ -116,7 +116,6 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
@@ -276,11 +275,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
}
}
/** Only for default display */
@Nullable
AssistHandleViewController mAssistHandlerViewController;
private final AutoHideUiElement mAutoHideUiElement = new AutoHideUiElement() {
@Override
public void synchronizeState() {
@@ -630,11 +624,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
}
setDisabled2Flags(mDisabledFlags2);
if (mIsOnDefaultDisplay) {
mAssistHandlerViewController =
new AssistHandleViewController(mHandler, mNavigationBarView);
getBarTransitions().addDarkIntensityListener(mAssistHandlerViewController);
}
initSecondaryHomeHandleForRotation();
@@ -664,11 +653,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
@Override
public void onViewDetachedFromWindow(View v) {
if (mNavigationBarView != null) {
if (mIsOnDefaultDisplay) {
mNavigationBarView.getBarTransitions()
.removeDarkIntensityListener(mAssistHandlerViewController);
mAssistHandlerViewController = null;
}
mNavigationBarView.getBarTransitions().destroy();
mNavigationBarView.getLightTransitionsController().destroy(mContext);
}
@@ -1596,11 +1580,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
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 com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.Dumpable;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
@@ -399,13 +398,6 @@ public class NavigationBarController implements Callbacks,
return mNavigationBars.get(DEFAULT_DISPLAY);
}
/** @return {@link AssistHandleViewController} (only on the default display). */
@Nullable
public AssistHandleViewController getAssistHandlerViewController() {
NavigationBar navBar = getDefaultNavigationBar();
return navBar == null ? null : navBar.getAssistHandlerViewController();
}
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
for (int i = 0; i < mNavigationBars.size(); i++) {

View File

@@ -69,7 +69,6 @@ import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.model.SysUiState;
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
import com.android.systemui.navigationbar.buttons.ContextualButton;
@@ -1357,14 +1356,6 @@ public class NavigationBarView extends FrameLayout implements
setClipChildren(shouldClip);
setClipToPadding(shouldClip);
NavigationBarController navigationBarController =
Dependency.get(NavigationBarController.class);
AssistHandleViewController controller =
navigationBarController == null
? null : navigationBarController.getAssistHandlerViewController();
if (controller != null) {
controller.setBottomOffset(insets.getSystemWindowInsetBottom());
}
return super.onApplyWindowInsets(insets);
}

View File

@@ -196,8 +196,6 @@ public class ButtonDispatcher {
if (animate) {
setVisibility(View.VISIBLE);
mFadeAnimator = ValueAnimator.ofFloat(getAlpha(), alpha);
mFadeAnimator.setStartDelay(
mAssistManager.getAssistHandleShowAndGoRemainingDurationMs());
mFadeAnimator.setDuration(duration);
mFadeAnimator.setInterpolator(LINEAR);
mFadeAnimator.addListener(mFadeListener);

View File

@@ -1,392 +0,0 @@
/*
* 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 org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.SmallTest;
import com.android.internal.app.AssistUtils;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.EnumMap;
import java.util.Map;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
private static final ComponentName COMPONENT_NAME = new ComponentName("", "");
private AssistHandleBehaviorController mAssistHandleBehaviorController;
@Mock private AssistUtils mMockAssistUtils;
@Mock private Handler mMockHandler;
@Mock private DeviceConfigHelper mMockDeviceConfigHelper;
@Mock private AssistHandleOffBehavior mMockOffBehavior;
@Mock private AssistHandleLikeHomeBehavior mMockLikeHomeBehavior;
@Mock private AssistHandleReminderExpBehavior mMockReminderExpBehavior;
@Mock private AssistHandleBehaviorController.BehaviorController mMockTestBehavior;
@Mock private NavigationModeController mMockNavigationModeController;
@Mock private AssistHandleViewController mMockAssistHandleViewController;
@Mock private AccessibilityManager mMockA11yManager;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
doAnswer(answerVoid(Runnable::run)).when(mMockHandler).post(any(Runnable.class));
doAnswer(answerVoid(Runnable::run)).when(mMockHandler)
.postDelayed(any(Runnable.class), anyLong());
doAnswer(invocation -> invocation.getArgument(0)).when(mMockA11yManager)
.getRecommendedTimeoutMillis(anyInt(), anyInt());
Map<AssistHandleBehavior, AssistHandleBehaviorController.BehaviorController> behaviorMap =
new EnumMap<>(AssistHandleBehavior.class);
behaviorMap.put(AssistHandleBehavior.OFF, mMockOffBehavior);
behaviorMap.put(AssistHandleBehavior.LIKE_HOME, mMockLikeHomeBehavior);
behaviorMap.put(AssistHandleBehavior.REMINDER_EXP, mMockReminderExpBehavior);
behaviorMap.put(AssistHandleBehavior.TEST, mMockTestBehavior);
mAssistHandleBehaviorController =
new AssistHandleBehaviorController(
mContext,
mMockAssistUtils,
mMockHandler,
() -> mMockAssistHandleViewController,
mMockDeviceConfigHelper,
behaviorMap,
mMockNavigationModeController,
() -> mMockA11yManager,
mock(DumpManager.class));
}
@After
public void teardown() {
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF);
}
@Test
public void hide_hidesHandlesWhenShowing() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.hide();
// Assert
verify(mMockAssistHandleViewController).setAssistHintVisible(false);
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void hide_doesNothingWhenHiding() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.hide();
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndStay_showsHandlesWhenHiding() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndStay();
// Assert
verify(mMockAssistHandleViewController).setAssistHintVisible(true);
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndStay_doesNothingWhenShowing() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndStay();
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndStay_doesNothingWhenThereIsNoAssistant() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndStay();
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndGo_showsThenHidesHandlesWhenHiding() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGo();
// Assert
InOrder inOrder = inOrder(mMockAssistHandleViewController);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(true);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
inOrder.verifyNoMoreInteractions();
}
@Test
public void showAndGo_hidesHandlesAfterTimeoutWhenShowing() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGo();
// Assert
verify(mMockAssistHandleViewController).setAssistHintVisible(false);
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndGo_doesNothingIfRecentlyHidden() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
when(mMockDeviceConfigHelper.getLong(
eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS),
anyLong())).thenReturn(10000L);
mAssistHandleBehaviorController.showAndGo();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGo();
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndGo_doesNothingWhenThereIsNoAssistant() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGo();
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndGo_usesA11yTimeout() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
when(mMockDeviceConfigHelper.getLong(
eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS), anyLong()))
.thenReturn(12345L);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController, mMockA11yManager);
when(mMockA11yManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(54321);
ArgumentCaptor<Long> delay = ArgumentCaptor.forClass(Long.class);
// Act
mAssistHandleBehaviorController.showAndGo();
// Assert
verify(mMockA11yManager).getRecommendedTimeoutMillis(
eq(12345), eq(AccessibilityManager.FLAG_CONTENT_ICONS));
verify(mMockHandler).postDelayed(any(Runnable.class), delay.capture());
assert delay.getValue() == 54321L;
}
@Test
public void showAndGoDelayed_showsThenHidesHandlesWhenHiding() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
// Assert
InOrder inOrder = inOrder(mMockAssistHandleViewController);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(true);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
inOrder.verifyNoMoreInteractions();
}
@Test
public void showAndGoDelayed_hidesHandlesAfterTimeoutWhenShowing() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
// Assert
verify(mMockAssistHandleViewController).setAssistHintVisible(false);
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndGoDelayed_hidesInitiallyThenShowsThenHidesAfterTimeoutWhenHideRequested() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGoDelayed(1000, true);
// Assert
InOrder inOrder = inOrder(mMockAssistHandleViewController);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(true);
inOrder.verify(mMockAssistHandleViewController).setAssistHintVisible(false);
inOrder.verifyNoMoreInteractions();
}
@Test
public void showAndGoDelayed_doesNothingIfRecentlyHidden() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
when(mMockDeviceConfigHelper.getLong(
eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS),
anyLong())).thenReturn(10000L);
mAssistHandleBehaviorController.showAndGo();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void showAndGoDelayed_doesNothingWhenThereIsNoAssistant() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
mAssistHandleBehaviorController.hide();
reset(mMockAssistHandleViewController);
// Act
mAssistHandleBehaviorController.showAndGoDelayed(1000, false);
// Assert
verifyNoMoreInteractions(mMockAssistHandleViewController);
}
@Test
public void setBehavior_activatesTheBehaviorWhenInGesturalMode() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.setInGesturalModeForTest(true);
// Act
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
verify(mMockTestBehavior).onModeActivated(mContext, mAssistHandleBehaviorController);
verifyNoMoreInteractions(mMockTestBehavior);
}
@Test
public void setBehavior_deactivatesThePreviousBehaviorWhenInGesturalMode() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
mAssistHandleBehaviorController.setInGesturalModeForTest(true);
reset(mMockTestBehavior);
// Act
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF);
// Assert
verify(mMockTestBehavior).onModeDeactivated();
verifyNoMoreInteractions(mMockTestBehavior);
}
@Test
public void setBehavior_doesNothingWhenNotInGesturalMode() {
// Arrange
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.setInGesturalModeForTest(false);
// Act
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
verifyNoMoreInteractions(mMockTestBehavior);
}
}

View File

@@ -1,364 +0,0 @@
/*
* 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 org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class AssistHandleLikeHomeBehaviorTest extends SysuiTestCase {
private AssistHandleLikeHomeBehavior mAssistHandleLikeHomeBehavior;
@Mock private StatusBarStateController mMockStatusBarStateController;
@Mock private WakefulnessLifecycle mMockWakefulnessLifecycle;
@Mock private SysUiState mMockSysUiState;
@Mock private AssistHandleCallbacks mMockAssistHandleCallbacks;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mAssistHandleLikeHomeBehavior = new AssistHandleLikeHomeBehavior(
() -> mMockStatusBarStateController,
() -> mMockWakefulnessLifecycle,
() -> mMockSysUiState);
}
@Test
public void onModeActivated_beginsObserving() {
// Arrange
// Act
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
// Assert
verify(mMockStatusBarStateController).isDozing();
verify(mMockStatusBarStateController).addCallback(
any(StatusBarStateController.StateListener.class));
verify(mMockWakefulnessLifecycle).getWakefulness();
verify(mMockWakefulnessLifecycle).addObserver(any(WakefulnessLifecycle.Observer.class));
verify(mMockSysUiState).addCallback(any(SysUiState.SysUiStateCallback.class));
verifyNoMoreInteractions(mMockWakefulnessLifecycle, mMockSysUiState);
}
@Test
public void onModeActivated_showsHandlesWhenFullyAwake() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(false);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
// Act
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
// Assert
verify(mMockAssistHandleCallbacks).showAndStay();
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
@Test
public void onModeActivated_hidesHandlesWhenNotAwake() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(true);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP);
// Act
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
@Test
public void onModeActivated_hidesHandlesWhenDozing() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(true);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
// Act
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
@Test
public void onModeDeactivated_stopsObserving() {
// Arrange
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
ArgumentCaptor<StatusBarStateController.StateListener> stateListener =
ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
ArgumentCaptor<WakefulnessLifecycle.Observer> observer =
ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback =
ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class);
verify(mMockStatusBarStateController).addCallback(stateListener.capture());
verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
verify(mMockSysUiState).addCallback(sysUiStateCallback.capture());
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
mAssistHandleLikeHomeBehavior.onModeDeactivated();
// Assert
verify(mMockStatusBarStateController).removeCallback(eq(stateListener.getValue()));
verify(mMockWakefulnessLifecycle).removeObserver(eq(observer.getValue()));
verify(mMockSysUiState).removeCallback(eq(sysUiStateCallback.getValue()));
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
@Test
public void onAssistantGesturePerformed_doesNothing() {
// Arrange
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
mAssistHandleLikeHomeBehavior.onAssistantGesturePerformed();
// Assert
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
@Test
public void onAssistHandlesRequested_doesNothing() {
// Arrange
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
mAssistHandleLikeHomeBehavior.onAssistHandlesRequested();
// Assert
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
@Test
public void onBothAwakeAndUnDoze_handlesShow() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(true);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP);
ArgumentCaptor<StatusBarStateController.StateListener> stateListener =
ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
ArgumentCaptor<WakefulnessLifecycle.Observer> observer =
ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
verify(mMockStatusBarStateController).addCallback(stateListener.capture());
verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
observer.getValue().onFinishedWakingUp();
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Arrange
observer.getValue().onFinishedGoingToSleep();
reset(mMockAssistHandleCallbacks);
// Act
stateListener.getValue().onDozingChanged(false);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
observer.getValue().onFinishedWakingUp();
// Assert
verify(mMockAssistHandleCallbacks).showAndStay();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
@Test
public void onSleepOrDoze_handlesHide() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(false);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
ArgumentCaptor<StatusBarStateController.StateListener> stateListener =
ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
ArgumentCaptor<WakefulnessLifecycle.Observer> observer =
ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
verify(mMockStatusBarStateController).addCallback(stateListener.capture());
verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
observer.getValue().onStartedGoingToSleep();
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Arrange
observer.getValue().onFinishedWakingUp();
reset(mMockAssistHandleCallbacks);
// Act
stateListener.getValue().onDozingChanged(true);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
@Test
public void onHomeHandleHide_handlesHide() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(false);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback =
ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class);
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
verify(mMockSysUiState).addCallback(sysUiStateCallback.capture());
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
sysUiStateCallback.getValue().onSystemUiStateChanged(
QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
@Test
public void onHomeHandleUnhide_handlesShow() {
// Arrange
when(mMockStatusBarStateController.isDozing()).thenReturn(false);
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback =
ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class);
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
verify(mMockSysUiState).addCallback(sysUiStateCallback.capture());
sysUiStateCallback.getValue().onSystemUiStateChanged(
QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
reset(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
// Act
sysUiStateCallback.getValue().onSystemUiStateChanged(
~QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
// Assert
verify(mMockAssistHandleCallbacks).showAndStay();
verifyNoMoreInteractions(
mMockStatusBarStateController,
mMockWakefulnessLifecycle,
mMockSysUiState,
mMockAssistHandleCallbacks);
}
}

View File

@@ -1,101 +0,0 @@
/*
* 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 org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
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)
@TestableLooper.RunWithLooper
public class AssistHandleOffBehaviorTest extends SysuiTestCase {
private AssistHandleOffBehavior mAssistHandleOffBehavior;
@Mock private AssistHandleCallbacks mMockAssistHandleCallbacks;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mAssistHandleOffBehavior = new AssistHandleOffBehavior();
}
@Test
public void onModeActivated_hidesHandles() {
// Arrange
// Act
mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
@Test
public void onModeDeactivated_doesNothing() {
// Arrange
mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(mMockAssistHandleCallbacks);
// Act
mAssistHandleOffBehavior.onModeDeactivated();
// Assert
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
@Test
public void onAssistantGesturePerformed_doesNothing() {
// Arrange
mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(mMockAssistHandleCallbacks);
// Act
mAssistHandleOffBehavior.onAssistantGesturePerformed();
// Assert
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
@Test
public void onAssistHandlesRequested_doesNothing() {
// Arrange
mAssistHandleOffBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(mMockAssistHandleCallbacks);
// Act
mAssistHandleOffBehavior.onAssistHandlesRequested();
// Assert
verifyNoMoreInteractions(mMockAssistHandleCallbacks);
}
}

View File

@@ -1,104 +0,0 @@
/*
* 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);
}
}

View File

@@ -29,7 +29,6 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -272,10 +271,4 @@ public class NavigationBarControllerTest extends SysuiTestCase {
verify(mSecondaryNavBar).disableAnimationsDuringHide(eq(500L));
}
@Test
public void testGetAssistHandlerViewController_noCrash() {
reset(mNavigationBarController.mNavigationBars);
mNavigationBarController.getAssistHandlerViewController();
}
}