Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f606b09 authored by Govinda Wasserman's avatar Govinda Wasserman
Browse files

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
parent 43110221
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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() { }
}
+17 −28
Original line number Diff line number Diff line
@@ -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() {}
    }
}
+0 −5
Original line number Diff line number Diff line
@@ -27,9 +27,4 @@ final class AssistHandleOffBehavior implements BehaviorController {
    public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
        callbacks.hide();
    }

    @Override
    public void onModeDeactivated() {
        // Do nothing
    }
}
+103 −7
Original line number Diff line number Diff line
@@ -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);
    }
}
+5 −1
Original line number Diff line number Diff line
@@ -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);
    }