Adds learned state to the Reminder Experience for Assistant Handles

am: 1f606b099e

Change-Id: I9e23630e82a3cc4a060f906d9892cee148f522eb
This commit is contained in:
Govinda Wasserman
2019-05-29 20:42:00 -07:00
committed by android-build-merger
5 changed files with 137 additions and 41 deletions

View File

@@ -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() { }
}

View File

@@ -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() {}
}
}

View File

@@ -27,9 +27,4 @@ final class AssistHandleOffBehavior implements BehaviorController {
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
callbacks.hide();
}
@Override
public void onModeDeactivated() {
// Do nothing
}
}

View File

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

View File

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