Merge "Trigger doze detection using WakefulnessLifecycle" into qt-qpr1-dev

am: 17f9fb422c

Change-Id: I1b0d431c1de7d861d14edd649bedd525afe66a86
This commit is contained in:
Govinda Wasserman
2019-09-12 09:22:26 -07:00
committed by android-build-merger
11 changed files with 628 additions and 108 deletions

View File

@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
import com.android.systemui.util.AsyncSensorManager;
@@ -33,7 +34,7 @@ import dagger.Provides;
* 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

View File

@@ -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.annotations.VisibleForTesting;
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 @@ import java.util.function.Supplier;
* 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 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
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 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
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 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null));
}
});
Dependency.get(DumpController.class).addListener(this);
dumpController.addListener(this);
}
@Override // AssistHandleCallbacks
@@ -241,7 +229,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
}
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 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
return;
}
ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
ScreenDecorations screenDecorations = mScreenDecorations.get();
if (screenDecorations == null) {
Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable");
} else {

View File

@@ -20,25 +20,45 @@ import android.content.Context;
import androidx.annotation.Nullable;
import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.recents.OverviewProxyService;
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 OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
@@ -48,32 +68,39 @@ final class AssistHandleLikeHomeBehavior implements BehaviorController {
handleSystemUiStateChange(sysuiStateFlags);
}
};
private final StatusBarStateController mStatusBarStateController;
private final OverviewProxyService mOverviewProxyService;
private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
private final Lazy<OverviewProxyService> mOverviewProxyService;
private boolean mIsDozing;
private boolean mIsHomeHandleHiding;
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
AssistHandleLikeHomeBehavior() {
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
@Inject
AssistHandleLikeHomeBehavior(
Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
Lazy<OverviewProxyService> overviewProxyService) {
mWakefulnessLifecycle = wakefulnessLifecycle;
mOverviewProxyService = overviewProxyService;
}
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
mAssistHandleCallbacks = callbacks;
mIsDozing = mStatusBarStateController.isDozing();
mStatusBarStateController.addCallback(mStatusBarStateListener);
mOverviewProxyService.addCallback(mOverviewProxyListener);
mIsDozing = mWakefulnessLifecycle.get().getWakefulness()
!= WakefulnessLifecycle.WAKEFULNESS_AWAKE;
mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
mOverviewProxyService.get().addCallback(mOverviewProxyListener);
callbackForCurrentState();
}
@Override
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
mOverviewProxyService.removeCallback(mOverviewProxyListener);
mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
}
private static boolean isHomeHandleHiding(int sysuiStateFlags) {

View File

@@ -20,9 +20,17 @@ import android.content.Context;
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();

View File

@@ -16,6 +16,9 @@
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;
@@ -24,14 +27,14 @@ import android.content.Intent;
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.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -46,11 +49,18 @@ import java.util.ArrayList;
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";
@@ -83,11 +93,6 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
public void onStateChanged(int newState) {
handleStatusBarStateChanged(newState);
}
@Override
public void onDozingChanged(boolean isDozing) {
handleDozingChanged(isDozing);
}
};
private final TaskStackChangeListener mTaskStackChangeListener =
new TaskStackChangeListener() {
@@ -113,6 +118,18 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
handleSystemUiStateChanged(sysuiStateFlags);
}
};
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) {
@@ -122,11 +139,14 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
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 Lazy<StatusBarStateController> mStatusBarStateController;
private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
private final Lazy<OverviewProxyService> mOverviewProxyService;
private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;
private boolean mOnLockscreen;
private boolean mIsDozing;
@@ -148,12 +168,24 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
@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<WakefulnessLifecycle> wakefulnessLifecycle,
Lazy<PackageManagerWrapper> packageManagerWrapper) {
mClock = clock;
mHandler = handler;
mPhenotypeHelper = phenotypeHelper;
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mStatusBarStateController = statusBarStateController;
mActivityManagerWrapper = activityManagerWrapper;
mOverviewProxyService = overviewProxyService;
mWakefulnessLifecycle = wakefulnessLifecycle;
mPackageManagerWrapper = packageManagerWrapper;
mDefaultHomeIntentFilter = new IntentFilter();
for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
mDefaultHomeIntentFilter.addAction(action);
@@ -167,13 +199,16 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
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);
mActivityManagerWrapper.get().registerTaskStackListener(mTaskStackChangeListener);
mOverviewProxyService.get().addCallback(mOverviewProxyListener);
mIsDozing = mWakefulnessLifecycle.get().getWakefulness()
!= WakefulnessLifecycle.WAKEFULNESS_AWAKE;
mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
mLearningTimeElapsed = Settings.Secure.getLong(
context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
@@ -181,7 +216,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
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);
}
@@ -196,9 +231,10 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
mContext = null;
}
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
mOverviewProxyService.removeCallback(mOverviewProxyListener);
mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
mActivityManagerWrapper.get().unregisterTaskStackListener(mTaskStackChangeListener);
mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
}
@Override
@@ -218,15 +254,10 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
}
}
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;
}
@@ -282,7 +313,8 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
}
private void handleSystemUiStateChanged(int sysuiStateFlags) {
boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags);
boolean isNavBarHidden =
(sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
if (mIsNavBarHidden == isNavBarHidden) {
return;
}
@@ -369,21 +401,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
return;
}
long currentTimestamp = SystemClock.uptimeMillis();
long currentTimestamp = mClock.currentTimeMillis();
mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
mLastLearningTimestamp = currentTimestamp;
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() {

View File

@@ -19,7 +19,6 @@ import android.os.AsyncTask;
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;
@@ -155,17 +154,18 @@ public class AssistManager implements ConfigurationChangedReceiver {
};
@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

View File

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

View File

@@ -22,8 +22,18 @@ import androidx.annotation.Nullable;
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) {

View File

@@ -37,10 +37,12 @@ import androidx.test.filters.SmallTest;
import com.android.internal.app.AssistUtils;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.DumpController;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.phone.NavigationModeController;
import org.junit.After;
import org.junit.Before;
@@ -50,6 +52,9 @@ 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
@@ -63,7 +68,12 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@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() {
@@ -74,13 +84,23 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
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
@@ -314,8 +334,8 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
verify(mMockBehaviorController).onModeActivated(mContext, mAssistHandleBehaviorController);
verifyNoMoreInteractions(mMockBehaviorController);
verify(mMockTestBehavior).onModeActivated(mContext, mAssistHandleBehaviorController);
verifyNoMoreInteractions(mMockTestBehavior);
}
@Test
@@ -324,14 +344,14 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
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
@@ -344,6 +364,6 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
verifyNoMoreInteractions(mMockBehaviorController);
verifyNoMoreInteractions(mMockTestBehavior);
}
}

