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

Commit 61c92d6f authored by Govinda Wasserman's avatar Govinda Wasserman
Browse files

Trigger doze detection using WakefulnessLifecycle

Previously, doze detection used StatusBarStateController, which only
provides a signal at the end of the doze transition. This resulted in
the handles only animating away once the screen was already off. Using
the WakefulnessLifecycle allows for a callback when the transition
begins instead.

Test: Tested locally
BUG:137742178
Change-Id: I289ef5b5081fa96b1c8e82c4373c7654e8df80cb
parent 1eb71b84
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;

import com.android.systemui.assist.AssistModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
@@ -34,7 +35,7 @@ import dagger.Provides;
 * A dagger module for injecting components of System UI that are not overridden by the System UI
 * implementation.
 */
@Module
@Module(includes = {AssistModule.class})
public abstract class SystemUIModule {

    @Singleton
+23 −35
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.assist;

import static com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME;

import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
@@ -28,20 +30,21 @@ import com.android.internal.annotations.VisibleForTesting;
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;
import java.util.function.Supplier;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;

/**
 * A class for managing Assistant handle logic.
@@ -49,6 +52,7 @@ import java.util.function.Supplier;
 * Controls when visual handles for Assistant gesture affordance should be shown or hidden using an
 * {@link AssistHandleBehavior}.
 */
@Singleton
public final class AssistHandleBehaviorController implements AssistHandleCallbacks, Dumpable {

    private static final String TAG = "AssistHandleBehavior";
@@ -67,10 +71,9 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
    private final Handler mHandler;
    private final Runnable mHideHandles = this::hideHandles;
    private final Runnable mShowAndGo = this::showAndGoInternal;
    private final Supplier<ScreenDecorations> mScreenDecorationsSupplier;
    private final Provider<ScreenDecorations> mScreenDecorations;
    private final PhenotypeHelper mPhenotypeHelper;
    private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap =
            new EnumMap<>(AssistHandleBehavior.class);
    private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap;

    private boolean mHandlesShowing = false;
    private long mHandlesLastHiddenAt;
@@ -82,41 +85,25 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
    private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF;
    private boolean mInGesturalMode;

    AssistHandleBehaviorController(Context context, AssistUtils assistUtils, Handler handler) {
        this(
                context,
                assistUtils,
                handler,
                () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class),
                new PhenotypeHelper(),
                /* testBehavior = */ null);
    }

    @VisibleForTesting
    @Inject
    AssistHandleBehaviorController(
            Context context,
            AssistUtils assistUtils,
            Handler handler,
            Supplier<ScreenDecorations> screenDecorationsSupplier,
            @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
            Provider<ScreenDecorations> screenDecorations,
            PhenotypeHelper phenotypeHelper,
            @Nullable BehaviorController testBehavior) {
            Map<AssistHandleBehavior, BehaviorController> behaviorMap,
            NavigationModeController navigationModeController,
            DumpController dumpController) {
        mContext = context;
        mAssistUtils = assistUtils;
        mHandler = handler;
        mScreenDecorationsSupplier = screenDecorationsSupplier;
        mScreenDecorations = screenDecorations;
        mPhenotypeHelper = phenotypeHelper;
        mBehaviorMap.put(AssistHandleBehavior.OFF, new AssistHandleOffBehavior());
        mBehaviorMap.put(AssistHandleBehavior.LIKE_HOME, new AssistHandleLikeHomeBehavior());
        mBehaviorMap.put(
                AssistHandleBehavior.REMINDER_EXP,
                new AssistHandleReminderExpBehavior(handler, phenotypeHelper));
        if (testBehavior != null) {
            mBehaviorMap.put(AssistHandleBehavior.TEST, testBehavior);
        }
        mBehaviorMap = behaviorMap;

        mInGesturalMode = QuickStepContract.isGesturalMode(
                Dependency.get(NavigationModeController.class)
                        .addListener(this::handleNavigationModeChange));
                navigationModeController.addListener(this::handleNavigationModeChange));

