• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
17 package com.android.systemui.navigationbar;
18 
19 import static android.app.StatusBarManager.WINDOW_NAVIGATION_BAR;
20 import static android.app.StatusBarManager.WindowVisibleState;
21 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
22 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
23 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
24 import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
25 import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
26 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
27 
28 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.DEFAULT;
29 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
30 import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
31 import static com.android.systemui.accessibility.SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON;
32 import static com.android.systemui.accessibility.SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER;
33 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
34 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
35 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_OPAQUE;
36 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
37 import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
38 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
39 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
40 
41 import android.content.ContentResolver;
42 import android.content.Context;
43 import android.content.res.Configuration;
44 import android.database.ContentObserver;
45 import android.inputmethodservice.InputMethodService;
46 import android.inputmethodservice.InputMethodService.ImeWindowVisibility;
47 import android.net.Uri;
48 import android.os.Bundle;
49 import android.os.Handler;
50 import android.os.Looper;
51 import android.os.Process;
52 import android.os.RemoteException;
53 import android.os.UserHandle;
54 import android.provider.Settings;
55 import android.provider.Settings.Secure;
56 import android.util.Log;
57 import android.view.IRotationWatcher;
58 import android.view.IWallpaperVisibilityListener;
59 import android.view.IWindowManager;
60 import android.view.View;
61 import android.view.WindowInsets;
62 import android.view.accessibility.AccessibilityManager;
63 
64 import androidx.annotation.NonNull;
65 import androidx.annotation.Nullable;
66 import androidx.annotation.WorkerThread;
67 
68 import com.android.internal.annotations.VisibleForTesting;
69 import com.android.systemui.Dumpable;
70 import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
71 import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
72 import com.android.systemui.accessibility.AccessibilityGestureTargetsObserver;
73 import com.android.systemui.accessibility.SystemActions;
74 import com.android.systemui.assist.AssistManager;
75 import com.android.systemui.dagger.SysUISingleton;
76 import com.android.systemui.dagger.qualifiers.Background;
77 import com.android.systemui.dagger.qualifiers.Main;
78 import com.android.systemui.dump.DumpManager;
79 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
80 import com.android.systemui.recents.LauncherProxyService;
81 import com.android.systemui.settings.DisplayTracker;
82 import com.android.systemui.settings.UserTracker;
83 import com.android.systemui.shared.Flags;
84 import com.android.systemui.shared.rotation.RotationPolicyUtil;
85 import com.android.systemui.shared.statusbar.phone.BarTransitions.TransitionMode;
86 import com.android.systemui.shared.system.QuickStepContract;
87 import com.android.systemui.statusbar.CommandQueue;
88 import com.android.systemui.statusbar.NotificationShadeWindowController;
89 import com.android.systemui.statusbar.phone.CentralSurfaces;
90 import com.android.systemui.statusbar.policy.ConfigurationController;
91 import com.android.systemui.statusbar.policy.KeyguardStateController;
92 
93 import dagger.Lazy;
94 
95 import java.io.PrintWriter;
96 import java.util.ArrayList;
97 import java.util.List;
98 import java.util.Optional;
99 import java.util.concurrent.Executor;
100 
101 import javax.inject.Inject;
102 
103 /**
104  * Extracts shared elements between navbar and taskbar delegate to de-dupe logic and help them
105  * experience the joys of friendship.
106  * The events are then passed through
107  *
108  * Currently consolidates
109  * * A11y
110  * * Assistant
111  */
112 @SysUISingleton
113 public final class NavBarHelper implements
114         AccessibilityManager.AccessibilityServicesStateChangeListener,
115         AccessibilityButtonModeObserver.ModeChangedListener,
116         AccessibilityButtonTargetsObserver.TargetsChangedListener,
117         AccessibilityGestureTargetsObserver.TargetsChangedListener,
118         LauncherProxyService.LauncherProxyListener, NavigationModeController.ModeChangedListener,
119         Dumpable, CommandQueue.Callbacks, ConfigurationController.ConfigurationListener {
120     private static final String TAG = NavBarHelper.class.getSimpleName();
121 
122     private final Handler mHandler = new Handler(Looper.getMainLooper());
123     private final Executor mMainExecutor;
124     private final Handler mBgHandler;
125     private final AccessibilityManager mAccessibilityManager;
126     private final Lazy<AssistManager> mAssistManagerLazy;
127     private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
128     private final KeyguardStateController mKeyguardStateController;
129     private final UserTracker mUserTracker;
130     private final SystemActions mSystemActions;
131     private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
132     private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
133     private final AccessibilityGestureTargetsObserver mAccessibilityGestureTargetsObserver;
134     private final List<NavbarTaskbarStateUpdater> mStateListeners = new ArrayList<>();
135     private final Context mContext;
136     private final NotificationShadeWindowController mNotificationShadeWindowController;
137     private final CommandQueue mCommandQueue;
138     private final ContentResolver mContentResolver;
139     private final EdgeBackGestureHandler mEdgeBackGestureHandler;
140     private final IWindowManager mWm;
141     private final int mDefaultDisplayId;
142     private boolean mAssistantAvailable;
143     private boolean mLongPressHomeEnabled;
144     private boolean mAssistantTouchGestureEnabled;
145     private int mNavBarMode;
146     private long mA11yButtonState;
147     private int mRotationWatcherRotation;
148     private boolean mTogglingNavbarTaskbar;
149     private boolean mWallpaperVisible;
150 
151     // Attributes used in NavBarHelper.CurrentSysuiState
152     private int mWindowStateDisplayId;
153     private @WindowVisibleState int mWindowState;
154 
155     // Listens for changes to the assistant
156     private final ContentObserver mAssistContentObserver = new ContentObserver(mHandler) {
157         @Override
158         public void onChange(boolean selfChange, Uri uri) {
159             updateAssistantAvailability();
160         }
161     };
162 
163     // Listens for changes to the wallpaper visibility
164     private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
165             new IWallpaperVisibilityListener.Stub() {
166                 @Override
167                 public void onWallpaperVisibilityChanged(boolean visible,
168                         int displayId) throws RemoteException {
169                     mHandler.post(() -> {
170                         mWallpaperVisible = visible;
171                         dispatchWallpaperVisibilityChanged(visible, displayId);
172                     });
173                 }
174             };
175 
176     // Listens for changes to display rotation
177     private final IRotationWatcher mRotationWatcher = new IRotationWatcher.Stub() {
178         @WorkerThread
179         @Override
180         public void onRotationChanged(final int rotation) {
181             // We need this to be scheduled as early as possible to beat the redrawing of
182             // window in response to the orientation change.
183             @Nullable Boolean isRotationLocked = RotationPolicyUtil.isRotationLocked(mContext);
184             mHandler.postAtFrontOfQueue(() -> {
185                 mRotationWatcherRotation = rotation;
186                 dispatchRotationChanged(rotation, isRotationLocked);
187             });
188         }
189     };
190 
191     /**
192      * @param context This is not display specific, then again neither is any of the code in
193      *                this class. Once there's display specific code, we may want to create an
194      *                instance of this class per navbar vs having it be a singleton.
195      */
196     @Inject
NavBarHelper(Context context, AccessibilityManager accessibilityManager, AccessibilityButtonModeObserver accessibilityButtonModeObserver, AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver, AccessibilityGestureTargetsObserver accessibilityGestureTargetsObserver, SystemActions systemActions, LauncherProxyService launcherProxyService, Lazy<AssistManager> assistManagerLazy, Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy, KeyguardStateController keyguardStateController, NavigationModeController navigationModeController, EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory, IWindowManager wm, UserTracker userTracker, DisplayTracker displayTracker, NotificationShadeWindowController notificationShadeWindowController, ConfigurationController configurationController, DumpManager dumpManager, CommandQueue commandQueue, @Main Executor mainExecutor, @Background Handler bgHandler)197     public NavBarHelper(Context context, AccessibilityManager accessibilityManager,
198             AccessibilityButtonModeObserver accessibilityButtonModeObserver,
199             AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver,
200             AccessibilityGestureTargetsObserver accessibilityGestureTargetsObserver,
201             SystemActions systemActions,
202             LauncherProxyService launcherProxyService,
203             Lazy<AssistManager> assistManagerLazy,
204             Lazy<Optional<CentralSurfaces>> centralSurfacesOptionalLazy,
205             KeyguardStateController keyguardStateController,
206             NavigationModeController navigationModeController,
207             EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
208             IWindowManager wm,
209             UserTracker userTracker,
210             DisplayTracker displayTracker,
211             NotificationShadeWindowController notificationShadeWindowController,
212             ConfigurationController configurationController,
213             DumpManager dumpManager,
214             CommandQueue commandQueue,
215             @Main Executor mainExecutor,
216             @Background Handler bgHandler) {
217         // b/319489709: This component shouldn't be running for a non-primary user
218         if (!Process.myUserHandle().equals(UserHandle.SYSTEM)) {
219             Log.wtf(TAG, "Unexpected initialization for non-primary user", new Throwable());
220         }
221         mContext = context;
222         mNotificationShadeWindowController = notificationShadeWindowController;
223         mCommandQueue = commandQueue;
224         mContentResolver = mContext.getContentResolver();
225         mAccessibilityManager = accessibilityManager;
226         mAssistManagerLazy = assistManagerLazy;
227         mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy;
228         mKeyguardStateController = keyguardStateController;
229         mUserTracker = userTracker;
230         mSystemActions = systemActions;
231         mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
232         mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
233         mAccessibilityGestureTargetsObserver = accessibilityGestureTargetsObserver;
234         mWm = wm;
235         mDefaultDisplayId = displayTracker.getDefaultDisplayId();
236         mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
237         mMainExecutor = mainExecutor;
238         mBgHandler = bgHandler;
239 
240         mNavBarMode = navigationModeController.addListener(this);
241         mCommandQueue.addCallback(this);
242         configurationController.addCallback(this);
243         launcherProxyService.addCallback(this);
244         dumpManager.registerDumpable(this);
245     }
246 
247     /**
248      * Hints to the helper that bars are being replaced, which is a signal to potentially suppress
249      * normal setup/cleanup when no bars are present.
250      */
setTogglingNavbarTaskbar(boolean togglingNavbarTaskbar)251     public void setTogglingNavbarTaskbar(boolean togglingNavbarTaskbar) {
252         mTogglingNavbarTaskbar = togglingNavbarTaskbar;
253     }
254 
255     /**
256      * Called when the first (non-replacing) bar is registered.
257      */
setupOnFirstBar()258     private void setupOnFirstBar() {
259         // Setup accessibility listeners
260         mAccessibilityManager.addAccessibilityServicesStateChangeListener(this);
261         mAccessibilityButtonModeObserver.addListener(this);
262         mAccessibilityButtonTargetsObserver.addListener(this);
263         mAccessibilityGestureTargetsObserver.addListener(this);
264 
265         // Setup assistant listener
266         mContentResolver.registerContentObserver(
267                 Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
268                 false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
269         mContentResolver.registerContentObserver(
270                 Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED),
271                 false, mAssistContentObserver, UserHandle.USER_ALL);
272         mContentResolver.registerContentObserver(
273                 Settings.Secure.getUriFor(Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED),
274                 false, mAssistContentObserver, UserHandle.USER_ALL);
275         mContentResolver.registerContentObserver(
276                 Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),
277                 false, mAssistContentObserver, UserHandle.USER_ALL);
278 
279         // Setup display rotation watcher
280         try {
281             mWm.watchRotation(mRotationWatcher, mDefaultDisplayId);
282         } catch (Exception e) {
283             Log.w(TAG, "Failed to register rotation watcher", e);
284         }
285 
286         // Setup wallpaper visibility listener
287         try {
288             mWallpaperVisible = mWm.registerWallpaperVisibilityListener(
289                     mWallpaperVisibilityListener, mDefaultDisplayId);
290         } catch (Exception e) {
291             Log.w(TAG, "Failed to register wallpaper visibility listener", e);
292         }
293 
294         // Attach the back handler only when the first bar is registered
295         mEdgeBackGestureHandler.onNavBarAttached();
296     }
297 
298     /**
299      * Called after the last (non-replacing) bar is unregistered.
300      */
cleanupAfterLastBar()301     private void cleanupAfterLastBar() {
302         // Clean up accessibility listeners
303         mAccessibilityManager.removeAccessibilityServicesStateChangeListener(this);
304         mAccessibilityButtonModeObserver.removeListener(this);
305         mAccessibilityButtonTargetsObserver.removeListener(this);
306         mAccessibilityGestureTargetsObserver.removeListener(this);
307 
308         // Clean up assistant listeners
309         mContentResolver.unregisterContentObserver(mAssistContentObserver);
310 
311         // Clean up display rotation watcher
312         try {
313             mWm.removeRotationWatcher(mRotationWatcher);
314         } catch (Exception e) {
315             Log.w(TAG, "Failed to unregister rotation watcher", e);
316         }
317 
318         // Clean up wallpaper visibility listener
319         try {
320             mWm.unregisterWallpaperVisibilityListener(mWallpaperVisibilityListener,
321                     mDefaultDisplayId);
322         } catch (Exception e) {
323             Log.w(TAG, "Failed to register wallpaper visibility listener", e);
324         }
325 
326         // No more bars, detach the back handler for now
327         mEdgeBackGestureHandler.onNavBarDetached();
328     }
329 
330     /**
331      * Registers a listener for future updates to the shared navbar/taskbar state.
332      * @param listener Will immediately get callbacks based on current state
333      */
registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener)334     public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
335         mStateListeners.add(listener);
336         if (!mTogglingNavbarTaskbar && mStateListeners.size() == 1) {
337             setupOnFirstBar();
338 
339             // Update the state once the first bar is registered
340             updateAssistantAvailability();
341             updateA11yState();
342             mCommandQueue.recomputeDisableFlags(mContext.getDisplayId(), false /* animate */);
343         } else {
344             listener.updateAccessibilityServicesState();
345             listener.updateAssistantAvailable(mAssistantAvailable, mLongPressHomeEnabled);
346         }
347         listener.updateWallpaperVisibility(mWallpaperVisible, mDefaultDisplayId);
348 
349         mBgHandler.post(() -> {
350             Boolean isRotationLocked = RotationPolicyUtil.isRotationLocked(mContext);
351             mMainExecutor.execute(
352                     () -> listener.updateRotationWatcherState(
353                             mRotationWatcherRotation, isRotationLocked));
354         });
355     }
356 
357     /**
358      * Removes a previously registered listener.
359      */
removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener)360     public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
361         mStateListeners.remove(listener);
362         if (!mTogglingNavbarTaskbar && mStateListeners.isEmpty()) {
363             cleanupAfterLastBar();
364         }
365     }
366 
dispatchA11yEventUpdate()367     private void dispatchA11yEventUpdate() {
368         for (NavbarTaskbarStateUpdater listener : mStateListeners) {
369             listener.updateAccessibilityServicesState();
370         }
371     }
372 
dispatchAssistantEventUpdate(boolean assistantAvailable, boolean longPressHomeEnabled)373     private void dispatchAssistantEventUpdate(boolean assistantAvailable,
374             boolean longPressHomeEnabled) {
375         for (NavbarTaskbarStateUpdater listener : mStateListeners) {
376             listener.updateAssistantAvailable(assistantAvailable, longPressHomeEnabled);
377         }
378     }
379 
380     @Override
onAccessibilityServicesStateChanged(AccessibilityManager manager)381     public void onAccessibilityServicesStateChanged(AccessibilityManager manager) {
382         updateA11yState();
383     }
384 
385     @Override
onAccessibilityButtonModeChanged(int mode)386     public void onAccessibilityButtonModeChanged(int mode) {
387         updateA11yState();
388     }
389 
390     @Override
onAccessibilityButtonTargetsChanged(String targets)391     public void onAccessibilityButtonTargetsChanged(String targets) {
392         updateA11yState();
393     }
394 
395     @Override
onAccessibilityGestureTargetsChanged(String targets)396     public void onAccessibilityGestureTargetsChanged(String targets) {
397         updateA11yState();
398     }
399 
400     @Override
onConfigChanged(Configuration newConfig)401     public void onConfigChanged(Configuration newConfig) {
402         mEdgeBackGestureHandler.onConfigurationChanged(newConfig);
403     }
404 
getNumOfA11yShortcutTargetsForNavSystem()405     private int getNumOfA11yShortcutTargetsForNavSystem() {
406         final int buttonMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
407         final int shortcutType;
408         if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
409             shortcutType = buttonMode
410                     != ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU ? SOFTWARE : DEFAULT;
411             // If accessibility button is floating menu mode, there are no clickable targets.
412         } else {
413             if (mNavBarMode == NAV_BAR_MODE_GESTURAL) {
414                 shortcutType = GESTURE;
415             } else {
416                 shortcutType = buttonMode == ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR
417                         ? SOFTWARE : DEFAULT;
418             }
419         }
420         return mAccessibilityManager.getAccessibilityShortcutTargets(shortcutType).size();
421     }
422 
423     /**
424      * Updates the current accessibility button state. The accessibility button state is only
425      * used for {@link Secure#ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR} and
426      * {@link Secure#ACCESSIBILITY_BUTTON_MODE_GESTURE}, otherwise it is reset to 0.
427      */
428     @VisibleForTesting
updateA11yState()429     void updateA11yState() {
430         final long prevState = mA11yButtonState;
431         final boolean clickable;
432         final boolean longClickable;
433         int clickableServices = getNumOfA11yShortcutTargetsForNavSystem();
434         clickable = clickableServices >= 1;
435         // `longClickable` is used to determine whether to pop up the accessibility chooser
436         // dialog or not, and it’s also only for multiple services.
437         longClickable = clickableServices >= 2;
438         mA11yButtonState = (clickable ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0)
439                 | (longClickable ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0);
440 
441         // Update the system actions if the state has changed
442         if (prevState != mA11yButtonState) {
443             updateSystemAction(clickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON);
444             updateSystemAction(longClickable, SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER);
445         }
446 
447         dispatchA11yEventUpdate();
448     }
449 
450     /**
451      * Registers/unregisters the given system action id.
452      */
updateSystemAction(boolean register, int actionId)453     private void updateSystemAction(boolean register, int actionId) {
454         if (register) {
455             mSystemActions.register(actionId);
456         } else {
457             mSystemActions.unregister(actionId);
458         }
459     }
460 
461     /**
462      * Gets the accessibility button state based on the {@link Secure#ACCESSIBILITY_BUTTON_MODE}.
463      *
464      * @return the accessibility button state:
465      * 0 = disable state
466      * 16 = {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE}
467      * 48 = the combination of {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and
468      * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE}
469      */
getA11yButtonState()470     public long getA11yButtonState() {
471         return mA11yButtonState;
472     }
473 
474     @Override
onConnectionChanged(boolean isConnected)475     public void onConnectionChanged(boolean isConnected) {
476         if (isConnected) {
477             // We add the OPS callback during construction, so if the service is already connected
478             // then we will try to get the AssistManager dependency which itself has an indirect
479             // dependency on NavBarHelper leading to a cycle. For now, we can defer updating the
480             // assistant availability.
481             mMainExecutor.execute(this::updateAssistantAvailability);
482         }
483     }
484 
updateAssistantAvailability()485     private void updateAssistantAvailability() {
486         boolean assistantAvailableForUser = mAssistManagerLazy.get()
487                 .getAssistInfoForUser(mUserTracker.getUserId()) != null;
488 
489         boolean overrideLongPressHome = mAssistManagerLazy.get()
490                 .shouldOverrideAssist(AssistManager.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
491         boolean longPressDefault = mContext.getResources().getBoolean(overrideLongPressHome
492                 ? com.android.internal.R.bool.config_searchAllEntrypointsEnabledDefault
493                 : com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
494         mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver,
495                 overrideLongPressHome ? Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED
496                         : Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0,
497                 mUserTracker.getUserId()) != 0;
498 
499         boolean gestureDefault = mContext.getResources().getBoolean(
500                 com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
501         mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver,
502                 Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0,
503                 mUserTracker.getUserId()) != 0;
504 
505         boolean supportsSwipeGesture = QuickStepContract.isGesturalMode(mNavBarMode)
506                 || (QuickStepContract.isLegacyMode(mNavBarMode) && Flags.threeButtonCornerSwipe());
507         mAssistantAvailable = assistantAvailableForUser
508                 && mAssistantTouchGestureEnabled
509                 && supportsSwipeGesture;
510         dispatchAssistantEventUpdate(mAssistantAvailable, mLongPressHomeEnabled);
511     }
512 
getLongPressHomeEnabled()513     public boolean getLongPressHomeEnabled() {
514         return mLongPressHomeEnabled;
515     }
516 
getEdgeBackGestureHandler()517     public EdgeBackGestureHandler getEdgeBackGestureHandler() {
518         return mEdgeBackGestureHandler;
519     }
520 
521     @Override
startAssistant(Bundle bundle)522     public void startAssistant(Bundle bundle) {
523         mAssistManagerLazy.get().startAssist(bundle);
524     }
525 
526     @Override
setAssistantOverridesRequested(int[] invocationTypes)527     public void setAssistantOverridesRequested(int[] invocationTypes) {
528         mAssistManagerLazy.get().setAssistantOverridesRequested(invocationTypes);
529         updateAssistantAvailability();
530     }
531 
532     @Override
onNavigationModeChanged(int mode)533     public void onNavigationModeChanged(int mode) {
534         mNavBarMode = mode;
535         updateAssistantAvailability();
536     }
537 
538     /**
539      * Checks whether the IME is visible on top of the screen, based on the given IME window
540      * visibility flags, and the current keyguard state.
541      *
542      * @param vis the IME window visibility.
543      */
isImeVisible(@meWindowVisibility int vis)544     public boolean isImeVisible(@ImeWindowVisibility int vis) {
545         View shadeWindowView =  mNotificationShadeWindowController.getWindowRootView();
546         boolean isKeyguardShowing = mKeyguardStateController.isShowing();
547         boolean imeVisibleOnShade = shadeWindowView != null && shadeWindowView.isAttachedToWindow()
548                 && shadeWindowView.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
549         return imeVisibleOnShade
550                 || (!isKeyguardShowing && (vis & InputMethodService.IME_VISIBLE) != 0);
551     }
552 
553     @Override
setWindowState(int displayId, int window, int state)554     public void setWindowState(int displayId, int window, int state) {
555         CommandQueue.Callbacks.super.setWindowState(displayId, window, state);
556         if (window != WINDOW_NAVIGATION_BAR) {
557             return;
558         }
559         mWindowStateDisplayId = displayId;
560         mWindowState = state;
561     }
562 
dispatchWallpaperVisibilityChanged(boolean visible, int displayId)563     private void dispatchWallpaperVisibilityChanged(boolean visible, int displayId) {
564         for (NavbarTaskbarStateUpdater listener : mStateListeners) {
565             listener.updateWallpaperVisibility(visible, displayId);
566         }
567     }
568 
dispatchRotationChanged(int rotation, @Nullable Boolean isRotationLocked)569     private void dispatchRotationChanged(int rotation, @Nullable Boolean isRotationLocked) {
570         for (NavbarTaskbarStateUpdater listener : mStateListeners) {
571             listener.updateRotationWatcherState(rotation, isRotationLocked);
572         }
573     }
574 
getCurrentSysuiState()575     public CurrentSysuiState getCurrentSysuiState() {
576         return new CurrentSysuiState();
577     }
578 
579     /**
580      * Callbacks will get fired once immediately after registering via
581      * {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)}
582      */
583     public interface NavbarTaskbarStateUpdater {
updateAccessibilityServicesState()584         void updateAccessibilityServicesState();
updateAssistantAvailable(boolean available, boolean longPressHomeEnabled)585         void updateAssistantAvailable(boolean available, boolean longPressHomeEnabled);
updateWallpaperVisibility(boolean visible, int displayId)586         default void updateWallpaperVisibility(boolean visible, int displayId) {}
updateRotationWatcherState(int rotation, @Nullable Boolean isRotationLocked)587         default void updateRotationWatcherState(int rotation, @Nullable Boolean isRotationLocked) {}
588     }
589 
590     /** Data class to help Taskbar/Navbar initiate state correctly when switching between the two.*/
591     public class CurrentSysuiState {
592         public final int mWindowStateDisplayId;
593         public final @WindowVisibleState int mWindowState;
594 
CurrentSysuiState()595         public CurrentSysuiState() {
596             mWindowStateDisplayId = NavBarHelper.this.mWindowStateDisplayId;
597             mWindowState = NavBarHelper.this.mWindowState;
598         }
599     }
600 
transitionMode(boolean isTransient, int appearance)601     public static @TransitionMode int transitionMode(boolean isTransient, int appearance) {
602         final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_NAVIGATION_BARS;
603         if (isTransient) {
604             return MODE_SEMI_TRANSPARENT;
605         } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
606             return MODE_LIGHTS_OUT;
607         } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
608             return MODE_LIGHTS_OUT_TRANSPARENT;
609         } else if ((appearance & APPEARANCE_OPAQUE_NAVIGATION_BARS) != 0) {
610             return MODE_OPAQUE;
611         } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS) != 0) {
612             return MODE_SEMI_TRANSPARENT;
613         } else {
614             return MODE_TRANSPARENT;
615         }
616     }
617 
618     @Override
dump(@onNull PrintWriter pw, @NonNull String[] args)619     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
620         pw.println("NavbarTaskbarFriendster");
621         pw.println("  longPressHomeEnabled=" + mLongPressHomeEnabled);
622         pw.println("  mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled);
623         pw.println("  mAssistantAvailable=" + mAssistantAvailable);
624         pw.println("  mNavBarMode=" + mNavBarMode);
625     }
626 }
627