Trigger doze detection using WakefulnessLifecycle
Previously, doze detection used StatusBarStateController, which only
provides a signal at the end of the doze transition. This resulted in
the handles only animating away once the screen was already off. Using
the WakefulnessLifecycle allows for a callback when the transition
begins instead.
Test: Tested locally
BUG:137742178
Change-Id: I289ef5b5081fa96b1c8e82c4373c7654e8df80cb
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
index 3395014..ff4eb83 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
+import com.android.systemui.assist.AssistModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
@@ -34,7 +35,7 @@
* A dagger module for injecting components of System UI that are not overridden by the System UI
* implementation.
*/
-@Module
+@Module(includes = {AssistModule.class})
public abstract class SystemUIModule {
@Singleton
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 38ca708..9bdfa03 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -16,6 +16,8 @@
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;
@@ -28,20 +30,21 @@
import com.android.internal.app.AssistUtils;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.Dependency;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.ScreenDecorations;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.NavigationModeController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.EnumMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
-import java.util.function.Supplier;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
/**
* A class for managing Assistant handle logic.
@@ -49,6 +52,7 @@
* Controls when visual handles for Assistant gesture affordance should be shown or hidden using an
* {@link AssistHandleBehavior}.
*/
+@Singleton
public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable {
private static final String TAG = "AssistHandleBehavior";
@@ -67,10 +71,9 @@
private final Handler mHandler;
private final Runnable mHideHandles = this::hideHandles;
private final Runnable mShowAndGo = this::showAndGoInternal;
- private final Supplier<ScreenDecorations> mScreenDecorationsSupplier;
+ private final Provider<ScreenDecorations> mScreenDecorations;
private final PhenotypeHelper mPhenotypeHelper;
- private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap =
- new EnumMap<>(AssistHandleBehavior.class);
+ private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap;
private boolean mHandlesShowing = false;
private long mHandlesLastHiddenAt;
@@ -82,41 +85,25 @@
private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF;
private boolean mInGesturalMode;
- AssistHandleBehaviorController(Context context, AssistUtils assistUtils, Handler handler) {
- this(
- context,
- assistUtils,
- handler,
- () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class),
- new PhenotypeHelper(),
- /* testBehavior = */ null);
- }
-
- @VisibleForTesting
+ @Inject
AssistHandleBehaviorController(
Context context,
AssistUtils assistUtils,
- Handler handler,
- Supplier<ScreenDecorations> screenDecorationsSupplier,
+ @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
+ Provider<ScreenDecorations> screenDecorations,
PhenotypeHelper phenotypeHelper,
- @Nullable BehaviorController testBehavior) {
+ Map<AssistHandleBehavior, BehaviorController> behaviorMap,
+ NavigationModeController navigationModeController,
+ DumpController dumpController) {
mContext = context;
mAssistUtils = assistUtils;
mHandler = handler;
- mScreenDecorationsSupplier = screenDecorationsSupplier;
+ mScreenDecorations = screenDecorations;
mPhenotypeHelper = phenotypeHelper;
- mBehaviorMap.put(AssistHandleBehavior.OFF, new AssistHandleOffBehavior());
- mBehaviorMap.put(AssistHandleBehavior.LIKE_HOME, new AssistHandleLikeHomeBehavior());
- mBehaviorMap.put(
- AssistHandleBehavior.REMINDER_EXP,
- new AssistHandleReminderExpBehavior(handler, phenotypeHelper));
- if (testBehavior != null) {
- mBehaviorMap.put(AssistHandleBehavior.TEST, testBehavior);
- }
+ mBehaviorMap = behaviorMap;
mInGesturalMode = QuickStepContract.isGesturalMode(
- Dependency.get(NavigationModeController.class)
- .addListener(this::handleNavigationModeChange));
+ navigationModeController.addListener(this::handleNavigationModeChange));
setBehavior(getBehaviorMode());
mPhenotypeHelper.addOnPropertiesChangedListener(
@@ -128,7 +115,8 @@
SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null));
}
});
- Dependency.get(DumpController.class).registerDumpable(TAG, this);
+
+ dumpController.registerDumpable(TAG, this);
}
@Override // AssistHandleCallbacks
@@ -241,7 +229,7 @@
}
if (handlesUnblocked(ignoreThreshold)) {
- ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
+ ScreenDecorations screenDecorations = mScreenDecorations.get();
if (screenDecorations == null) {
Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable");
} else {
@@ -256,7 +244,7 @@
return;
}
- ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
+ ScreenDecorations screenDecorations = mScreenDecorations.get();
if (screenDecorations == null) {
Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable");
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
index 763315d..a0d8b4c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
@@ -20,56 +20,82 @@
import androidx.annotation.Nullable;
-import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
+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 javax.inject.Singleton;
+
+import dagger.Lazy;
+
/**
* Assistant Handle behavior that makes Assistant handles show/hide when the home handle is
* shown/hidden, respectively.
*/
+@Singleton
final class AssistHandleLikeHomeBehavior implements BehaviorController {
- private final StatusBarStateController.StateListener mStatusBarStateListener =
- new StatusBarStateController.StateListener() {
+ private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
+ new WakefulnessLifecycle.Observer() {
@Override
- public void onDozingChanged(boolean isDozing) {
- handleDozingChanged(isDozing);
+ public void onStartedWakingUp() {
+ handleDozingChanged(/* isDozing = */ true);
+ }
+
+ @Override
+ public void onFinishedWakingUp() {
+ handleDozingChanged(/* isDozing = */ false);
+ }
+
+ @Override
+ public void onStartedGoingToSleep() {
+ handleDozingChanged(/* isDozing = */ true);
+ }
+
+ @Override
+ public void onFinishedGoingToSleep() {
+ handleDozingChanged(/* isDozing = */ true);
}
};
private final SysUiState.SysUiStateCallback mSysUiStateCallback =
this::handleSystemUiStateChange;
- private final StatusBarStateController mStatusBarStateController;
- private final SysUiState mSysUiFlagContainer;
+
+ private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
+ private final Lazy<SysUiState> mSysUiFlagContainer;
private boolean mIsDozing;
private boolean mIsHomeHandleHiding;
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
- AssistHandleLikeHomeBehavior() {
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
- mSysUiFlagContainer = Dependency.get(SysUiState.class);
+ @Inject
+ AssistHandleLikeHomeBehavior(
+ Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
+ Lazy<SysUiState> sysUiFlagContainer) {
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mSysUiFlagContainer = sysUiFlagContainer;
}
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
mAssistHandleCallbacks = callbacks;
- mIsDozing = mStatusBarStateController.isDozing();
- mStatusBarStateController.addCallback(mStatusBarStateListener);
- mSysUiFlagContainer.addCallback(mSysUiStateCallback);
+ mIsDozing = mWakefulnessLifecycle.get().getWakefulness()
+ != WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+ mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
+ mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
callbackForCurrentState();
}
@Override
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
- mSysUiFlagContainer.removeCallback(mSysUiStateCallback);
+ mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
+ mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
}
private static boolean isHomeHandleHiding(int sysuiStateFlags) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java
index f4130ae..df913f9 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java
@@ -20,9 +20,17 @@
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/** Assistant handle behavior that hides the Assistant handles. */
+@Singleton
final class AssistHandleOffBehavior implements BehaviorController {
+ @Inject
+ AssistHandleOffBehavior() {
+ }
+
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
callbacks.hide();
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 5dd3cb1..d371dbe 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -16,7 +16,8 @@
package com.android.systemui.assist;
-import static com.android.systemui.DejankUtils.whitelistIpcs;
+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;
@@ -26,14 +27,14 @@
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.os.Handler;
-import android.os.SystemClock;
import android.provider.Settings;
import androidx.annotation.Nullable;
+import androidx.slice.Clock;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
+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;
@@ -49,11 +50,18 @@
import java.util.List;
import java.util.concurrent.TimeUnit;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+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.
*/
+@Singleton
final class AssistHandleReminderExpBehavior implements BehaviorController {
private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed";
@@ -86,11 +94,6 @@
public void onStateChanged(int newState) {
handleStatusBarStateChanged(newState);
}
-
- @Override
- public void onDozingChanged(boolean isDozing) {
- handleDozingChanged(isDozing);
- }
};
private final TaskStackChangeListener mTaskStackChangeListener =
new TaskStackChangeListener() {
@@ -111,9 +114,20 @@
handleOverviewShown();
}
};
-
private final SysUiState.SysUiStateCallback mSysUiStateCallback =
this::handleSystemUiStateChanged;
+ private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
+ new WakefulnessLifecycle.Observer() {
+ @Override
+ public void onFinishedWakingUp() {
+ handleDozingChanged(false);
+ }
+
+ @Override
+ public void onStartedGoingToSleep() {
+ handleDozingChanged(true);
+ }
+ };
private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -123,12 +137,15 @@
private final IntentFilter mDefaultHomeIntentFilter;
private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches;
+ private final Clock mClock;
private final Handler mHandler;
private final PhenotypeHelper mPhenotypeHelper;
- private final StatusBarStateController mStatusBarStateController;
- private final ActivityManagerWrapper mActivityManagerWrapper;
- private final OverviewProxyService mOverviewProxyService;
- private final SysUiState mSysUiFlagContainer;
+ private final Lazy<StatusBarStateController> mStatusBarStateController;
+ private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
+ private final Lazy<OverviewProxyService> mOverviewProxyService;
+ private final Lazy<SysUiState> mSysUiFlagContainer;
+ private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
+ private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;
private boolean mOnLockscreen;
private boolean mIsDozing;
@@ -150,13 +167,26 @@
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
@Nullable private ComponentName mDefaultHome;
- AssistHandleReminderExpBehavior(Handler handler, PhenotypeHelper phenotypeHelper) {
+ @Inject
+ AssistHandleReminderExpBehavior(
+ @Named(UPTIME_NAME) Clock clock,
+ @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
+ PhenotypeHelper phenotypeHelper,
+ Lazy<StatusBarStateController> statusBarStateController,
+ Lazy<ActivityManagerWrapper> activityManagerWrapper,
+ Lazy<OverviewProxyService> overviewProxyService,
+ Lazy<SysUiState> sysUiFlagContainer,
+ Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
+ Lazy<PackageManagerWrapper> packageManagerWrapper) {
+ mClock = clock;
mHandler = handler;
mPhenotypeHelper = phenotypeHelper;
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
- mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
- mSysUiFlagContainer = Dependency.get(SysUiState.class);
+ mStatusBarStateController = statusBarStateController;
+ mActivityManagerWrapper = activityManagerWrapper;
+ mOverviewProxyService = overviewProxyService;
+ mSysUiFlagContainer = sysUiFlagContainer;
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mPackageManagerWrapper = packageManagerWrapper;
mDefaultHomeIntentFilter = new IntentFilter();
for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
mDefaultHomeIntentFilter.addAction(action);
@@ -170,14 +200,17 @@
mConsecutiveTaskSwitches = 0;
mDefaultHome = getCurrentDefaultHome();
context.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
- mOnLockscreen = onLockscreen(mStatusBarStateController.getState());
- mIsDozing = mStatusBarStateController.isDozing();
- mStatusBarStateController.addCallback(mStatusBarStateListener);
- ActivityManager.RunningTaskInfo runningTaskInfo = mActivityManagerWrapper.getRunningTask();
+ mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState());
+ mStatusBarStateController.get().addCallback(mStatusBarStateListener);
+ ActivityManager.RunningTaskInfo runningTaskInfo =
+ mActivityManagerWrapper.get().getRunningTask();
mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
- mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
- mOverviewProxyService.addCallback(mOverviewProxyListener);
- mSysUiFlagContainer.addCallback(mSysUiStateCallback);
+ mActivityManagerWrapper.get().registerTaskStackListener(mTaskStackChangeListener);
+ mOverviewProxyService.get().addCallback(mOverviewProxyListener);
+ mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
+ mIsDozing = mWakefulnessLifecycle.get().getWakefulness()
+ != WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+ mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
mLearningTimeElapsed = Settings.Secure.getLong(
context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
@@ -185,7 +218,7 @@
context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0);
mLearnedHintLastShownEpochDay = Settings.Secure.getLong(
context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0);
- mLastLearningTimestamp = SystemClock.uptimeMillis();
+ mLastLearningTimestamp = mClock.currentTimeMillis();
callbackForCurrentState(/* justUnlocked = */ false);
}
@@ -200,10 +233,11 @@
Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
mContext = null;
}
- mStatusBarStateController.removeCallback(mStatusBarStateListener);
- mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
- mOverviewProxyService.removeCallback(mOverviewProxyListener);
- mSysUiFlagContainer.removeCallback(mSysUiStateCallback);
+ mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
+ mActivityManagerWrapper.get().unregisterTaskStackListener(mTaskStackChangeListener);
+ mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
+ mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
+ mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
}
@Override
@@ -223,15 +257,10 @@
}
}
- private static boolean isNavBarHidden(int sysuiStateFlags) {
- return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
- }
-
@Nullable
- private static ComponentName getCurrentDefaultHome() {
+ private ComponentName getCurrentDefaultHome() {
List<ResolveInfo> homeActivities = new ArrayList<>();
- ComponentName defaultHome =
- PackageManagerWrapper.getInstance().getHomeActivities(homeActivities);
+ ComponentName defaultHome = mPackageManagerWrapper.get().getHomeActivities(homeActivities);
if (defaultHome != null) {
return defaultHome;
}
@@ -287,7 +316,8 @@
}
private void handleSystemUiStateChanged(int sysuiStateFlags) {
- boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags);
+ boolean isNavBarHidden =
+ (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
if (mIsNavBarHidden == isNavBarHidden) {
return;
}
@@ -374,24 +404,15 @@
return;
}
- long currentTimestamp = SystemClock.uptimeMillis();
+ long currentTimestamp = mClock.currentTimeMillis();
mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
mLastLearningTimestamp = currentTimestamp;
- // TODO(b/140034473)
- whitelistIpcs(() -> Settings.Secure.putLong(
- mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed));
mIsLearned =
mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();
- mHandler.post(this::recordLearnTimeElapsed);
- }
-
- private void recordLearnTimeElapsed() {
- if (mContext != null) {
- Settings.Secure.putLong(
- mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed);
- }
+ mHandler.post(() -> Settings.Secure.putLong(
+ mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed));
}
private void resetConsecutiveTaskSwitches() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index eb60b3d..1f950f6 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -21,7 +21,6 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -157,17 +156,18 @@
};
@Inject
- public AssistManager(DeviceProvisionedController controller, Context context) {
+ public AssistManager(
+ DeviceProvisionedController controller,
+ Context context,
+ AssistUtils assistUtils,
+ AssistHandleBehaviorController handleController) {
mContext = context;
mDeviceProvisionedController = controller;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- mAssistUtils = new AssistUtils(context);
+ mAssistUtils = assistUtils;
mAssistDisclosure = new AssistDisclosure(context, new Handler());
mPhoneStateMonitor = new PhoneStateMonitor(context);
- final HandlerThread assistHandleThread = new HandlerThread("AssistHandleThread");
- assistHandleThread.start();
- mHandleController = new AssistHandleBehaviorController(
- context, mAssistUtils, assistHandleThread.getThreadHandler());
+ mHandleController = handleController;
registerVoiceInteractionSessionListener();
mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
new file mode 100644
index 0000000..2a82d21
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
@@ -0,0 +1,88 @@
+/*
+ * 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 android.os.Handler;
+import android.os.HandlerThread;
+import android.os.SystemClock;
+
+import androidx.slice.Clock;
+
+import com.android.internal.app.AssistUtils;
+import com.android.systemui.ScreenDecorations;
+import com.android.systemui.SysUiServiceProvider;
+
+import java.util.EnumMap;
+import java.util.Map;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/** Module for dagger injections related to the Assistant. */
+@Module
+public abstract class AssistModule {
+
+ static final String ASSIST_HANDLE_THREAD_NAME = "assist_handle_thread";
+ static final String UPTIME_NAME = "uptime";
+
+ @Provides
+ @Singleton
+ @Named(ASSIST_HANDLE_THREAD_NAME)
+ static Handler provideBackgroundHandler() {
+ final HandlerThread backgroundHandlerThread =
+ new HandlerThread("AssistHandleThread");
+ backgroundHandlerThread.start();
+ return backgroundHandlerThread.getThreadHandler();
+ }
+
+ @Provides
+ @Singleton
+ 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
+ static ScreenDecorations provideScreenDecorations(Context context) {
+ return SysUiServiceProvider.getComponent(context, ScreenDecorations.class);
+ }
+
+ @Provides
+ @Singleton
+ static AssistUtils provideAssistUtils(Context context) {
+ return new AssistUtils(context);
+ }
+
+ @Provides
+ @Singleton
+ @Named(UPTIME_NAME)
+ static Clock provideSystemClock() {
+ return SystemClock::uptimeMillis;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java
index c21a717..cbb56e8 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java
@@ -24,8 +24,18 @@
import java.util.concurrent.Executor;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Wrapper class for retrieving phenotype flag values.
+ *
+ * Can be mocked in tests for ease of testing the effects of particular values.
+ */
+@Singleton
public class PhenotypeHelper {
+ @Inject
public PhenotypeHelper() {}
public long getLong(String name, long defaultValue) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
index 6db5ef9..9c920f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
@@ -42,6 +42,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.statusbar.phone.NavigationModeController;
import org.junit.After;
import org.junit.Before;
@@ -51,6 +52,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.EnumMap;
+import java.util.Map;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -64,7 +68,12 @@
@Mock private AssistUtils mMockAssistUtils;
@Mock private Handler mMockHandler;
@Mock private PhenotypeHelper mMockPhenotypeHelper;
- @Mock private AssistHandleBehaviorController.BehaviorController mMockBehaviorController;
+ @Mock private AssistHandleOffBehavior mMockOffBehavior;
+ @Mock private AssistHandleLikeHomeBehavior mMockLikeHomeBehavior;
+ @Mock private AssistHandleReminderExpBehavior mMockReminderExpBehavior;
+ @Mock private AssistHandleBehaviorController.BehaviorController mMockTestBehavior;
+ @Mock private NavigationModeController mMockNavigationModeController;
+ @Mock private DumpController mMockDumpController;
@Before
public void setup() {
@@ -76,13 +85,23 @@
doAnswer(answerVoid(Runnable::run)).when(mMockHandler)
.postDelayed(any(Runnable.class), anyLong());
+ 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, () -> mMockScreenDecorations,
+ mMockHandler,
+ () -> mMockScreenDecorations,
mMockPhenotypeHelper,
- mMockBehaviorController);
+ behaviorMap,
+ mMockNavigationModeController,
+ mMockDumpController);
}
@After
@@ -316,8 +335,8 @@
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
- verify(mMockBehaviorController).onModeActivated(mContext, mAssistHandleBehaviorController);
- verifyNoMoreInteractions(mMockBehaviorController);
+ verify(mMockTestBehavior).onModeActivated(mContext, mAssistHandleBehaviorController);
+ verifyNoMoreInteractions(mMockTestBehavior);
}
@Test
@@ -326,14 +345,14 @@
when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
mAssistHandleBehaviorController.setInGesturalModeForTest(true);
- reset(mMockBehaviorController);
+ reset(mMockTestBehavior);
// Act
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF);
// Assert
- verify(mMockBehaviorController).onModeDeactivated();
- verifyNoMoreInteractions(mMockBehaviorController);
+ verify(mMockTestBehavior).onModeDeactivated();
+ verifyNoMoreInteractions(mMockTestBehavior);
}
@Test
@@ -346,6 +365,6 @@
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
- verifyNoMoreInteractions(mMockBehaviorController);
+ verifyNoMoreInteractions(mMockTestBehavior);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java
new file mode 100644
index 0000000..c53289c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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.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 WakefulnessLifecycle mMockWakefulnessLifecycle;
+ @Mock private SysUiState mMockSysUiState;
+ @Mock private AssistHandleCallbacks mMockAssistHandleCallbacks;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mAssistHandleLikeHomeBehavior = new AssistHandleLikeHomeBehavior(
+ () -> mMockWakefulnessLifecycle, () -> mMockSysUiState);
+ }
+
+ @Test
+ public void onModeActivated_beginsObserving() {
+ // Arrange
+
+ // Act
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+
+ // Assert
+ verify(mMockWakefulnessLifecycle).getWakefulness();
+ verify(mMockWakefulnessLifecycle).addObserver(any(WakefulnessLifecycle.Observer.class));
+ verify(mMockSysUiState).addCallback(any(SysUiState.SysUiStateCallback.class));
+ verifyNoMoreInteractions(mMockWakefulnessLifecycle, mMockSysUiState);
+ }
+
+ @Test
+ public void onModeActivated_showsHandlesWhenAwake() {
+ // Arrange
+ 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(mMockWakefulnessLifecycle.getWakefulness())
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP);
+
+ // Act
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+
+ // Assert
+ verify(mMockAssistHandleCallbacks).hide();
+ verifyNoMoreInteractions(mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onModeDeactivated_stopsObserving() {
+ // Arrange
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+ ArgumentCaptor<WakefulnessLifecycle.Observer> observer =
+ ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
+ ArgumentCaptor<SysUiState.SysUiStateCallback> sysUiStateCallback =
+ ArgumentCaptor.forClass(SysUiState.SysUiStateCallback.class);
+ verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
+ verify(mMockSysUiState).addCallback(sysUiStateCallback.capture());
+ reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ mAssistHandleLikeHomeBehavior.onModeDeactivated();
+
+ // Assert
+ verify(mMockWakefulnessLifecycle).removeObserver(eq(observer.getValue()));
+ verify(mMockSysUiState).removeCallback(eq(sysUiStateCallback.getValue()));
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onAssistantGesturePerformed_doesNothing() {
+ // Arrange
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+ reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ mAssistHandleLikeHomeBehavior.onAssistantGesturePerformed();
+
+ // Assert
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onAssistHandlesRequested_doesNothing() {
+ // Arrange
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+ reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ mAssistHandleLikeHomeBehavior.onAssistHandlesRequested();
+
+ // Assert
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onWake_handlesShow() {
+ // Arrange
+ when(mMockWakefulnessLifecycle.getWakefulness())
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP);
+ ArgumentCaptor<WakefulnessLifecycle.Observer> observer =
+ ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+ verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
+ reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ observer.getValue().onStartedWakingUp();
+
+ // Assert
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ observer.getValue().onFinishedWakingUp();
+
+ // Assert
+ verify(mMockAssistHandleCallbacks).showAndStay();
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onSleep_handlesHide() {
+ // Arrange
+ when(mMockWakefulnessLifecycle.getWakefulness())
+ .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
+ ArgumentCaptor<WakefulnessLifecycle.Observer> observer =
+ ArgumentCaptor.forClass(WakefulnessLifecycle.Observer.class);
+ mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
+ verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
+ reset(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ observer.getValue().onStartedGoingToSleep();
+
+ // Assert
+ verify(mMockAssistHandleCallbacks).hide();
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ observer.getValue().onFinishedGoingToSleep();
+
+ // Assert
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onHomeHandleHide_handlesHide() {
+ // Arrange
+ 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(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ sysUiStateCallback.getValue().onSystemUiStateChanged(
+ QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
+
+ // Assert
+ verify(mMockAssistHandleCallbacks).hide();
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+
+ @Test
+ public void onHomeHandleUnhide_handlesShow() {
+ // Arrange
+ 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(mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+
+ // Act
+ sysUiStateCallback.getValue().onSystemUiStateChanged(
+ ~QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
+
+ // Assert
+ verify(mMockAssistHandleCallbacks).showAndStay();
+ verifyNoMoreInteractions(
+ mMockWakefulnessLifecycle, mMockSysUiState, mMockAssistHandleCallbacks);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleOffBehaviorTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleOffBehaviorTest.java
new file mode 100644
index 0000000..15d4d5b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleOffBehaviorTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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);
+ }
+}