View File

@@ -0,0 +1,251 @@
/*
* 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.recents.OverviewProxyService;
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 OverviewProxyService mMockOverviewProxyService;
@Mock private AssistHandleCallbacks mMockAssistHandleCallbacks;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mAssistHandleLikeHomeBehavior = new AssistHandleLikeHomeBehavior(
() -> mMockWakefulnessLifecycle, () -> mMockOverviewProxyService);
}
@Test
public void onModeActivated_beginsObserving() {
// Arrange
// Act
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
// Assert
verify(mMockWakefulnessLifecycle).getWakefulness();
verify(mMockWakefulnessLifecycle).addObserver(any(WakefulnessLifecycle.Observer.class));
verify(mMockOverviewProxyService).addCallback(any(
OverviewProxyService.OverviewProxyListener.class));
verifyNoMoreInteractions(mMockWakefulnessLifecycle, mMockOverviewProxyService);
}
@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<OverviewProxyService.OverviewProxyListener> overviewProxyListener =
ArgumentCaptor.forClass(OverviewProxyService.OverviewProxyListener.class);
verify(mMockWakefulnessLifecycle).addObserver(observer.capture());
verify(mMockOverviewProxyService).addCallback(overviewProxyListener.capture());
reset(mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
mAssistHandleLikeHomeBehavior.onModeDeactivated();
// Assert
verify(mMockWakefulnessLifecycle).removeObserver(eq(observer.getValue()));
verify(mMockOverviewProxyService).removeCallback(eq(overviewProxyListener.getValue()));
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
}
@Test
public void onAssistantGesturePerformed_doesNothing() {
// Arrange
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
mAssistHandleLikeHomeBehavior.onAssistantGesturePerformed();
// Assert
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
}
@Test
public void onAssistHandlesRequested_doesNothing() {
// Arrange
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
reset(mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
mAssistHandleLikeHomeBehavior.onAssistHandlesRequested();
// Assert
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, 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, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
observer.getValue().onStartedWakingUp();
// Assert
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
observer.getValue().onFinishedWakingUp();
// Assert
verify(mMockAssistHandleCallbacks).showAndStay();
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, 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, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
observer.getValue().onStartedGoingToSleep();
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
observer.getValue().onFinishedGoingToSleep();
// Assert
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
}
@Test
public void onHomeHandleHide_handlesHide() {
// Arrange
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
ArgumentCaptor<OverviewProxyService.OverviewProxyListener> sysUiStateCallback =
ArgumentCaptor.forClass(OverviewProxyService.OverviewProxyListener.class);
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
verify(mMockOverviewProxyService).addCallback(sysUiStateCallback.capture());
reset(mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
sysUiStateCallback.getValue().onSystemUiStateChanged(
QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
// Assert
verify(mMockAssistHandleCallbacks).hide();
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
}
@Test
public void onHomeHandleUnhide_handlesShow() {
// Arrange
when(mMockWakefulnessLifecycle.getWakefulness())
.thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE);
ArgumentCaptor<OverviewProxyService.OverviewProxyListener> sysUiStateCallback =
ArgumentCaptor.forClass(OverviewProxyService.OverviewProxyListener.class);
mAssistHandleLikeHomeBehavior.onModeActivated(mContext, mMockAssistHandleCallbacks);
verify(mMockOverviewProxyService).addCallback(sysUiStateCallback.capture());
sysUiStateCallback.getValue().onSystemUiStateChanged(
QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
reset(mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
// Act
sysUiStateCallback.getValue().onSystemUiStateChanged(
~QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN);
// Assert
verify(mMockAssistHandleCallbacks).showAndStay();
verifyNoMoreInteractions(
mMockWakefulnessLifecycle, mMockOverviewProxyService, mMockAssistHandleCallbacks);
}
}

View File

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