summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2019-06-06 21:50:28 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2019-06-06 21:50:28 +0000
commit4335d958e48161ea2bcbfa6fd93a6dfdf9a46dfe (patch)
treea3bd934c2d6457a76c8954c9b43fb8078b02301f
parente05421a8f3d337b2af0b10887196d6958b3f7f8c (diff)
parent48cdd68afef0e467be3815a824d0406ac4a33f79 (diff)
Merge "Improves the REMINDER_EXP mode for Assist Handle behavior" into qt-dev
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java118
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleCallbacks.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java220
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/PhenotypeHelper.java51
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java95
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);