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

Commit 2c113405 authored by Govinda Wasserman's avatar Govinda Wasserman
Browse files

Update assist handle behavior control

Improves behavior modes to use more reliable callback mechanisms. Added
phenotype flag hooks for control of behavior and behavior parameters.
Added more robust null guarding.

Test: Tested locally
BUG:132983599
Change-Id: I42039152836071941d6b4f1cafb3670c62a65824
parent 190e99cf
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -113,5 +113,25 @@ public final class SystemUiDeviceConfigFlags {
     */
    public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";

    // Flags related to Assistant Handles

    /**
     * (String) Which behavior mode for the Assistant Handles to use.
     */
    public static final String ASSIST_HANDLES_BEHAVIOR_MODE = "assist_handles_behavior_mode";

    /**
     * (long) How long, in milliseconds, to display Assist Handles when showing them temporarily.
     */
    public static final String ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS =
            "assist_handles_show_and_go_duration_ms";

    /**
     * (long) How long, in milliseconds, to wait before displaying Assist Handles temporarily after
     * hiding them.
     */
    public static final String ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS =
            "assist_handles_shown_frequency_threshold_ms";

    private SystemUiDeviceConfigFlags() { }
}
+38 −4
Original line number Diff line number Diff line
@@ -24,9 +24,13 @@ import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.util.Log;

