blob: 039404800fbb9c47d38ff453add2afcce194deee [file] [log] [blame]
Govinda Wassermanc7495cd2019-05-20 14:43:28 -04001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.assist;
18
Govinda Wasserman3fcd7172019-09-05 16:32:23 -040019import static com.android.systemui.assist.AssistModule.ASSIST_HANDLE_THREAD_NAME;
20import static com.android.systemui.assist.AssistModule.UPTIME_NAME;
21
Govinda Wasserman2c113402019-05-24 14:11:24 -040022import android.app.ActivityManager;
Govinda Wasserman48cdd682019-06-04 12:15:23 -040023import android.content.BroadcastReceiver;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040024import android.content.ComponentName;
25import android.content.Context;
Govinda Wasserman48cdd682019-06-04 12:15:23 -040026import android.content.Intent;
27import android.content.IntentFilter;
Govinda Wasserman8c78dee2019-06-13 09:58:22 -040028import android.content.pm.ResolveInfo;
Govinda Wasserman48cdd682019-06-04 12:15:23 -040029import android.os.Handler;
Govinda Wasserman1f606b02019-05-29 09:16:02 -040030import android.provider.Settings;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040031
32import androidx.annotation.Nullable;
Govinda Wasserman3fcd7172019-09-05 16:32:23 -040033import androidx.slice.Clock;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040034
Govinda Wasserman1f606b02019-05-29 09:16:02 -040035import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040036import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
Govinda Wasserman3fcd7172019-09-05 16:32:23 -040037import com.android.systemui.keyguard.WakefulnessLifecycle;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040038import com.android.systemui.plugins.statusbar.StatusBarStateController;
39import com.android.systemui.recents.OverviewProxyService;
40import com.android.systemui.shared.system.ActivityManagerWrapper;
Govinda Wasserman48cdd682019-06-04 12:15:23 -040041import com.android.systemui.shared.system.PackageManagerWrapper;
Govinda Wasserman2c113402019-05-24 14:11:24 -040042import com.android.systemui.shared.system.QuickStepContract;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040043import com.android.systemui.shared.system.TaskStackChangeListener;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040044import com.android.systemui.statusbar.StatusBarState;
45
Govinda Wasserman48cdd682019-06-04 12:15:23 -040046import java.io.PrintWriter;
47import java.time.LocalDate;
48import java.util.ArrayList;
Govinda Wasserman8c78dee2019-06-13 09:58:22 -040049import java.util.List;
Govinda Wasserman1f606b02019-05-29 09:16:02 -040050import java.util.concurrent.TimeUnit;
51
Govinda Wasserman3fcd7172019-09-05 16:32:23 -040052import javax.inject.Inject;
53import javax.inject.Named;
54import javax.inject.Singleton;
55
56import dagger.Lazy;
57
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040058/**
59 * Assistant handle behavior that hides the handles when the phone is dozing or in immersive mode,
60 * shows the handles when on lockscreen, and shows the handles temporarily when changing tasks or
61 * entering overview.
62 */
Govinda Wasserman3fcd7172019-09-05 16:32:23 -040063@Singleton
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040064final class AssistHandleReminderExpBehavior implements BehaviorController {
65
Govinda Wasserman1f606b02019-05-29 09:16:02 -040066 private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed";
67 private static final String LEARNING_EVENT_COUNT_KEY = "reminder_exp_learning_event_count";
Govinda Wasserman48cdd682019-06-04 12:15:23 -040068 private static final String LEARNED_HINT_LAST_SHOWN_KEY =
69 "reminder_exp_learned_hint_last_shown";
Matt Casey176b2052019-06-18 16:27:56 -040070 private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(10);
71 private static final int DEFAULT_LEARNING_COUNT = 10;
Govinda Wasserman48cdd682019-06-04 12:15:23 -040072 private static final long DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS = 150;
73 private static final long DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS =
74 TimeUnit.SECONDS.toMillis(1);
75 private static final long DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS =
76 TimeUnit.SECONDS.toMillis(3);
77 private static final boolean DEFAULT_SUPPRESS_ON_LOCKSCREEN = false;
78 private static final boolean DEFAULT_SUPPRESS_ON_LAUNCHER = false;
Matt Casey176b2052019-06-18 16:27:56 -040079 private static final boolean DEFAULT_SUPPRESS_ON_APPS = true;
Govinda Wasserman3aa4f362019-06-19 11:23:43 -040080 private static final boolean DEFAULT_SHOW_WHEN_TAUGHT = false;
Govinda Wasserman1f606b02019-05-29 09:16:02 -040081
Govinda Wasserman8c78dee2019-06-13 09:58:22 -040082 private static final String[] DEFAULT_HOME_CHANGE_ACTIONS = new String[] {
83 PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED,
84 Intent.ACTION_BOOT_COMPLETED,
85 Intent.ACTION_PACKAGE_ADDED,
86 Intent.ACTION_PACKAGE_CHANGED,
87 Intent.ACTION_PACKAGE_REMOVED
88 };
89
Govinda Wassermanc7495cd2019-05-20 14:43:28 -040090 private final StatusBarStateController.StateListener mStatusBarStateListener =
91 new StatusBarStateController.StateListener() {
92 @Override
93 public void onStateChanged(int newState) {
94 handleStatusBarStateChanged(newState);
95 }
Govinda Wasserman7b546482019-09-18 14:35:35 -040096
97 @Override
98 public void onDozingChanged(boolean isDozing) {
99 handleDozingChanged(isDozing);
100 }
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400101 };
102 private final TaskStackChangeListener mTaskStackChangeListener =
103 new TaskStackChangeListener() {
104 @Override
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400105 public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
106 handleTaskStackTopChanged(taskInfo.taskId, taskInfo.topActivity);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400107 }
108
109 @Override
110 public void onTaskCreated(int taskId, ComponentName componentName) {
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400111 handleTaskStackTopChanged(taskId, componentName);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400112 }
113 };
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400114 private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
115 new OverviewProxyService.OverviewProxyListener() {
116 @Override
117 public void onOverviewShown(boolean fromHome) {
118 handleOverviewShown();
119 }
Govinda Wasserman2c113402019-05-24 14:11:24 -0400120
121 @Override
122 public void onSystemUiStateChanged(int sysuiStateFlags) {
123 handleSystemUiStateChanged(sysuiStateFlags);
124 }
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400125 };
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400126 private final WakefulnessLifecycle.Observer mWakefulnessLifecycleObserver =
127 new WakefulnessLifecycle.Observer() {
128 @Override
Govinda Wasserman7b546482019-09-18 14:35:35 -0400129 public void onStartedWakingUp() {
130 handleWakefullnessChanged(/* isAwake = */ false);
131 }
132
133 @Override
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400134 public void onFinishedWakingUp() {
Govinda Wasserman7b546482019-09-18 14:35:35 -0400135 handleWakefullnessChanged(/* isAwake = */ true);
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400136 }
137
138 @Override
139 public void onStartedGoingToSleep() {
Govinda Wasserman7b546482019-09-18 14:35:35 -0400140 handleWakefullnessChanged(/* isAwake = */ false);
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400141 }
Govinda Wasserman7b546482019-09-18 14:35:35 -0400142
143 @Override
144 public void onFinishedGoingToSleep() {
145 handleWakefullnessChanged(/* isAwake = */ false);
146 }
147 };
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400148 private final BroadcastReceiver mDefaultHomeBroadcastReceiver = new BroadcastReceiver() {
149 @Override
150 public void onReceive(Context context, Intent intent) {
151 mDefaultHome = getCurrentDefaultHome();
152 }
153 };
Govinda Wasserman8c78dee2019-06-13 09:58:22 -0400154 private final IntentFilter mDefaultHomeIntentFilter;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400155 private final Runnable mResetConsecutiveTaskSwitches = this::resetConsecutiveTaskSwitches;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400156
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400157 private final Clock mClock;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400158 private final Handler mHandler;
159 private final PhenotypeHelper mPhenotypeHelper;
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400160 private final Lazy<StatusBarStateController> mStatusBarStateController;
161 private final Lazy<ActivityManagerWrapper> mActivityManagerWrapper;
162 private final Lazy<OverviewProxyService> mOverviewProxyService;
163 private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
164 private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;
Govinda Wasserman2c113402019-05-24 14:11:24 -0400165
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400166 private boolean mOnLockscreen;
167 private boolean mIsDozing;
Govinda Wasserman7b546482019-09-18 14:35:35 -0400168 private boolean mIsAwake;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400169 private int mRunningTaskId;
Govinda Wasserman2c113402019-05-24 14:11:24 -0400170 private boolean mIsNavBarHidden;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400171 private boolean mIsLauncherShowing;
172 private int mConsecutiveTaskSwitches;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400173
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400174 /** Whether user has learned the gesture. */
175 private boolean mIsLearned;
176 private long mLastLearningTimestamp;
177 /** Uptime while in this behavior. */
178 private long mLearningTimeElapsed;
179 /** Number of successful Assistant invocations while in this behavior. */
180 private int mLearningCount;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400181 private long mLearnedHintLastShownEpochDay;
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400182
183 @Nullable private Context mContext;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400184 @Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400185 @Nullable private ComponentName mDefaultHome;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400186
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400187 @Inject
188 AssistHandleReminderExpBehavior(
189 @Named(UPTIME_NAME) Clock clock,
190 @Named(ASSIST_HANDLE_THREAD_NAME) Handler handler,
191 PhenotypeHelper phenotypeHelper,
192 Lazy<StatusBarStateController> statusBarStateController,
193 Lazy<ActivityManagerWrapper> activityManagerWrapper,
194 Lazy<OverviewProxyService> overviewProxyService,
195 Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
196 Lazy<PackageManagerWrapper> packageManagerWrapper) {
197 mClock = clock;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400198 mHandler = handler;
199 mPhenotypeHelper = phenotypeHelper;
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400200 mStatusBarStateController = statusBarStateController;
201 mActivityManagerWrapper = activityManagerWrapper;
202 mOverviewProxyService = overviewProxyService;
203 mWakefulnessLifecycle = wakefulnessLifecycle;
204 mPackageManagerWrapper = packageManagerWrapper;
Govinda Wasserman8c78dee2019-06-13 09:58:22 -0400205 mDefaultHomeIntentFilter = new IntentFilter();
206 for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
207 mDefaultHomeIntentFilter.addAction(action);
208 }
Govinda Wasserman2c113402019-05-24 14:11:24 -0400209 }
210
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400211 @Override
212 public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400213 mContext = context;
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400214 mAssistHandleCallbacks = callbacks;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400215 mConsecutiveTaskSwitches = 0;
216 mDefaultHome = getCurrentDefaultHome();
217 context.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400218 mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState());
Govinda Wasserman7b546482019-09-18 14:35:35 -0400219 mIsDozing = mStatusBarStateController.get().isDozing();
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400220 mStatusBarStateController.get().addCallback(mStatusBarStateListener);
221 ActivityManager.RunningTaskInfo runningTaskInfo =
222 mActivityManagerWrapper.get().getRunningTask();
Govinda Wasserman2c113402019-05-24 14:11:24 -0400223 mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400224 mActivityManagerWrapper.get().registerTaskStackListener(mTaskStackChangeListener);
225 mOverviewProxyService.get().addCallback(mOverviewProxyListener);
Govinda Wasserman7b546482019-09-18 14:35:35 -0400226 mIsAwake = mWakefulnessLifecycle.get().getWakefulness()
227 == WakefulnessLifecycle.WAKEFULNESS_AWAKE;
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400228 mWakefulnessLifecycle.get().addObserver(mWakefulnessLifecycleObserver);
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400229
230 mLearningTimeElapsed = Settings.Secure.getLong(
231 context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
232 mLearningCount = Settings.Secure.getInt(
233 context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0);
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400234 mLearnedHintLastShownEpochDay = Settings.Secure.getLong(
235 context.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, /* default = */ 0);
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400236 mLastLearningTimestamp = mClock.currentTimeMillis();
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400237
238 callbackForCurrentState(/* justUnlocked = */ false);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400239 }
240
241 @Override
242 public void onModeDeactivated() {
243 mAssistHandleCallbacks = null;
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400244 if (mContext != null) {
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400245 mContext.unregisterReceiver(mDefaultHomeBroadcastReceiver);
246 Settings.Secure.putLong(mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, 0);
247 Settings.Secure.putInt(mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, 0);
248 Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400249 mContext = null;
250 }
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400251 mStatusBarStateController.get().removeCallback(mStatusBarStateListener);
252 mActivityManagerWrapper.get().unregisterTaskStackListener(mTaskStackChangeListener);
253 mOverviewProxyService.get().removeCallback(mOverviewProxyListener);
254 mWakefulnessLifecycle.get().removeObserver(mWakefulnessLifecycleObserver);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400255 }
256
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400257 @Override
258 public void onAssistantGesturePerformed() {
259 if (mContext == null) {
260 return;
261 }
262
263 Settings.Secure.putLong(
264 mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, ++mLearningCount);
265 }
266
Govinda Wasserman40c043a2019-08-12 12:22:13 -0400267 @Override
268 public void onAssistHandlesRequested() {
Govinda Wasserman7b546482019-09-18 14:35:35 -0400269 if (mAssistHandleCallbacks != null
270 && isFullyAwake()
271 && !mIsNavBarHidden
272 && !mOnLockscreen) {
Govinda Wasserman40c043a2019-08-12 12:22:13 -0400273 mAssistHandleCallbacks.showAndGo();
274 }
275 }
276
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400277 @Nullable
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400278 private ComponentName getCurrentDefaultHome() {
Govinda Wasserman8c78dee2019-06-13 09:58:22 -0400279 List<ResolveInfo> homeActivities = new ArrayList<>();
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400280 ComponentName defaultHome = mPackageManagerWrapper.get().getHomeActivities(homeActivities);
Govinda Wasserman8c78dee2019-06-13 09:58:22 -0400281 if (defaultHome != null) {
282 return defaultHome;
283 }
284
285 int topPriority = Integer.MIN_VALUE;
286 ComponentName topComponent = null;
287 for (ResolveInfo resolveInfo : homeActivities) {
288 if (resolveInfo.priority > topPriority) {
289 topComponent = resolveInfo.activityInfo.getComponentName();
290 topPriority = resolveInfo.priority;
291 } else if (resolveInfo.priority == topPriority) {
292 topComponent = null;
293 }
294 }
295 return topComponent;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400296 }
297
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400298 private void handleStatusBarStateChanged(int newState) {
299 boolean onLockscreen = onLockscreen(newState);
300 if (mOnLockscreen == onLockscreen) {
301 return;
302 }
303
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400304 resetConsecutiveTaskSwitches();
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400305 mOnLockscreen = onLockscreen;
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400306 callbackForCurrentState(!onLockscreen);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400307 }
308
309 private void handleDozingChanged(boolean isDozing) {
310 if (mIsDozing == isDozing) {
311 return;
312 }
313
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400314 resetConsecutiveTaskSwitches();
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400315 mIsDozing = isDozing;
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400316 callbackForCurrentState(/* justUnlocked = */ false);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400317 }
318
Govinda Wasserman7b546482019-09-18 14:35:35 -0400319 private void handleWakefullnessChanged(boolean isAwake) {
320 if (mIsAwake == isAwake) {
321 return;
322 }
323
324 resetConsecutiveTaskSwitches();
325 mIsAwake = isAwake;
326 callbackForCurrentState(/* justUnlocked = */ false);
327 }
328
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400329 private void handleTaskStackTopChanged(int taskId, @Nullable ComponentName taskComponentName) {
330 if (mRunningTaskId == taskId || taskComponentName == null) {
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400331 return;
332 }
333
334 mRunningTaskId = taskId;
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400335 mIsLauncherShowing = taskComponentName.equals(mDefaultHome);
336 if (mIsLauncherShowing) {
337 resetConsecutiveTaskSwitches();
338 } else {
339 rescheduleConsecutiveTaskSwitchesReset();
340 mConsecutiveTaskSwitches++;
341 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400342 callbackForCurrentState(/* justUnlocked = */ false);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400343 }
344
Govinda Wasserman2c113402019-05-24 14:11:24 -0400345 private void handleSystemUiStateChanged(int sysuiStateFlags) {
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400346 boolean isNavBarHidden =
347 (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
Govinda Wasserman2c113402019-05-24 14:11:24 -0400348 if (mIsNavBarHidden == isNavBarHidden) {
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400349 return;
350 }
351
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400352 resetConsecutiveTaskSwitches();
Govinda Wasserman2c113402019-05-24 14:11:24 -0400353 mIsNavBarHidden = isNavBarHidden;
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400354 callbackForCurrentState(/* justUnlocked = */ false);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400355 }
356
357 private void handleOverviewShown() {
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400358 resetConsecutiveTaskSwitches();
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400359 callbackForCurrentState(/* justUnlocked = */ false);
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400360 }
361
362 private boolean onLockscreen(int statusBarState) {
363 return statusBarState == StatusBarState.KEYGUARD
364 || statusBarState == StatusBarState.SHADE_LOCKED;
365 }
366
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400367 private void callbackForCurrentState(boolean justUnlocked) {
368 updateLearningStatus();
369
370 if (mIsLearned) {
371 callbackForLearnedState(justUnlocked);
372 } else {
373 callbackForUnlearnedState();
374 }
375 }
376
377 private void callbackForLearnedState(boolean justUnlocked) {
378 if (mAssistHandleCallbacks == null) {
379 return;
380 }
381
Govinda Wasserman7b546482019-09-18 14:35:35 -0400382 if (!isFullyAwake() || mIsNavBarHidden || mOnLockscreen || !getShowWhenTaught()) {
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400383 mAssistHandleCallbacks.hide();
384 } else if (justUnlocked) {
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400385 long currentEpochDay = LocalDate.now().toEpochDay();
386 if (mLearnedHintLastShownEpochDay < currentEpochDay) {
387 if (mContext != null) {
388 Settings.Secure.putLong(
389 mContext.getContentResolver(),
390 LEARNED_HINT_LAST_SHOWN_KEY,
391 currentEpochDay);
392 }
393 mLearnedHintLastShownEpochDay = currentEpochDay;
394 mAssistHandleCallbacks.showAndGo();
395 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400396 }
397 }
398
399 private void callbackForUnlearnedState() {
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400400 if (mAssistHandleCallbacks == null) {
401 return;
402 }
403
Govinda Wasserman7b546482019-09-18 14:35:35 -0400404 if (!isFullyAwake() || mIsNavBarHidden || isSuppressed()) {
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400405 mAssistHandleCallbacks.hide();
406 } else if (mOnLockscreen) {
407 mAssistHandleCallbacks.showAndStay();
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400408 } else if (mIsLauncherShowing) {
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400409 mAssistHandleCallbacks.showAndGo();
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400410 } else if (mConsecutiveTaskSwitches == 1) {
411 mAssistHandleCallbacks.showAndGoDelayed(
412 getShowAndGoDelayedShortDelayMs(), /* hideIfShowing = */ false);
413 } else {
414 mAssistHandleCallbacks.showAndGoDelayed(
415 getShowAndGoDelayedLongDelayMs(), /* hideIfShowing = */ true);
416 }
417 }
418
419 private boolean isSuppressed() {
420 if (mOnLockscreen) {
421 return getSuppressOnLockscreen();
422 } else if (mIsLauncherShowing) {
423 return getSuppressOnLauncher();
424 } else {
425 return getSuppressOnApps();
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400426 }
427 }
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400428
429 private void updateLearningStatus() {
430 if (mContext == null) {
431 return;
432 }
433
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400434 long currentTimestamp = mClock.currentTimeMillis();
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400435 mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
436 mLastLearningTimestamp = currentTimestamp;
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400437
438 mIsLearned =
439 mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();
Govinda Wasserman79b74882019-08-27 10:17:27 -0400440
Govinda Wasserman3fcd7172019-09-05 16:32:23 -0400441 mHandler.post(() -> Settings.Secure.putLong(
442 mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed));
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400443 }
444
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400445 private void resetConsecutiveTaskSwitches() {
446 mHandler.removeCallbacks(mResetConsecutiveTaskSwitches);
447 mConsecutiveTaskSwitches = 0;
448 }
449
450 private void rescheduleConsecutiveTaskSwitchesReset() {
451 mHandler.removeCallbacks(mResetConsecutiveTaskSwitches);
452 mHandler.postDelayed(mResetConsecutiveTaskSwitches, getShowAndGoDelayResetTimeoutMs());
453 }
454
Govinda Wasserman7b546482019-09-18 14:35:35 -0400455 private boolean isFullyAwake() {
456 return mIsAwake && !mIsDozing;
457 }
458
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400459 private long getLearningTimeMs() {
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400460 return mPhenotypeHelper.getLong(
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400461 SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS,
462 DEFAULT_LEARNING_TIME_MS);
463 }
464
465 private int getLearningCount() {
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400466 return mPhenotypeHelper.getInt(
Govinda Wasserman1f606b02019-05-29 09:16:02 -0400467 SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT,
468 DEFAULT_LEARNING_COUNT);
469 }
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400470
471 private long getShowAndGoDelayedShortDelayMs() {
472 return mPhenotypeHelper.getLong(
473 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS,
474 DEFAULT_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS);
475 }
476
477 private long getShowAndGoDelayedLongDelayMs() {
478 return mPhenotypeHelper.getLong(
479 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS,
480 DEFAULT_SHOW_AND_GO_DELAYED_LONG_DELAY_MS);
481 }
482
483 private long getShowAndGoDelayResetTimeoutMs() {
484 return mPhenotypeHelper.getLong(
485 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS,
486 DEFAULT_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS);
487 }
488
489 private boolean getSuppressOnLockscreen() {
490 return mPhenotypeHelper.getBoolean(
491 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN,
492 DEFAULT_SUPPRESS_ON_LOCKSCREEN);
493 }
494
495 private boolean getSuppressOnLauncher() {
496 return mPhenotypeHelper.getBoolean(
497 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER,
498 DEFAULT_SUPPRESS_ON_LAUNCHER);
499 }
500
501 private boolean getSuppressOnApps() {
502 return mPhenotypeHelper.getBoolean(
503 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS,
504 DEFAULT_SUPPRESS_ON_APPS);
505 }
506
Govinda Wasserman3aa4f362019-06-19 11:23:43 -0400507 private boolean getShowWhenTaught() {
508 return mPhenotypeHelper.getBoolean(
509 SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT,
510 DEFAULT_SHOW_WHEN_TAUGHT);
511 }
512
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400513 @Override
514 public void dump(PrintWriter pw, String prefix) {
515 pw.println(prefix + "Current AssistHandleReminderExpBehavior State:");
516 pw.println(prefix + " mOnLockscreen=" + mOnLockscreen);
517 pw.println(prefix + " mIsDozing=" + mIsDozing);
Govinda Wasserman7b546482019-09-18 14:35:35 -0400518 pw.println(prefix + " mIsAwake=" + mIsAwake);
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400519 pw.println(prefix + " mRunningTaskId=" + mRunningTaskId);
520 pw.println(prefix + " mDefaultHome=" + mDefaultHome);
521 pw.println(prefix + " mIsNavBarHidden=" + mIsNavBarHidden);
522 pw.println(prefix + " mIsLauncherShowing=" + mIsLauncherShowing);
523 pw.println(prefix + " mConsecutiveTaskSwitches=" + mConsecutiveTaskSwitches);
524 pw.println(prefix + " mIsLearned=" + mIsLearned);
525 pw.println(prefix + " mLastLearningTimestamp=" + mLastLearningTimestamp);
526 pw.println(prefix + " mLearningTimeElapsed=" + mLearningTimeElapsed);
527 pw.println(prefix + " mLearningCount=" + mLearningCount);
528 pw.println(prefix + " mLearnedHintLastShownEpochDay=" + mLearnedHintLastShownEpochDay);
529 pw.println(
530 prefix + " mAssistHandleCallbacks present: " + (mAssistHandleCallbacks != null));
531
532 pw.println(prefix + " Phenotype Flags:");
533 pw.println(prefix + " "
534 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS
535 + "="
536 + getLearningTimeMs());
537 pw.println(prefix + " "
538 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT
539 + "="
540 + getLearningCount());
541 pw.println(prefix + " "
542 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_SHORT_DELAY_MS
543 + "="
544 + getShowAndGoDelayedShortDelayMs());
545 pw.println(prefix + " "
546 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAYED_LONG_DELAY_MS
547 + "="
548 + getShowAndGoDelayedLongDelayMs());
549 pw.println(prefix + " "
550 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DELAY_RESET_TIMEOUT_MS
551 + "="
552 + getShowAndGoDelayResetTimeoutMs());
553 pw.println(prefix + " "
554 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LOCKSCREEN
555 + "="
556 + getSuppressOnLockscreen());
557 pw.println(prefix + " "
558 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_LAUNCHER
559 + "="
560 + getSuppressOnLauncher());
561 pw.println(prefix + " "
562 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SUPPRESS_ON_APPS
563 + "="
564 + getSuppressOnApps());
Govinda Wasserman3aa4f362019-06-19 11:23:43 -0400565 pw.println(prefix + " "
566 + SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_WHEN_TAUGHT
567 + "="
568 + getShowWhenTaught());
Govinda Wasserman48cdd682019-06-04 12:15:23 -0400569 }
Govinda Wassermanc7495cd2019-05-20 14:43:28 -0400570}