Adds learned state to the Reminder Experience for Assistant Handles
Also sets the Reminder Experience as the default behavior. Test: Tested locally BUG:132983599 Change-Id: I27b063ca142fbde99b0bd1f6d107f45d6070869a
This commit is contained in:
@@ -133,5 +133,17 @@ public final class SystemUiDeviceConfigFlags {
|
||||
public static final String ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS =
|
||||
"assist_handles_shown_frequency_threshold_ms";
|
||||
|
||||
/**
|
||||
* (long) How long, in milliseconds, for teaching behaviors to wait before considering the user
|
||||
* taught.
|
||||
*/
|
||||
public static final String ASSIST_HANDLES_LEARN_TIME_MS = "assist_handles_learn_time_ms";
|
||||
|
||||
/**
|
||||
* (int) How many times for teaching behaviors to see the user perform an action to consider it
|
||||
* taught.
|
||||
*/
|
||||
public static final String ASSIST_HANDLES_LEARN_COUNT = "assist_handles_learn_count";
|
||||
|
||||
private SystemUiDeviceConfigFlags() { }
|
||||
}
|
||||
|
||||
@@ -16,11 +16,7 @@
|
||||
|
||||
package com.android.systemui.assist;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
@@ -37,7 +33,6 @@ import com.android.systemui.SysUiServiceProvider;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.statusbar.phone.NavigationModeController;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -51,18 +46,17 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
|
||||
private static final String TAG = "AssistHandleBehavior";
|
||||
|
||||
private static final boolean IS_DEBUG_DEVICE =
|
||||
Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
|
||||
|| Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
|
||||
|
||||
private static final String SHOWN_FREQUENCY_THRESHOLD_KEY =
|
||||
"ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS";
|
||||
private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(10);
|
||||
private static final String SHOW_AND_GO_DURATION_KEY = "ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS";
|
||||
private static final long DEFAULT_SHOW_AND_GO_DURATION_MS = TimeUnit.SECONDS.toMillis(3);
|
||||
private static final String BEHAVIOR_KEY = "behavior";
|
||||
private static final String SET_BEHAVIOR_ACTION =
|
||||
"com.android.systemui.SET_ASSIST_HANDLE_BEHAVIOR";
|
||||
|
||||
/**
|
||||
* This is the default behavior that will be used once the system is up. It will be set once the
|
||||
* behavior dependencies are available. This ensures proper behavior lifecycle.
|
||||
*/
|
||||
private static final AssistHandleBehavior DEFAULT_BEHAVIOR = AssistHandleBehavior.REMINDER_EXP;
|
||||
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
@@ -71,6 +65,10 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
|
||||
private boolean mHandlesShowing = false;
|
||||
private long mHandlesLastHiddenAt;
|
||||
/**
|
||||
* This should always be initialized as {@link AssistHandleBehavior#OFF} to ensure proper
|
||||
* behavior lifecycle.
|
||||
*/
|
||||
private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF;
|
||||
private boolean mInGesturalMode;
|
||||
|
||||
@@ -95,7 +93,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
setBehavior(DeviceConfig.getString(
|
||||
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE,
|
||||
mCurrentBehavior.toString()));
|
||||
DEFAULT_BEHAVIOR.toString()));
|
||||
DeviceConfig.addOnPropertyChangedListener(
|
||||
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
mHandler::post,
|
||||
@@ -104,20 +102,6 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
setBehavior(value);
|
||||
}
|
||||
});
|
||||
|
||||
if (IS_DEBUG_DEVICE) {
|
||||
context.registerReceiver(new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String behaviorString = intent.getExtras().getString(BEHAVIOR_KEY);
|
||||
try {
|
||||
setBehavior(AssistHandleBehavior.valueOf(behaviorString));
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Invalid behavior identifier: " + behaviorString);
|
||||
}
|
||||
}
|
||||
}, new IntentFilter(SET_BEHAVIOR_ACTION));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,6 +125,10 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
mHandler.post(() -> maybeShowHandles(/* ignoreThreshold = */ true));
|
||||
}
|
||||
|
||||
void onAssistantGesturePerformed() {
|
||||
mCurrentBehavior.getController().onAssistantGesturePerformed();
|
||||
}
|
||||
|
||||
void setBehavior(AssistHandleBehavior behavior) {
|
||||
if (mCurrentBehavior == behavior) {
|
||||
return;
|
||||
@@ -233,6 +221,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
|
||||
|
||||
interface BehaviorController {
|
||||
void onModeActivated(Context context, AssistHandleCallbacks callbacks);
|
||||
void onModeDeactivated();
|
||||
default void onModeDeactivated() {}
|
||||
default void onAssistantGesturePerformed() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,4 @@ final class AssistHandleOffBehavior implements BehaviorController {
|
||||
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
|
||||
callbacks.hide();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModeDeactivated() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,13 @@ package com.android.systemui.assist;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
@@ -31,6 +35,8 @@ import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.statusbar.StatusBarState;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -38,6 +44,11 @@ import com.android.systemui.statusbar.StatusBarState;
|
||||
*/
|
||||
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 final StatusBarStateController.StateListener mStatusBarStateListener =
|
||||
new StatusBarStateController.StateListener() {
|
||||
@Override
|
||||
@@ -84,6 +95,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
private int mRunningTaskId;
|
||||
private boolean mIsNavBarHidden;
|
||||
|
||||
/** Whether user has learned the gesture. */
|
||||
private boolean mIsLearned;
|
||||
private long mLastLearningTimestamp;
|
||||
/** Uptime while in this behavior. */
|
||||
private long mLearningTimeElapsed;
|
||||
/** Number of successful Assistant invocations while in this behavior. */
|
||||
private int mLearningCount;
|
||||
|
||||
@Nullable private Context mContext;
|
||||
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
|
||||
|
||||
AssistHandleReminderExpBehavior() {
|
||||
@@ -94,6 +114,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
|
||||
@Override
|
||||
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
|
||||
mContext = context;
|
||||
mAssistHandleCallbacks = callbacks;
|
||||
mOnLockscreen = onLockscreen(mStatusBarStateController.getState());
|
||||
mIsDozing = mStatusBarStateController.isDozing();
|
||||
@@ -102,17 +123,41 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
|
||||
mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
|
||||
mOverviewProxyService.addCallback(mOverviewProxyListener);
|
||||
callbackForCurrentState();
|
||||
|
||||
mLearningTimeElapsed = Settings.Secure.getLong(
|
||||
context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
|
||||
mLearningCount = Settings.Secure.getInt(
|
||||
context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0);
|
||||
mLastLearningTimestamp = SystemClock.uptimeMillis();
|
||||
|
||||
callbackForCurrentState(/* justUnlocked = */ false);
|
||||
}
|
||||
|
||||
@Override
|
||||
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 = null;
|
||||
}
|
||||
mStatusBarStateController.removeCallback(mStatusBarStateListener);
|
||||
mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
|
||||
mOverviewProxyService.removeCallback(mOverviewProxyListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAssistantGesturePerformed() {
|
||||
if (mContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Settings.Secure.putLong(
|
||||
mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, ++mLearningCount);
|
||||
}
|
||||
|
||||
private static boolean isNavBarHidden(int sysuiStateFlags) {
|
||||
return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
|
||||
}
|
||||
@@ -124,7 +169,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
}
|
||||
|
||||
mOnLockscreen = onLockscreen;
|
||||
callbackForCurrentState();
|
||||
callbackForCurrentState(!onLockscreen);
|
||||
}
|
||||
|
||||
private void handleDozingChanged(boolean isDozing) {
|
||||
@@ -133,7 +178,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
}
|
||||
|
||||
mIsDozing = isDozing;
|
||||
callbackForCurrentState();
|
||||
callbackForCurrentState(/* justUnlocked = */ false);
|
||||
}
|
||||
|
||||
private void handleTaskStackTopChanged(int taskId) {
|
||||
@@ -142,7 +187,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
}
|
||||
|
||||
mRunningTaskId = taskId;
|
||||
callbackForCurrentState();
|
||||
callbackForCurrentState(/* justUnlocked = */ false);
|
||||
}
|
||||
|
||||
private void handleSystemUiStateChanged(int sysuiStateFlags) {
|
||||
@@ -152,11 +197,11 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
}
|
||||
|
||||
mIsNavBarHidden = isNavBarHidden;
|
||||
callbackForCurrentState();
|
||||
callbackForCurrentState(/* justUnlocked = */ false);
|
||||
}
|
||||
|
||||
private void handleOverviewShown() {
|
||||
callbackForCurrentState();
|
||||
callbackForCurrentState(/* justUnlocked = */ false);
|
||||
}
|
||||
|
||||
private boolean onLockscreen(int statusBarState) {
|
||||
@@ -164,7 +209,29 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
|| statusBarState == StatusBarState.SHADE_LOCKED;
|
||||
}
|
||||
|
||||
private void callbackForCurrentState() {
|
||||
private void callbackForCurrentState(boolean justUnlocked) {
|
||||
updateLearningStatus();
|
||||
|
||||
if (mIsLearned) {
|
||||
callbackForLearnedState(justUnlocked);
|
||||
} else {
|
||||
callbackForUnlearnedState();
|
||||
}
|
||||
}
|
||||
|
||||
private void callbackForLearnedState(boolean justUnlocked) {
|
||||
if (mAssistHandleCallbacks == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsDozing || mIsNavBarHidden || mOnLockscreen) {
|
||||
mAssistHandleCallbacks.hide();
|
||||
} else if (justUnlocked) {
|
||||
mAssistHandleCallbacks.showAndGo();
|
||||
}
|
||||
}
|
||||
|
||||
private void callbackForUnlearnedState() {
|
||||
if (mAssistHandleCallbacks == null) {
|
||||
return;
|
||||
}
|
||||
@@ -177,4 +244,33 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|
||||
mAssistHandleCallbacks.showAndGo();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLearningStatus() {
|
||||
if (mContext == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
long currentTimestamp = SystemClock.uptimeMillis();
|
||||
mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
|
||||
mLastLearningTimestamp = currentTimestamp;
|
||||
Settings.Secure.putLong(
|
||||
mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed);
|
||||
|
||||
mIsLearned =
|
||||
mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();
|
||||
}
|
||||
|
||||
private long getLearningTimeMs() {
|
||||
return DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS,
|
||||
DEFAULT_LEARNING_TIME_MS);
|
||||
}
|
||||
|
||||
private int getLearningCount() {
|
||||
return DeviceConfig.getInt(
|
||||
DeviceConfig.NAMESPACE_SYSTEMUI,
|
||||
SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT,
|
||||
DEFAULT_LEARNING_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,13 +246,17 @@ public class AssistManager implements ConfigurationChangedReceiver {
|
||||
if (args == null) {
|
||||
args = new Bundle();
|
||||
}
|
||||
int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
|
||||
if (invocationType == INVOCATION_TYPE_GESTURE) {
|
||||
mHandleController.onAssistantGesturePerformed();
|
||||
}
|
||||
args.putInt(INVOCATION_PHONE_STATE_KEY, mPhoneStateMonitor.getPhoneState());
|
||||
args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.uptimeMillis());
|
||||
// Logs assistant start with invocation type.
|
||||
MetricsLogger.action(
|
||||
new LogMaker(MetricsEvent.ASSISTANT)
|
||||
.setType(MetricsEvent.TYPE_OPEN).setSubtype(
|
||||
args.getInt(INVOCATION_TYPE_KEY)));
|
||||
invocationType));
|
||||
startAssistInternal(args, assistComponent, isService);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user