import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.Dependency;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysUiServiceProvider;
@@ -46,6 +50,7 @@ import java.util.function.Supplier;
public final class AssistHandleBehaviorController implements AssistHandleCallbacks {

    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");
@@ -87,6 +92,19 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
                Dependency.get(NavigationModeController.class)
                        .addListener(this::handleNavigationModeChange));

        setBehavior(DeviceConfig.getString(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE,
                mCurrentBehavior.toString()));
        DeviceConfig.addOnPropertyChangedListener(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                mHandler::post,
                (namespace, name, value) -> {
                    if (SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE.equals(name)) {
                        setBehavior(value);
                    }
                });

        if (IS_DEBUG_DEVICE) {
            context.registerReceiver(new BroadcastReceiver() {
                @Override
@@ -136,13 +154,29 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
        mCurrentBehavior = behavior;
    }

    private static long getShownFrequencyThreshold() {
    private void setBehavior(@Nullable String behavior) {
        try {
            setBehavior(AssistHandleBehavior.valueOf(behavior));
        } catch (IllegalArgumentException | NullPointerException e) {
            Log.e(TAG, "Invalid behavior: " + behavior, e);
        }
    }

    private long getShownFrequencyThreshold() {
        long configValue = DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS,
                DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS);
        return SystemProperties.getLong(
                SHOWN_FREQUENCY_THRESHOLD_KEY, DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS);
                SHOWN_FREQUENCY_THRESHOLD_KEY, configValue);
    }

    private static long getShowAndGoDuration() {
        return SystemProperties.getLong(SHOW_AND_GO_DURATION_KEY, DEFAULT_SHOW_AND_GO_DURATION_MS);
    private long getShowAndGoDuration() {
        long configValue = DeviceConfig.getLong(
                DeviceConfig.NAMESPACE_SYSTEMUI,
                SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS,
                DEFAULT_SHOW_AND_GO_DURATION_MS);
        return SystemProperties.getLong(SHOW_AND_GO_DURATION_KEY, configValue);
    }

    private void maybeShowHandles(boolean ignoreThreshold) {
+47 −28
Original line number Diff line number Diff line
@@ -16,17 +16,15 @@

package com.android.systemui.assist;

import android.app.StatusBarManager;
import android.content.Context;

import androidx.annotation.Nullable;

import com.android.systemui.Dependency;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.QuickStepContract;

/**
 * Assistant Handle behavior that makes Assistant handles show/hide when the home handle is
@@ -34,47 +32,68 @@ import com.android.systemui.statusbar.phone.NavigationBarFragment;
 */
final class AssistHandleLikeHomeBehavior implements BehaviorController {

    private final CommandQueue.Callbacks mCallbacks = new CommandQueue.Callbacks() {
    private final StatusBarStateController.StateListener mStatusBarStateListener =
            new StatusBarStateController.StateListener() {
                @Override
        public void setWindowState(int displayId, int window, int state) {
            if (mNavBarDisplayId == displayId
                    && window == StatusBarManager.WINDOW_NAVIGATION_BAR) {
                handleWindowStateChanged(state);
                public void onDozingChanged(boolean isDozing) {
                    handleDozingChanged(isDozing);
                }
            };
    private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
            new OverviewProxyService.OverviewProxyListener() {
        @Override
        public void onSystemUiStateChanged(int sysuiStateFlags) {
            handleSystemUiStateChange(sysuiStateFlags);
        }
    };
    private final StatusBarStateController mStatusBarStateController;
    private final OverviewProxyService mOverviewProxyService;

    private CommandQueue mCommandQueue;
    private int mNavBarDisplayId;
    private boolean mIsNavBarWindowVisible;
    private boolean mIsDozing;
    private boolean mIsHomeHandleHiding;

    @Nullable private AssistHandleCallbacks mAssistHandleCallbacks;

    AssistHandleLikeHomeBehavior() {
        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
    }

    @Override
    public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
        mAssistHandleCallbacks = callbacks;
        NavigationBarFragment navigationBarFragment =
                Dependency.get(NavigationBarController.class).getDefaultNavigationBarFragment();
        mNavBarDisplayId = navigationBarFragment.mDisplayId;
        mIsNavBarWindowVisible = navigationBarFragment.isNavBarWindowVisible();
        mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
        mCommandQueue.addCallback(mCallbacks);
        mIsDozing = mStatusBarStateController.isDozing();
        mStatusBarStateController.addCallback(mStatusBarStateListener);
        mOverviewProxyService.addCallback(mOverviewProxyListener);
        callbackForCurrentState();
    }

    @Override
    public void onModeDeactivated() {
        mAssistHandleCallbacks = null;
        mCommandQueue.removeCallback(mCallbacks);
        mOverviewProxyService.removeCallback(mOverviewProxyListener);
    }

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

    private void handleDozingChanged(boolean isDozing) {
        if (mIsDozing == isDozing) {
            return;
        }

        mIsDozing = isDozing;
        callbackForCurrentState();
    }

    private void handleWindowStateChanged(int state) {
        boolean newVisibility = state == StatusBarManager.WINDOW_STATE_SHOWING;
        if (mIsNavBarWindowVisible == newVisibility) {
    private void handleSystemUiStateChange(int sysuiStateFlags) {
        boolean isHomeHandleHiding = isHomeHandleHiding(sysuiStateFlags);
        if (mIsHomeHandleHiding == isHomeHandleHiding) {
            return;
        }

        mIsNavBarWindowVisible = newVisibility;
        mIsHomeHandleHiding = isHomeHandleHiding;
        callbackForCurrentState();
    }

@@ -83,10 +102,10 @@ final class AssistHandleLikeHomeBehavior implements BehaviorController {
            return;
        }

        if (mIsNavBarWindowVisible) {
            mAssistHandleCallbacks.showAndStay();
        } else {
        if (mIsHomeHandleHiding || mIsDozing) {
            mAssistHandleCallbacks.hide();
        } else {
            mAssistHandleCallbacks.showAndStay();
        }
    }
}
+29 −42
Original line number Diff line number Diff line
@@ -16,22 +16,19 @@

package com.android.systemui.assist;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import android.view.WindowManager;

import androidx.annotation.Nullable;

import com.android.systemui.Dependency;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
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.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;

/**
@@ -65,53 +62,45 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
                    handleTaskStackTopChanged(taskId);
                }
            };
    private final CommandQueue.Callbacks mCallbacks = new CommandQueue.Callbacks() {
        @Override
        public void setSystemUiVisibility(int displayId, int vis,
                int fullscreenStackVis, int dockedStackVis, int mask,
                Rect fullscreenStackBounds, Rect dockedStackBounds,
                boolean navbarColorManagedByIme) {
            if (mStatusBarDisplayId == displayId) {
                handleSystemUiVisibilityChange(vis, mask);
            }
        }
    };
    private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
            new OverviewProxyService.OverviewProxyListener() {
                @Override
                public void onOverviewShown(boolean fromHome) {
                    handleOverviewShown();
                }

                @Override
                public void onSystemUiStateChanged(int sysuiStateFlags) {
                    handleSystemUiStateChanged(sysuiStateFlags);
                }
            };

    private StatusBarStateController mStatusBarStateController;
    private ActivityManagerWrapper mActivityManagerWrapper;
    private OverviewProxyService mOverviewProxyService;
    private int mStatusBarDisplayId;
    private CommandQueue mCommandQueue;
    private final StatusBarStateController mStatusBarStateController;
    private final ActivityManagerWrapper mActivityManagerWrapper;
    private final OverviewProxyService mOverviewProxyService;

    private boolean mOnLockscreen;
    private boolean mIsDozing;
    private int mRunningTaskId;
    private boolean mIsImmersive;
    private boolean mIsNavBarHidden;

    @Nullable private AssistHandleCallbacks mAssistHandleCallbacks;

    AssistHandleReminderExpBehavior() {
        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
        mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
    }

    @Override
    public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
        mAssistHandleCallbacks = callbacks;
        mStatusBarStateController = Dependency.get(StatusBarStateController.class);
        mOnLockscreen = onLockscreen(mStatusBarStateController.getState());
        mIsDozing = mStatusBarStateController.isDozing();
        mStatusBarStateController.addCallback(mStatusBarStateListener);
        mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
        mRunningTaskId = mActivityManagerWrapper.getRunningTask().taskId;
        ActivityManager.RunningTaskInfo runningTaskInfo = mActivityManagerWrapper.getRunningTask();
        mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
        mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
        mStatusBarDisplayId =
                ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
                        .getDefaultDisplay().getDisplayId();
        mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
        mCommandQueue.addCallback(mCallbacks);
        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
        mOverviewProxyService.addCallback(mOverviewProxyListener);
        callbackForCurrentState();
    }
@@ -121,10 +110,13 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
        mAssistHandleCallbacks = null;
        mStatusBarStateController.removeCallback(mStatusBarStateListener);
        mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
        mCommandQueue.removeCallback(mCallbacks);
        mOverviewProxyService.removeCallback(mOverviewProxyListener);
    }

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

    private void handleStatusBarStateChanged(int newState) {
        boolean onLockscreen = onLockscreen(newState);
        if (mOnLockscreen == onLockscreen) {
@@ -153,13 +145,13 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
        callbackForCurrentState();
    }

    private void handleSystemUiVisibilityChange(int vis, int mask) {
        boolean isImmersive = isImmersive(vis, mask);
        if (mIsImmersive == isImmersive) {
    private void handleSystemUiStateChanged(int sysuiStateFlags) {
        boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags);
        if (mIsNavBarHidden == isNavBarHidden) {
            return;
        }

        mIsImmersive = isImmersive;
        mIsNavBarHidden = isNavBarHidden;
        callbackForCurrentState();
    }

@@ -172,17 +164,12 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
                || statusBarState == StatusBarState.SHADE_LOCKED;
    }

    private boolean isImmersive(int vis, int mask) {
        return ((vis & mask)
                & (View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0;
    }

    private void callbackForCurrentState() {
        if (mAssistHandleCallbacks == null) {
            return;
        }

        if (mIsDozing || mIsImmersive) {
        if (mIsDozing || mIsNavBarHidden) {
            mAssistHandleCallbacks.hide();
        } else if (mOnLockscreen) {
            mAssistHandleCallbacks.showAndStay();