diff options
author | 2019-09-12 15:45:38 +0000 | |
---|---|---|
committer | 2019-09-12 15:45:38 +0000 | |
commit | 17f9fb422cc8cd81a7e896e6891267b5d34cb0a9 (patch) | |
tree | 6bcdb3f889f10ab39a2b25e06334f9c934b67120 | |
parent | 636ae6a3863003850b2860e0e4abbb0891160885 (diff) | |
parent | 3fcd71785e84db5a12dede8ab7702b31b080c2f2 (diff) |
Merge "Trigger doze detection using WakefulnessLifecycle" into qt-qpr1-dev
11 files changed, 628 insertions, 108 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/SystemUIModule.java index edd2463984c8..defa5741521e 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.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 diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java index 25d16455a164..738ec80a40c4 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.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 { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java index 6cf2034e6c9b..fa6ffe143022 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java @@ -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) { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java index f4130aeb1d08..df913f9ce9cd 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 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(); diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java index bdc666de4bc7..a567315f0296 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java @@ -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() { diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java index ffe3cc04a150..1a2d062f1b80 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java @@ -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 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 000000000000..2a82d215e44a --- /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 b3f57afc0753..ff76adfd5b6a 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java @@ -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) { 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 a583b1c4308e..20983fc16080 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java @@ -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); } } 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 000000000000..2aa866e2c179 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleLikeHomeBehaviorTest.java @@ -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); + } +} 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 000000000000..15d4d5b4792f --- /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); + } +} |