diff options
| author | 2019-06-06 21:50:28 +0000 | |
|---|---|---|
| committer | 2019-06-06 21:50:28 +0000 | |
| commit | 4335d958e48161ea2bcbfa6fd93a6dfdf9a46dfe (patch) | |
| tree | a3bd934c2d6457a76c8954c9b43fb8078b02301f | |
| parent | e05421a8f3d337b2af0b10887196d6958b3f7f8c (diff) | |
| parent | 48cdd68afef0e467be3815a824d0406ac4a33f79 (diff) | |
Merge "Improves the REMINDER_EXP mode for Assist Handle behavior" into qt-dev
7 files changed, 488 insertions, 51 deletions
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 48ca766f0da2..8b9072266d16 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -120,6 +120,26 @@ public final class SystemUiDeviceConfigFlags { "assist_handles_show_and_go_duration_ms"; /** + * (long) How long, in milliseconds, to wait before showing the Assist Handles temporarily when + * performing a short delayed show. + */ + public static final String ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = + "assist_handles_show_and_go_delayed_short_delay_ms"; + + /** + * (long) How long, in milliseconds, to wait before showing the Assist Handles temporarily when + * performing a long delayed show. + */ + public static final String ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS = + "assist_handles_show_and_go_delayed_long_delay_ms"; + + /** + * (long) How long, in milliseconds, to wait before resetting delayed show delay times. + */ + public static final String ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS = + "assist_handles_show_and_go_delay_reset_timeout_ms"; + + /** * (long) How long, in milliseconds, to wait before displaying Assist Handles temporarily after * hiding them. */ @@ -138,5 +158,23 @@ public final class SystemUiDeviceConfigFlags { */ public static final String ASSIST_HANDLES_LEARN_COUNT = "assist_handles_learn_count"; + /** + * (bool) Whether to suppress handles on lockscreen." + */ + public static final String ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN = + "assist_handles_suppress_on_lockscreen"; + + /** + * (bool) Whether to suppress handles on launcher." + */ + public static final String ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER = + "assist_handles_suppress_on_launcher"; + + /** + * (bool) Whether to suppress handles on apps." + */ + public static final String ASSIST_HANDLES_SUPPRESS_ON_APPS = + "assist_handles_suppress_on_apps"; + private SystemUiDeviceConfigFlags() { } } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java index 6d109fb59abb..b747998514ed 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java @@ -20,7 +20,6 @@ import android.content.ComponentName; import android.content.Context; import android.os.Handler; import android.os.SystemClock; -import android.provider.DeviceConfig; import android.util.Log; import androidx.annotation.Nullable; @@ -30,11 +29,15 @@ 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; @@ -46,11 +49,11 @@ import java.util.function.Supplier; * Controls when visual handles for Assistant gesture affordance should be shown or hidden using an * {@link AssistHandleBehavior}. */ -public final class AssistHandleBehaviorController implements AssistHandleCallbacks { +public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable { private static final String TAG = "AssistHandleBehavior"; - private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(10); + private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = 0; private static final long DEFAULT_SHOW_AND_GO_DURATION_MS = TimeUnit.SECONDS.toMillis(3); /** @@ -63,7 +66,9 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac private final AssistUtils mAssistUtils; private final Handler mHandler; private final Runnable mHideHandles = this::hideHandles; + private final Runnable mShowAndGo = this::showAndGoInternal; private final Supplier<ScreenDecorations> mScreenDecorationsSupplier; + private final PhenotypeHelper mPhenotypeHelper; private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap = new EnumMap<>(AssistHandleBehavior.class); @@ -80,7 +85,9 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac this( context, assistUtils, - handler, () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class), + handler, + () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class), + new PhenotypeHelper(), /* testBehavior = */ null); } @@ -90,15 +97,18 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac AssistUtils assistUtils, Handler handler, Supplier<ScreenDecorations> screenDecorationsSupplier, + PhenotypeHelper phenotypeHelper, @Nullable BehaviorController testBehavior) { mContext = context; mAssistUtils = assistUtils; mHandler = handler; mScreenDecorationsSupplier = screenDecorationsSupplier; - + mPhenotypeHelper = phenotypeHelper; mBehaviorMap.put(AssistHandleBehavior.OFF, new AssistHandleOffBehavior()); mBehaviorMap.put(AssistHandleBehavior.LIKE_HOME, new AssistHandleLikeHomeBehavior()); - mBehaviorMap.put(AssistHandleBehavior.REMINDER_EXP, new AssistHandleReminderExpBehavior()); + mBehaviorMap.put( + AssistHandleBehavior.REMINDER_EXP, + new AssistHandleReminderExpBehavior(handler, phenotypeHelper)); if (testBehavior != null) { mBehaviorMap.put(AssistHandleBehavior.TEST, testBehavior); } @@ -107,38 +117,48 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac Dependency.get(NavigationModeController.class) .addListener(this::handleNavigationModeChange)); - setBehavior(DeviceConfig.getString( - DeviceConfig.NAMESPACE_SYSTEMUI, - SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, - DEFAULT_BEHAVIOR.toString())); - DeviceConfig.addOnPropertyChangedListener( - DeviceConfig.NAMESPACE_SYSTEMUI, + setBehavior(getBehaviorMode()); + mPhenotypeHelper.addOnPropertiesChangedListener( mHandler::post, - (namespace, name, value) -> { - if (SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE.equals(name)) { - setBehavior(value); + (properties) -> { + if (properties.getKeyset().contains( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE)) { + setBehavior(properties.getString( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null)); } }); + Dependency.get(DumpController.class).addListener(this); } - @Override + @Override // AssistHandleCallbacks public void hide() { - mHandler.removeCallbacks(mHideHandles); + clearPendingCommands(); mHandler.post(mHideHandles); } - @Override + @Override // AssistHandleCallbacks public void showAndGo() { - mHandler.removeCallbacks(mHideHandles); - mHandler.post(() -> { - maybeShowHandles(/* ignoreThreshold = */ false); - mHandler.postDelayed(mHideHandles, getShowAndGoDuration()); - }); + clearPendingCommands(); + mHandler.post(mShowAndGo); + } + + private void showAndGoInternal() { + maybeShowHandles(/* ignoreThreshold = */ false); + mHandler.postDelayed(mHideHandles, getShowAndGoDuration()); + } + + @Override // AssistHandleCallbacks + public void showAndGoDelayed(long delayMs, boolean hideIfShowing) { + clearPendingCommands(); + if (hideIfShowing) { + mHandler.post(mHideHandles); + } + mHandler.postDelayed(mShowAndGo, delayMs); } - @Override + @Override // AssistHandleCallbacks public void showAndStay() { - mHandler.removeCallbacks(mHideHandles); + clearPendingCommands(); mHandler.post(() -> maybeShowHandles(/* ignoreThreshold = */ true)); } @@ -178,37 +198,41 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac private boolean handlesUnblocked(boolean ignoreThreshold) { long timeSinceHidden = SystemClock.elapsedRealtime() - mHandlesLastHiddenAt; - boolean notThrottled = ignoreThreshold || timeSinceHidden > getShownFrequencyThreshold(); + boolean notThrottled = ignoreThreshold || timeSinceHidden >= getShownFrequencyThreshold(); ComponentName assistantComponent = mAssistUtils.getAssistComponentForUser(KeyguardUpdateMonitor.getCurrentUser()); return notThrottled && assistantComponent != null; } private long getShownFrequencyThreshold() { - return DeviceConfig.getLong( - DeviceConfig.NAMESPACE_SYSTEMUI, + return mPhenotypeHelper.getLong( SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS, DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS); } private long getShowAndGoDuration() { - return DeviceConfig.getLong( - DeviceConfig.NAMESPACE_SYSTEMUI, + return mPhenotypeHelper.getLong( SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS, DEFAULT_SHOW_AND_GO_DURATION_MS); } + private String getBehaviorMode() { + return mPhenotypeHelper.getString( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, + DEFAULT_BEHAVIOR.toString()); + } + private void maybeShowHandles(boolean ignoreThreshold) { if (mHandlesShowing) { return; } if (handlesUnblocked(ignoreThreshold)) { - mHandlesShowing = true; ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get(); if (screenDecorations == null) { Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable"); } else { + mHandlesShowing = true; screenDecorations.setAssistHintVisible(true); } } @@ -244,14 +268,46 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac } } + private void clearPendingCommands() { + mHandler.removeCallbacks(mHideHandles); + mHandler.removeCallbacks(mShowAndGo); + } + @VisibleForTesting void setInGesturalModeForTest(boolean inGesturalMode) { mInGesturalMode = inGesturalMode; } + @Override // Dumpable + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("Current AssistHandleBehaviorController State:"); + + pw.println(" mHandlesShowing=" + mHandlesShowing); + pw.println(" mHandlesLastHiddenAt=" + mHandlesLastHiddenAt); + pw.println(" mInGesturalMode=" + mInGesturalMode); + + pw.println(" Phenotype Flags:"); + pw.println(" " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS + + "=" + + getShowAndGoDuration()); + pw.println(" " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS + + "=" + + getShownFrequencyThreshold()); + pw.println(" " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE + + "=" + + getBehaviorMode()); + + pw.println(" mCurrentBehavior=" + mCurrentBehavior.toString()); + mBehaviorMap.get(mCurrentBehavior).dump(pw, " "); + } + interface BehaviorController { void onModeActivated(Context context, AssistHandleCallbacks callbacks); default void onModeDeactivated() {} default void onAssistantGesturePerformed() {} + default void dump(PrintWriter pw, String prefix) {} } } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleCallbacks.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleCallbacks.java index 0577d37217e2..3db861d57268 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleCallbacks.java @@ -29,6 +29,13 @@ public interface AssistHandleCallbacks { */ void showAndGo(); + /** + * Same as show and go, but will not do anything until a delay has elapsed. + * + * Will be cancelled if another command is given during the delay. + */ + void showAndGoDelayed(long delayMs, boolean hideIfShowing); + /** Show the Assistant handles. */ void showAndStay(); } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java index 05e504c93b82..6cf2034e6c9b 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java @@ -26,6 +26,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.system.QuickStepContract; +import java.io.PrintWriter; + /** * Assistant Handle behavior that makes Assistant handles show/hide when the home handle is * shown/hidden, respectively. @@ -108,4 +110,12 @@ final class AssistHandleLikeHomeBehavior implements BehaviorController { mAssistHandleCallbacks.showAndStay(); } } + + @Override + public void dump(PrintWriter pw, String prefix) { + pw.println("Current AssistHandleLikeHomeBehavior State:"); + + pw.println(prefix + " mIsDozing=" + mIsDozing); + pw.println(prefix + " mIsHomeHandleHiding=" + mIsHomeHandleHiding); + } } diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java index 4b6a6dcee91d..87fb28b4c65e 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java @@ -16,11 +16,16 @@ package com.android.systemui.assist; +import static com.android.systemui.shared.system.PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED; + import android.app.ActivityManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Handler; import android.os.SystemClock; -import android.provider.DeviceConfig; import android.provider.Settings; import androidx.annotation.Nullable; @@ -31,10 +36,14 @@ import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorContro import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.StatusBarState; +import java.io.PrintWriter; +import java.time.LocalDate; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; /** @@ -46,8 +55,18 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed"; private static final String LEARNING_EVENT_COUNT_KEY = "reminder_exp_learning_event_count"; - private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(3); - private static final int DEFAULT_LEARNING_COUNT = 3; + private static final String LEARNED_HINT_LAST_SHOWN_KEY = + "reminder_exp_learned_hint_last_shown"; + private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(200); + private static final int DEFAULT_LEARNING_COUNT = 30000; + private static final long DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = 150; + private static final long DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS = + TimeUnit.SECONDS.toMillis(1); + private static final long DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS = + TimeUnit.SECONDS.toMillis(3); + private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false; + private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false; + private static final boolean DEFAULT_SUPPRESS_ON_APPS = false; private final StatusBarStateController.StateListener mStatusBarStateListener = new StatusBarStateController.StateListener() { @@ -64,13 +83,13 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { private final TaskStackChangeListener mTaskStackChangeListener = new TaskStackChangeListener() { @Override - public void onTaskMovedToFront(int taskId) { - handleTaskStackTopChanged(taskId); + public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) { + handleTaskStackTopChanged(taskInfo.taskId, taskInfo.topActivity); } @Override public void onTaskCreated(int taskId, ComponentName componentName) { - handleTaskStackTopChanged(taskId); + handleTaskStackTopChanged(taskId, componentName); } }; private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener = @@ -85,7 +104,18 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { handleSystemUiStateChanged(sysuiStateFlags); } }; + private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + mDefaultHome = getCurrentDefaultHome(); + } + }; + private final IntentFilter mDefaultHomeIntentFilter = + new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED); + private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches; + private final Handler mHandler; + private final PhenotypeHelper mPhenotypeHelper; private final StatusBarStateController mStatusBarStateController; private final ActivityManagerWrapper mActivityManagerWrapper; private final OverviewProxyService mOverviewProxyService; @@ -94,6 +124,8 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { private boolean mIsDozing; private int mRunningTaskId; private boolean mIsNavBarHidden; + private boolean mIsLauncherShowing; + private int mConsecutiveTaskSwitches; /** Whether user has learned the gesture. */ private boolean mIsLearned; @@ -102,11 +134,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { private long mLearningTimeElapsed; /** Number of successful Assistant invocations while in this behavior. */ private int mLearningCount; + private long mLearnedHintLastShownEpochDay; @Nullable private Context mContext; @Nullable private AssistHandleCallbacks mAssistHandleCallbacks; + @Nullable private ComponentName mDefaultHome; - AssistHandleReminderExpBehavior() { + AssistHandleReminderExpBehavior(Handler handler, PhenotypeHelper phenotypeHelper) { + mHandler = handler; + mPhenotypeHelper = phenotypeHelper; mStatusBarStateController = Dependency.get(StatusBarStateController.class); mActivityManagerWrapper = ActivityManagerWrapper.getInstance(); mOverviewProxyService = Dependency.get(OverviewProxyService.class); @@ -116,6 +152,9 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { public void onModeActivated(Context context, AssistHandleCallbacks callbacks) { mContext = context; mAssistHandleCallbacks = callbacks; + mConsecutiveTaskSwitches = 0; + mDefaultHome = getCurrentDefaultHome(); + context.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter); mOnLockscreen = onLockscreen(mStatusBarStateController.getState()); mIsDozing = mStatusBarStateController.isDozing(); mStatusBarStateController.addCallback(mStatusBarStateListener); @@ -128,6 +167,8 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0); mLearningCount = Settings.Secure.getInt( context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0); + mLearnedHintLastShownEpochDay = Settings.Secure.getLong( + context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0); mLastLearningTimestamp = SystemClock.uptimeMillis(); callbackForCurrentState(/* justUnlocked = */ false); @@ -137,10 +178,10 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { public void onModeDeactivated() { mAssistHandleCallbacks = null; if (mContext != null) { - Settings.Secure.putLong( - mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed); - Settings.Secure.putInt( - mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, mLearningCount); + mContext.unregisterReceiver(mDefaultHomeBroadcastReceiver); + Settings.Secure.putLong(mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, 0); + Settings.Secure.putInt(mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, 0); + Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0); mContext = null; } mStatusBarStateController.removeCallback(mStatusBarStateListener); @@ -162,12 +203,18 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0; } + @Nullable + private static ComponentName getCurrentDefaultHome() { + return PackageManagerWrapper.getInstance().getHomeActivities(new ArrayList<>()); + } + private void handleStatusBarStateChanged(int newState) { boolean onLockscreen = onLockscreen(newState); if (mOnLockscreen == onLockscreen) { return; } + resetConsecutiveTaskSwitches(); mOnLockscreen = onLockscreen; callbackForCurrentState(!onLockscreen); } @@ -177,16 +224,24 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { return; } + resetConsecutiveTaskSwitches(); mIsDozing = isDozing; callbackForCurrentState(/* justUnlocked = */ false); } - private void handleTaskStackTopChanged(int taskId) { - if (mRunningTaskId == taskId) { + private void handleTaskStackTopChanged(int taskId, @Nullable ComponentName taskComponentName) { + if (mRunningTaskId == taskId || taskComponentName == null) { return; } mRunningTaskId = taskId; + mIsLauncherShowing = taskComponentName.equals(mDefaultHome); + if (mIsLauncherShowing) { + resetConsecutiveTaskSwitches(); + } else { + rescheduleConsecutiveTaskSwitchesReset(); + mConsecutiveTaskSwitches++; + } callbackForCurrentState(/* justUnlocked = */ false); } @@ -196,11 +251,13 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { return; } + resetConsecutiveTaskSwitches(); mIsNavBarHidden = isNavBarHidden; callbackForCurrentState(/* justUnlocked = */ false); } private void handleOverviewShown() { + resetConsecutiveTaskSwitches(); callbackForCurrentState(/* justUnlocked = */ false); } @@ -227,7 +284,17 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { if (mIsDozing || mIsNavBarHidden || mOnLockscreen) { mAssistHandleCallbacks.hide(); } else if (justUnlocked) { - mAssistHandleCallbacks.showAndGo(); + long currentEpochDay = LocalDate.now().toEpochDay(); + if (mLearnedHintLastShownEpochDay < currentEpochDay) { + if (mContext != null) { + Settings.Secure.putLong( + mContext.getContentResolver(), + LEARNED_HINT_LAST_SHOWN_KEY, + currentEpochDay); + } + mLearnedHintLastShownEpochDay = currentEpochDay; + mAssistHandleCallbacks.showAndGo(); + } } } @@ -236,12 +303,28 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { return; } - if (mIsDozing || mIsNavBarHidden) { + if (mIsDozing || mIsNavBarHidden || isSuppressed()) { mAssistHandleCallbacks.hide(); } else if (mOnLockscreen) { mAssistHandleCallbacks.showAndStay(); - } else { + } else if (mIsLauncherShowing) { mAssistHandleCallbacks.showAndGo(); + } else if (mConsecutiveTaskSwitches == 1) { + mAssistHandleCallbacks.showAndGoDelayed( + getShowAndGoDelayedShortDelayMs(), /* hideIfShowing = */ false); + } else { + mAssistHandleCallbacks.showAndGoDelayed( + getShowAndGoDelayedLongDelayMs(), /* hideIfShowing = */ true); + } + } + + private boolean isSuppressed() { + if (mOnLockscreen) { + return getSuppressOnLockscreen(); + } else if (mIsLauncherShowing) { + return getSuppressOnLauncher(); + } else { + return getSuppressOnApps(); } } @@ -260,17 +343,114 @@ final class AssistHandleReminderExpBehavior implements BehaviorController { mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs(); } + private void resetConsecutiveTaskSwitches() { + mHandler.removeCallbacks(mResetConsecutiveTaskSwitches); + mConsecutiveTaskSwitches = 0; + } + + private void rescheduleConsecutiveTaskSwitchesReset() { + mHandler.removeCallbacks(mResetConsecutiveTaskSwitches); + mHandler.postDelayed(mResetConsecutiveTaskSwitches, getShowAndGoDelayResetTimeoutMs()); + } + private long getLearningTimeMs() { - return DeviceConfig.getLong( - DeviceConfig.NAMESPACE_SYSTEMUI, + return mPhenotypeHelper.getLong( SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS, DEFAULT_LEARNING_TIME_MS); } private int getLearningCount() { - return DeviceConfig.getInt( - DeviceConfig.NAMESPACE_SYSTEMUI, + return mPhenotypeHelper.getInt( SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT, DEFAULT_LEARNING_COUNT); } + + private long getShowAndGoDelayedShortDelayMs() { + return mPhenotypeHelper.getLong( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS, + DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS); + } + + private long getShowAndGoDelayedLongDelayMs() { + return mPhenotypeHelper.getLong( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS, + DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS); + } + + private long getShowAndGoDelayResetTimeoutMs() { + return mPhenotypeHelper.getLong( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS, + DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS); + } + + private boolean getSuppressOnLockscreen() { + return mPhenotypeHelper.getBoolean( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN, + DEFAULT_SUPPRESS_ON_LOCKSCREEN); + } + + private boolean getSuppressOnLauncher() { + return mPhenotypeHelper.getBoolean( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER, + DEFAULT_SUPPRESS_ON_LAUNCHER); + } + + private boolean getSuppressOnApps() { + return mPhenotypeHelper.getBoolean( + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS, + DEFAULT_SUPPRESS_ON_APPS); + } + + @Override + public void dump(PrintWriter pw, String prefix) { + pw.println(prefix + "Current AssistHandleReminderExpBehavior State:"); + pw.println(prefix + " mOnLockscreen=" + mOnLockscreen); + pw.println(prefix + " mIsDozing=" + mIsDozing); + pw.println(prefix + " mRunningTaskId=" + mRunningTaskId); + pw.println(prefix + " mDefaultHome=" + mDefaultHome); + pw.println(prefix + " mIsNavBarHidden=" + mIsNavBarHidden); + pw.println(prefix + " mIsLauncherShowing=" + mIsLauncherShowing); + pw.println(prefix + " mConsecutiveTaskSwitches=" + mConsecutiveTaskSwitches); + pw.println(prefix + " mIsLearned=" + mIsLearned); + pw.println(prefix + " mLastLearningTimestamp=" + mLastLearningTimestamp); + pw.println(prefix + " mLearningTimeElapsed=" + mLearningTimeElapsed); + pw.println(prefix + " mLearningCount=" + mLearningCount); + pw.println(prefix + " mLearnedHintLastShownEpochDay=" + mLearnedHintLastShownEpochDay); + pw.println( + prefix + " mAssistHandleCallbacks present: " + (mAssistHandleCallbacks != null)); + + pw.println(prefix + " Phenotype Flags:"); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS + + "=" + + getLearningTimeMs()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT + + "=" + + getLearningCount()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS + + "=" + + getShowAndGoDelayedShortDelayMs()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS + + "=" + + getShowAndGoDelayedLongDelayMs()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS + + "=" + + getShowAndGoDelayResetTimeoutMs()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN + + "=" + + getSuppressOnLockscreen()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER + + "=" + + getSuppressOnLauncher()); + pw.println(prefix + " " + + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS + + "=" + + getSuppressOnApps()); + } } diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java new file mode 100644 index 000000000000..61395f158aea --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java @@ -0,0 +1,51 @@ +/* + * 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.provider.DeviceConfig; + +import androidx.annotation.Nullable; + +import java.util.concurrent.Executor; + +class PhenotypeHelper { + + PhenotypeHelper() {} + + long getLong(String name, long defaultValue) { + return DeviceConfig.getLong(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + } + + int getInt(String name, int defaultValue) { + return DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + } + + @Nullable + String getString(String name, @Nullable String defaultValue) { + return DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + } + + boolean getBoolean(String name, boolean defaultValue) { + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI, name, defaultValue); + } + + void addOnPropertiesChangedListener( + Executor executor, DeviceConfig.OnPropertiesChangedListener listener) { + DeviceConfig.addOnPropertiesChangedListener( + DeviceConfig.NAMESPACE_SYSTEMUI, executor, listener); + } +} 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 18f114a71a8d..a583b1c4308e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java @@ -20,6 +20,7 @@ import static org.mockito.AdditionalAnswers.answerVoid; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.reset; @@ -35,11 +36,13 @@ import android.testing.TestableLooper.RunWithLooper; import androidx.test.filters.SmallTest; import com.android.internal.app.AssistUtils; +import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.systemui.ScreenDecorations; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -59,6 +62,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { @Mock private ScreenDecorations mMockScreenDecorations; @Mock private AssistUtils mMockAssistUtils; @Mock private Handler mMockHandler; + @Mock private PhenotypeHelper mMockPhenotypeHelper; @Mock private AssistHandleBehaviorController.BehaviorController mMockBehaviorController; @Before @@ -69,14 +73,21 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { doAnswer(answerVoid(Runnable::run)).when(mMockHandler).post(any(Runnable.class)); doAnswer(answerVoid(Runnable::run)).when(mMockHandler) .postDelayed(any(Runnable.class), anyLong()); + mAssistHandleBehaviorController = new AssistHandleBehaviorController( mContext, mMockAssistUtils, mMockHandler, () -> mMockScreenDecorations, + mMockPhenotypeHelper, mMockBehaviorController); } + @After + public void teardown() { + mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF); + } + @Test public void hide_hidesHandlesWhenShowing() { // Arrange @@ -185,6 +196,9 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { public void showAndGo_doesNothingIfRecentlyHidden() { // Arrange when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); + when(mMockPhenotypeHelper.getLong( + eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS), + anyLong())).thenReturn(10000L); mAssistHandleBehaviorController.showAndGo(); reset(mMockScreenDecorations); @@ -210,6 +224,87 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { } @Test + public void showAndGoDelayed_showsThenHidesHandlesWhenHiding() { + // Arrange + when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); + mAssistHandleBehaviorController.hide(); + reset(mMockScreenDecorations); + + // Act + mAssistHandleBehaviorController.showAndGoDelayed(1000, false); + + // Assert + InOrder inOrder = inOrder(mMockScreenDecorations); + inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true); + inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void showAndGoDelayed_hidesHandlesAfterTimeoutWhenShowing() { + // Arrange + when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); + mAssistHandleBehaviorController.showAndStay(); + reset(mMockScreenDecorations); + + // Act + mAssistHandleBehaviorController.showAndGoDelayed(1000, false); + + // Assert + verify(mMockScreenDecorations).setAssistHintVisible(false); + verifyNoMoreInteractions(mMockScreenDecorations); + } + + @Test + public void showAndGoDelayed_hidesInitiallyThenShowsThenHidesAfterTimeoutWhenHideRequested() { + // Arrange + when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); + mAssistHandleBehaviorController.showAndStay(); + reset(mMockScreenDecorations); + + // Act + mAssistHandleBehaviorController.showAndGoDelayed(1000, true); + + // Assert + InOrder inOrder = inOrder(mMockScreenDecorations); + inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false); + inOrder.verify(mMockScreenDecorations).setAssistHintVisible(true); + inOrder.verify(mMockScreenDecorations).setAssistHintVisible(false); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void showAndGoDelayed_doesNothingIfRecentlyHidden() { + // Arrange + when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); + when(mMockPhenotypeHelper.getLong( + eq(SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS), + anyLong())).thenReturn(10000L); + mAssistHandleBehaviorController.showAndGo(); + reset(mMockScreenDecorations); + + // Act + mAssistHandleBehaviorController.showAndGoDelayed(1000, false); + + // Assert + verifyNoMoreInteractions(mMockScreenDecorations); + } + + @Test + public void showAndGoDelayed_doesNothingWhenThereIsNoAssistant() { + // Arrange + when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null); + mAssistHandleBehaviorController.hide(); + reset(mMockScreenDecorations); + + // Act + mAssistHandleBehaviorController.showAndGoDelayed(1000, false); + + // Assert + verifyNoMoreInteractions(mMockScreenDecorations); + } + + @Test public void setBehavior_activatesTheBehaviorWhenInGesturalMode() { // Arrange when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME); |