        setBehavior(getBehaviorMode());
        mPhenotypeHelper.addOnPropertiesChangedListener(
@@ -128,7 +115,8 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
                                SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE, null));
                    }
                });
        Dependency.get(DumpController.class).registerDumpable(TAG, this);

        dumpController.registerDumpable(TAG, this);
    }

    @Override // AssistHandleCallbacks
@@ -241,7 +229,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
        }

        if (handlesUnblocked(ignoreThreshold)) {
            ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
            ScreenDecorations screenDecorations = mScreenDecorations.get();
            if (screenDecorations == null) {
                Log.w(TAG, "Couldn't show handles, ScreenDecorations unavailable");
            } else {
@@ -256,7 +244,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
            return;
        }

        ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
        ScreenDecorations screenDecorations = mScreenDecorations.get();
        if (screenDecorations == null) {
            Log.w(TAG, "Couldn't hide handles, ScreenDecorations unavailable");
        } else {
+41 −15
Original line number Diff line number Diff line
@@ -20,56 +20,82 @@ import android.content.Context;

import androidx.annotation.Nullable;

import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;

import java.io.PrintWriter;

import javax.inject.Inject;
import javax.inject.Singleton;

import dagger.Lazy;

/**
 * Assistant Handle behavior that makes Assistant handles show/hide when the home handle is
 * shown/hidden, respectively.
 */
@Singleton
final class AssistHandleLikeHomeBehavior implements BehaviorController {

    private final StatusBarStateController.StateListener mStatusBarStateListener =
            new StatusBarStateController.StateListener() {
    private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
            new WakefulnessLifecycle.Observer() {
                @Override
                public void onStartedWakingUp() {
                    handleDozingChanged(/* isDozing = */ true);
                }

                @Override
                public void onFinishedWakingUp() {
                    handleDozingChanged(/* isDozing = */ false);
                }

                @Override
                public void onStartedGoingToSleep() {
                    handleDozingChanged(/* isDozing = */ true);
                }

                @Override
                public void onDozingChanged(boolean isDozing) {
                    handleDozingChanged(isDozing);
                public void onFinishedGoingToSleep() {
                    handleDozingChanged(/* isDozing = */ true);
                }
            };

    private final SysUiState.SysUiStateCallback mSysUiStateCallback =
            this::handleSystemUiStateChange;
    private final StatusBarStateController mStatusBarStateController;
    private final SysUiState mSysUiFlagContainer;

    private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
    private final Lazy<SysUiState> mSysUiFlagContainer;

    private boolean mIsDozing;
    private boolean mIsHomeHandleHiding;

    @Nullable private AssistHandleCallbacks mAssistHandleCallbacks;

    AssistHandleLikeHomeBehavior() {
        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
        mSysUiFlagContainer = Dependency.get(SysUiState.class);
    @Inject
    AssistHandleLikeHomeBehavior(
            Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
            Lazy<SysUiState> sysUiFlagContainer) {
        mWakefulnessLifecycle = wakefulnessLifecycle;
        mSysUiFlagContainer = sysUiFlagContainer;
    }

    @Override
    public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
        mAssistHandleCallbacks = callbacks;
        mIsDozing = mStatusBarStateController.isDozing();
        mStatusBarStateController.addCallback(mStatusBarStateListener);
        mSysUiFlagContainer.addCallback(mSysUiStateCallback);
        mIsDozing = mWakefulnessLifecycle.get().getWakefulness()
                != WakefulnessLifecycle.WAKEFULNESS_AWAKE;
        mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
        mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
        callbackForCurrentState();
    }

    @Override
    public void onModeDeactivated() {
        mAssistHandleCallbacks = null;
        mSysUiFlagContainer.removeCallback(mSysUiStateCallback);
        mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
        mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
    }

    private static boolean isHomeHandleHiding(int sysuiStateFlags) {
+8 −0
Original line number Diff line number Diff line
@@ -20,9 +20,17 @@ import android.content.Context;

import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;

import javax.inject.Inject;
import javax.inject.Singleton;

/** Assistant handle behavior that hides the Assistant handles. */
@Singleton
final class AssistHandleOffBehavior implements BehaviorController {

    @Inject
    AssistHandleOffBehavior() {
    }

    @Override
    public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
        callbacks.hide();
+71 −50
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@

package com.android.systemui.assist;

import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME;
import static com.android.systemui.assist.AssistModule.UPTIME_NAME;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
@@ -26,14 +27,14 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
import android.os.Handler;
import android.os.SystemClock;
import android.provider.Settings;

import androidx.annotation.Nullable;
import androidx.slice.Clock;

import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
@@ -49,11 +50,18 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import dagger.Lazy;

/**
 * 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
 * entering overview.
 */
@Singleton
final class AssistHandleReminderExpBehavior implements BehaviorController {

    private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed";
@@ -86,11 +94,6 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
                public void onStateChanged(int newState) {
                    handleStatusBarStateChanged(newState);
                }

                @Override
                public void onDozingChanged(boolean isDozing) {
                    handleDozingChanged(isDozing);
                }
            };
    private final TaskStackChangeListener mTaskStackChangeListener =
            new TaskStackChangeListener() {
@@ -111,9 +114,20 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
                    handleOverviewShown();
                }
            };

    private final SysUiState.SysUiStateCallback mSysUiStateCallback =
            this::handleSystemUiStateChanged;
    private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
            new WakefulnessLifecycle.Observer() {
                @Override
                public void onFinishedWakingUp() {
                    handleDozingChanged(false);
                }

                @Override
                public void onStartedGoingToSleep() {
                    handleDozingChanged(true);
                }
    };
    private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -123,12 +137,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
    private final IntentFilter mDefaultHomeIntentFilter;
    private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches;

    private final Clock mClock;
    private final Handler mHandler;
    private final PhenotypeHelper mPhenotypeHelper;
    private final StatusBarStateController mStatusBarStateController;
    private final ActivityManagerWrapper mActivityManagerWrapper;
    private final OverviewProxyService mOverviewProxyService;
    private final SysUiState mSysUiFlagContainer;
    private final Lazy<StatusBarStateController> mStatusBarStateController;
    private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
    private final Lazy<OverviewProxyService> mOverviewProxyService;
    private final Lazy<SysUiState> mSysUiFlagContainer;
    private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
    private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;

    private boolean mOnLockscreen;
    private boolean mIsDozing;
@@ -150,13 +167,26 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
    @Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
    @Nullable private ComponentName mDefaultHome;

    AssistHandleReminderExpBehavior(Handler handler, PhenotypeHelper phenotypeHelper) {
    @Inject
    AssistHandleReminderExpBehavior(
            @Named(UPTIME_NAME) Clock clock,
            @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
            PhenotypeHelper phenotypeHelper,
            Lazy<StatusBarStateController> statusBarStateController,
            Lazy<ActivityManagerWrapper> activityManagerWrapper,
            Lazy<OverviewProxyService> overviewProxyService,
            Lazy<SysUiState> sysUiFlagContainer,
            Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
            Lazy<PackageManagerWrapper> packageManagerWrapper) {
        mClock = clock;
        mHandler = handler;
        mPhenotypeHelper = phenotypeHelper;
        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
        mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
        mSysUiFlagContainer = Dependency.get(SysUiState.class);
        mStatusBarStateController = statusBarStateController;
        mActivityManagerWrapper = activityManagerWrapper;
        mOverviewProxyService = overviewProxyService;
        mSysUiFlagContainer = sysUiFlagContainer;
        mWakefulnessLifecycle = wakefulnessLifecycle;
        mPackageManagerWrapper = packageManagerWrapper;
        mDefaultHomeIntentFilter = new IntentFilter();
        for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
            mDefaultHomeIntentFilter.addAction(action);
@@ -170,14 +200,17 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
        mConsecutiveTaskSwitches = 0;
        mDefaultHome = getCurrentDefaultHome();
        context.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
        mOnLockscreen = onLockscreen(mStatusBarStateController.getState());
        mIsDozing = mStatusBarStateController.isDozing();
        mStatusBarStateController.addCallback(mStatusBarStateListener);
        ActivityManager.RunningTaskInfo runningTaskInfo = mActivityManagerWrapper.getRunningTask();
        mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState());
        mStatusBarStateController.get().addCallback(mStatusBarStateListener);
        ActivityManager.RunningTaskInfo runningTaskInfo =
                mActivityManagerWrapper.get().getRunningTask();
        mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
        mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
        mOverviewProxyService.addCallback(mOverviewProxyListener);
        mSysUiFlagContainer.addCallback(mSysUiStateCallback);
        mActivityManagerWrapper.get().registerTaskStackListener(mTaskStackChangeListener);
        mOverviewProxyService.get().addCallback(mOverviewProxyListener);
        mSysUiFlagContainer.get().addCallback(mSysUiStateCallback);
        mIsDozing = mWakefulnessLifecycle.get().getWakefulness()
                != WakefulnessLifecycle.WAKEFULNESS_AWAKE;
        mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);

        mLearningTimeElapsed = Settings.Secure.getLong(
                context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
@@ -185,7 +218,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
                context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0);
        mLearnedHintLastShownEpochDay = Settings.Secure.getLong(
                context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0);
        mLastLearningTimestamp = SystemClock.uptimeMillis();
        mLastLearningTimestamp = mClock.currentTimeMillis();

        callbackForCurrentState(/* justUnlocked = */ false);
    }
@@ -200,10 +233,11 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
            Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
            mContext = null;
        }
        mStatusBarStateController.removeCallback(mStatusBarStateListener);
        mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
        mOverviewProxyService.removeCallback(mOverviewProxyListener);
        mSysUiFlagContainer.removeCallback(mSysUiStateCallback);
        mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
        mActivityManagerWrapper.get().unregisterTaskStackListener(mTaskStackChangeListener);
        mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
        mSysUiFlagContainer.get().removeCallback(mSysUiStateCallback);
        mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
    }

    @Override
@@ -223,15 +257,10 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
        }
    }

    private static boolean isNavBarHidden(int sysuiStateFlags) {
        return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
    }

    @Nullable
    private static ComponentName getCurrentDefaultHome() {
    private ComponentName getCurrentDefaultHome() {
        List<ResolveInfo> homeActivities = new ArrayList<>();
        ComponentName defaultHome =
                PackageManagerWrapper.getInstance().getHomeActivities(homeActivities);
        ComponentName defaultHome = mPackageManagerWrapper.get().getHomeActivities(homeActivities);
        if (defaultHome != null) {
            return defaultHome;
        }
@@ -287,7 +316,8 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
    }

    private void handleSystemUiStateChanged(int sysuiStateFlags) {
        boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags);
        boolean isNavBarHidden =
                (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
        if (mIsNavBarHidden == isNavBarHidden) {
            return;
        }
@@ -374,24 +404,15 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
            return;
        }

        long currentTimestamp = SystemClock.uptimeMillis();
        long currentTimestamp = mClock.currentTimeMillis();
        mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
        mLastLearningTimestamp = currentTimestamp;
        // TODO(b/140034473)
        whitelistIpcs(() -> Settings.Secure.putLong(
                mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed));

        mIsLearned =
                mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();

        mHandler.post(this::recordLearnTimeElapsed);
    }

    private void recordLearnTimeElapsed() {
        if (mContext != null) {
            Settings.Secure.putLong(
                    mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed);
        }
        mHandler.post(() -> Settings.Secure.putLong(
                mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed));
    }

    private void resetConsecutiveTaskSwitches() {
Loading