blob: 4b6a6dcee91d15337d0e736221086e64d014cb37 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
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.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
* entering overview.
*/
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
public void onStateChanged(int newState) {
handleStatusBarStateChanged(newState);
}
@Override
public void onDozingChanged(boolean isDozing) {
handleDozingChanged(isDozing);
}
};
private final TaskStackChangeListener mTaskStackChangeListener =
new TaskStackChangeListener() {
@Override
public void onTaskMovedToFront(int taskId) {
handleTaskStackTopChanged(taskId);
}
@Override
public void onTaskCreated(int taskId, ComponentName componentName) {
handleTaskStackTopChanged(taskId);
}
};
private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
new OverviewProxyService.OverviewProxyListener() {
@Override
public void onOverviewShown(boolean fromHome) {
handleOverviewShown();
}
@Override
public void onSystemUiStateChanged(int sysuiStateFlags) {
handleSystemUiStateChanged(sysuiStateFlags);
}
};
private final StatusBarStateController mStatusBarStateController;
private final ActivityManagerWrapper mActivityManagerWrapper;
private final OverviewProxyService mOverviewProxyService;
private boolean mOnLockscreen;
private boolean mIsDozing;
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() {
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
}
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
mContext = context;
mAssistHandleCallbacks = callbacks;
mOnLockscreen = onLockscreen(mStatusBarStateController.getState());
mIsDozing = mStatusBarStateController.isDozing();
mStatusBarStateController.addCallback(mStatusBarStateListener);
ActivityManager.RunningTaskInfo runningTaskInfo = mActivityManagerWrapper.getRunningTask();
mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
mOverviewProxyService.addCallback(mOverviewProxyListener);
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;
}
private void handleStatusBarStateChanged(int newState) {
boolean onLockscreen = onLockscreen(newState);
if (mOnLockscreen == onLockscreen) {
return;
}
mOnLockscreen = onLockscreen;
callbackForCurrentState(!onLockscreen);
}
private void handleDozingChanged(boolean isDozing) {
if (mIsDozing == isDozing) {
return;
}
mIsDozing = isDozing;
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleTaskStackTopChanged(int taskId) {
if (mRunningTaskId == taskId) {
return;
}
mRunningTaskId = taskId;
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleSystemUiStateChanged(int sysuiStateFlags) {
boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags);
if (mIsNavBarHidden == isNavBarHidden) {
return;
}
mIsNavBarHidden = isNavBarHidden;
callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleOverviewShown() {
callbackForCurrentState(/* justUnlocked = */ false);
}
private boolean onLockscreen(int statusBarState) {
return statusBarState == StatusBarState.KEYGUARD
|| statusBarState == StatusBarState.SHADE_LOCKED;
}
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;
}
if (mIsDozing || mIsNavBarHidden) {
mAssistHandleCallbacks.hide();
} else if (mOnLockscreen) {
mAssistHandleCallbacks.showAndStay();
} else {
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);
}
}