1 /*
2  * Copyright 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.ActivityManager.LOCK_TASK_MODE_PINNED;
20 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
21 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
22 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
23 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
24 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
25 
26 import static com.android.systemui.navigationbar.NavBarHelper.transitionMode;
27 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
28 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
29 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
30 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
31 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
32 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
33 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
34 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IMMERSIVE_MODE;
35 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
36 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
37 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
38 import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
39 
40 import android.app.StatusBarManager;
41 import android.app.StatusBarManager.WindowVisibleState;
42 import android.content.Context;
43 import android.content.res.Configuration;
44 import android.graphics.Rect;
45 import android.hardware.display.DisplayManager;
46 import android.inputmethodservice.InputMethodService;
47 import android.os.IBinder;
48 import android.os.RemoteException;
49 import android.util.Log;
50 import android.view.Display;
51 import android.view.View;
52 import android.view.WindowInsets;
53 import android.view.WindowInsets.Type.InsetsType;
54 import android.view.WindowInsetsController.Appearance;
55 import android.view.WindowInsetsController.Behavior;
56 
57 import androidx.annotation.NonNull;
58 import androidx.annotation.VisibleForTesting;
59 
60 import com.android.internal.statusbar.LetterboxDetails;
61 import com.android.internal.view.AppearanceRegion;
62 import com.android.systemui.Dumpable;
63 import com.android.systemui.dagger.SysUISingleton;
64 import com.android.systemui.dump.DumpManager;
65 import com.android.systemui.model.SysUiState;
66 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
67 import com.android.systemui.recents.OverviewProxyService;
68 import com.android.systemui.shared.recents.utilities.Utilities;
69 import com.android.systemui.shared.system.QuickStepContract;
70 import com.android.systemui.shared.system.TaskStackChangeListener;
71 import com.android.systemui.shared.system.TaskStackChangeListeners;
72 import com.android.systemui.statusbar.AutoHideUiElement;
73 import com.android.systemui.statusbar.CommandQueue;
74 import com.android.systemui.statusbar.phone.AutoHideController;
75 import com.android.systemui.statusbar.phone.BarTransitions;
76 import com.android.systemui.statusbar.phone.LightBarController;
77 import com.android.systemui.statusbar.phone.LightBarTransitionsController;
78 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
79 import com.android.wm.shell.back.BackAnimation;
80 import com.android.wm.shell.pip.Pip;
81 
82 import java.io.PrintWriter;
83 import java.util.Optional;
84 import java.util.function.Consumer;
85 
86 import javax.inject.Inject;
87 
88 /** */
89 @SysUISingleton
90 public class TaskbarDelegate implements CommandQueue.Callbacks,
91         OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
92         Dumpable {
93     private static final String TAG = TaskbarDelegate.class.getSimpleName();
94 
95     private EdgeBackGestureHandler mEdgeBackGestureHandler;
96     private final LightBarTransitionsController.Factory mLightBarTransitionsControllerFactory;
97     private boolean mInitialized;
98     private CommandQueue mCommandQueue;
99     private OverviewProxyService mOverviewProxyService;
100     private NavBarHelper mNavBarHelper;
101     private NavigationModeController mNavigationModeController;
102     private SysUiState mSysUiState;
103     private AutoHideController mAutoHideController;
104     private LightBarController mLightBarController;
105     private LightBarTransitionsController mLightBarTransitionsController;
106     private TaskStackChangeListeners mTaskStackChangeListeners;
107     private Optional<Pip> mPipOptional;
108     private int mDisplayId;
109     private int mNavigationIconHints;
110     private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater =
111             new NavBarHelper.NavbarTaskbarStateUpdater() {
112                 @Override
113                 public void updateAccessibilityServicesState() {
114                     updateSysuiFlags();
115                 }
116 
117                 @Override
118                 public void updateAssistantAvailable(boolean available,
119                         boolean longPressHomeEnabled) {
120                     updateAssistantAvailability(available, longPressHomeEnabled);
121                 }
122             };
123     private int mDisabledFlags;
124     private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING;
125 
126     private @TransitionMode int mTransitionMode;
127     private @Appearance int mAppearance;
128     private @Behavior int mBehavior;
129     private final Context mContext;
130     private final DisplayManager mDisplayManager;
131     private Context mWindowContext;
132     private ScreenPinningNotify mScreenPinningNotify;
133     private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
134         @Override
135         public void onLockTaskModeChanged(int mode) {
136             mSysUiState.setFlag(SYSUI_STATE_SCREEN_PINNING, mode == LOCK_TASK_MODE_PINNED)
137                     .commitUpdate(mDisplayId);
138         }
139     };
140 
141     private int mNavigationMode = -1;
142     private final Consumer<Rect> mPipListener;
143 
144     /**
145      * Tracks the system calls for when taskbar should transiently show or hide so we can return
146      * this value in {@link AutoHideUiElement#isVisible()} below.
147      *
148      * This also gets set by {@link #onTaskbarAutohideSuspend(boolean)} to force show the transient
149      * taskbar if launcher has requested to suspend auto-hide behavior.
150      */
151     private boolean mTaskbarTransientShowing;
152     private final AutoHideUiElement mAutoHideUiElement = new AutoHideUiElement() {
153         @Override
154         public void synchronizeState() {
155         }
156 
157         @Override
158         public boolean isVisible() {
159             return mTaskbarTransientShowing;
160         }
161 
162         @Override
163         public void hide() {
164             clearTransient();
165         }
166     };
167 
168     private BackAnimation mBackAnimation;
169 
170     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
171     @Inject
TaskbarDelegate(Context context, LightBarTransitionsController.Factory lightBarTransitionsControllerFactory, StatusBarKeyguardViewManager statusBarKeyguardViewManager)172     public TaskbarDelegate(Context context,
173             LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
174             StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
175         mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
176 
177         mContext = context;
178         mDisplayManager = mContext.getSystemService(DisplayManager.class);
179         mPipListener = (bounds) -> {
180             mEdgeBackGestureHandler.setPipStashExclusionBounds(bounds);
181         };
182         mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
183         mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
184     }
185 
setDependencies(CommandQueue commandQueue, OverviewProxyService overviewProxyService, NavBarHelper navBarHelper, NavigationModeController navigationModeController, SysUiState sysUiState, DumpManager dumpManager, AutoHideController autoHideController, LightBarController lightBarController, Optional<Pip> pipOptional, BackAnimation backAnimation, TaskStackChangeListeners taskStackChangeListeners)186     public void setDependencies(CommandQueue commandQueue,
187             OverviewProxyService overviewProxyService,
188             NavBarHelper navBarHelper,
189             NavigationModeController navigationModeController,
190             SysUiState sysUiState, DumpManager dumpManager,
191             AutoHideController autoHideController,
192             LightBarController lightBarController,
193             Optional<Pip> pipOptional,
194             BackAnimation backAnimation,
195             TaskStackChangeListeners taskStackChangeListeners) {
196         // TODO: adding this in the ctor results in a dagger dependency cycle :(
197         mCommandQueue = commandQueue;
198         mOverviewProxyService = overviewProxyService;
199         mNavBarHelper = navBarHelper;
200         mNavigationModeController = navigationModeController;
201         mSysUiState = sysUiState;
202         dumpManager.registerDumpable(this);
203         mAutoHideController = autoHideController;
204         mLightBarController = lightBarController;
205         mPipOptional = pipOptional;
206         mBackAnimation = backAnimation;
207         mLightBarTransitionsController = createLightBarTransitionsController();
208         mTaskStackChangeListeners = taskStackChangeListeners;
209         mEdgeBackGestureHandler = navBarHelper.getEdgeBackGestureHandler();
210     }
211 
212     // Separated into a method to keep setDependencies() clean/readable.
createLightBarTransitionsController()213     private LightBarTransitionsController createLightBarTransitionsController() {
214 
215         LightBarTransitionsController controller =  mLightBarTransitionsControllerFactory.create(
216                 new LightBarTransitionsController.DarkIntensityApplier() {
217                     @Override
218                     public void applyDarkIntensity(float darkIntensity) {
219                         mOverviewProxyService.onNavButtonsDarkIntensityChanged(darkIntensity);
220                     }
221 
222                     @Override
223                     public int getTintAnimationDuration() {
224                         return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
225                     }
226                 });
227 
228         return controller;
229     }
230 
init(int displayId)231     public void init(int displayId) {
232         if (mInitialized) {
233             return;
234         }
235         mDisplayId = displayId;
236         parseCurrentSysuiState();
237         mCommandQueue.addCallback(this);
238         mOverviewProxyService.addCallback(this);
239         onNavigationModeChanged(mNavigationModeController.addListener(this));
240         mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
241         // Initialize component callback
242         Display display = mDisplayManager.getDisplay(displayId);
243         mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
244         mScreenPinningNotify = new ScreenPinningNotify(mWindowContext);
245         // Set initial state for any listeners
246         updateSysuiFlags();
247         mAutoHideController.setNavigationBar(mAutoHideUiElement);
248         mLightBarController.setNavigationBar(mLightBarTransitionsController);
249         mPipOptional.ifPresent(this::addPipExclusionBoundsChangeListener);
250         mEdgeBackGestureHandler.setBackAnimation(mBackAnimation);
251         mEdgeBackGestureHandler.onConfigurationChanged(mContext.getResources().getConfiguration());
252         mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
253         mInitialized = true;
254     }
255 
destroy()256     public void destroy() {
257         if (!mInitialized) {
258             return;
259         }
260         mCommandQueue.removeCallback(this);
261         mOverviewProxyService.removeCallback(this);
262         mNavigationModeController.removeListener(this);
263         mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
264         mScreenPinningNotify = null;
265         mWindowContext = null;
266         mAutoHideController.setNavigationBar(null);
267         mLightBarTransitionsController.destroy();
268         mLightBarController.setNavigationBar(null);
269         mPipOptional.ifPresent(this::removePipExclusionBoundsChangeListener);
270         mTaskStackChangeListeners.unregisterTaskStackListener(mTaskStackListener);
271         mInitialized = false;
272     }
273 
addPipExclusionBoundsChangeListener(Pip pip)274     void addPipExclusionBoundsChangeListener(Pip pip) {
275         pip.addPipExclusionBoundsChangeListener(mPipListener);
276     }
277 
removePipExclusionBoundsChangeListener(Pip pip)278     void removePipExclusionBoundsChangeListener(Pip pip) {
279         pip.removePipExclusionBoundsChangeListener(mPipListener);
280     }
281 
282     /**
283      * Returns {@code true} if this taskBar is {@link #init(int)}.
284      * Returns {@code false} if this taskbar has not yet been {@link #init(int)}
285      * or has been {@link #destroy()}.
286      */
isInitialized()287     public boolean isInitialized() {
288         return mInitialized;
289     }
290 
parseCurrentSysuiState()291     private void parseCurrentSysuiState() {
292         NavBarHelper.CurrentSysuiState state = mNavBarHelper.getCurrentSysuiState();
293         if (state.mWindowStateDisplayId == mDisplayId) {
294             mTaskBarWindowState = state.mWindowState;
295         }
296     }
297 
updateSysuiFlags()298     private void updateSysuiFlags() {
299         int a11yFlags = mNavBarHelper.getA11yButtonState();
300         boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
301         boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
302 
303         mSysUiState.setFlag(SYSUI_STATE_A11Y_BUTTON_CLICKABLE, clickable)
304                 .setFlag(SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, longClickable)
305                 .setFlag(SYSUI_STATE_IME_SHOWING,
306                         (mNavigationIconHints & NAVIGATION_HINT_BACK_ALT) != 0)
307                 .setFlag(SYSUI_STATE_IME_SWITCHER_SHOWING,
308                         (mNavigationIconHints & NAVIGATION_HINT_IME_SWITCHER_SHOWN) != 0)
309                 .setFlag(SYSUI_STATE_OVERVIEW_DISABLED,
310                         (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0)
311                 .setFlag(SYSUI_STATE_HOME_DISABLED,
312                         (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0)
313                 .setFlag(SYSUI_STATE_BACK_DISABLED,
314                         (mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
315                 .setFlag(SYSUI_STATE_NAV_BAR_HIDDEN, !isWindowVisible())
316                 .setFlag(SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
317                         allowSystemGestureIgnoringBarVisibility())
318                 .setFlag(SYSUI_STATE_IMMERSIVE_MODE, isImmersiveMode())
319                 .commitUpdate(mDisplayId);
320     }
321 
isOverviewEnabled()322     boolean isOverviewEnabled() {
323         return (mSysUiState.getFlags() & View.STATUS_BAR_DISABLE_RECENT) == 0;
324     }
325 
updateAssistantAvailability(boolean assistantAvailable, boolean longPressHomeEnabled)326     private void updateAssistantAvailability(boolean assistantAvailable,
327             boolean longPressHomeEnabled) {
328         if (mOverviewProxyService.getProxy() == null) {
329             return;
330         }
331 
332         try {
333             mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable,
334                     longPressHomeEnabled);
335         } catch (RemoteException e) {
336             Log.e(TAG, "onAssistantAvailable() failed, available: " + assistantAvailable, e);
337         }
338     }
339 
340     @Override
setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher)341     public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
342             boolean showImeSwitcher) {
343         boolean imeShown = mNavBarHelper.isImeShown(vis);
344         if (!imeShown) {
345             // Count imperceptible changes as visible so we transition taskbar out quickly.
346             imeShown = (vis & InputMethodService.IME_VISIBLE_IMPERCEPTIBLE) != 0;
347         }
348         showImeSwitcher = imeShown && showImeSwitcher;
349         int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
350                 imeShown, showImeSwitcher);
351         if (hints != mNavigationIconHints) {
352             mNavigationIconHints = hints;
353             updateSysuiFlags();
354         }
355     }
356 
357     @Override
setWindowState(int displayId, int window, int state)358     public void setWindowState(int displayId, int window, int state) {
359         if (displayId == mDisplayId
360                 && window == StatusBarManager.WINDOW_NAVIGATION_BAR
361                 && mTaskBarWindowState != state) {
362             mTaskBarWindowState = state;
363             updateSysuiFlags();
364         }
365     }
366 
367     @Override
onRotationProposal(int rotation, boolean isValid)368     public void onRotationProposal(int rotation, boolean isValid) {
369         mOverviewProxyService.onRotationProposal(rotation, isValid);
370     }
371 
372     @Override
disable(int displayId, int state1, int state2, boolean animate)373     public void disable(int displayId, int state1, int state2, boolean animate) {
374         mDisabledFlags = state1;
375         updateSysuiFlags();
376         mOverviewProxyService.disable(displayId, state1, state2, animate);
377     }
378 
379     @Override
onSystemBarAttributesChanged(int displayId, int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, int behavior, @InsetsType int requestedVisibleTypes, String packageName, LetterboxDetails[] letterboxDetails)380     public void onSystemBarAttributesChanged(int displayId, int appearance,
381             AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, int behavior,
382             @InsetsType int requestedVisibleTypes, String packageName,
383             LetterboxDetails[] letterboxDetails) {
384         mOverviewProxyService.onSystemBarAttributesChanged(displayId, behavior);
385         boolean nbModeChanged = false;
386         if (mAppearance != appearance) {
387             mAppearance = appearance;
388             nbModeChanged = updateTransitionMode(
389                     transitionMode(mTaskbarTransientShowing, appearance));
390         }
391         if (displayId == mDisplayId) {
392             mLightBarController.onNavigationBarAppearanceChanged(appearance, nbModeChanged,
393                     BarTransitions.MODE_TRANSPARENT, navbarColorManagedByIme);
394         }
395         if (mBehavior != behavior) {
396             mBehavior = behavior;
397             updateSysuiFlags();
398         }
399     }
400 
401     @Override
showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar)402     public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) {
403         if (displayId != mDisplayId) {
404             return;
405         }
406         if ((types & WindowInsets.Type.navigationBars()) == 0) {
407             return;
408         }
409         if (!mTaskbarTransientShowing) {
410             mTaskbarTransientShowing = true;
411             onTransientStateChanged();
412         }
413     }
414 
415     @Override
abortTransient(int displayId, @InsetsType int types)416     public void abortTransient(int displayId, @InsetsType int types) {
417         if (displayId != mDisplayId) {
418             return;
419         }
420         if ((types & WindowInsets.Type.navigationBars()) == 0) {
421             return;
422         }
423         clearTransient();
424     }
425 
426     @Override
onTaskbarAutohideSuspend(boolean suspend)427     public void onTaskbarAutohideSuspend(boolean suspend) {
428         if (suspend) {
429             mAutoHideController.suspendAutoHide();
430         } else {
431             mAutoHideController.resumeSuspendedAutoHide();
432         }
433     }
434 
435     @Override
toggleTaskbar()436     public void toggleTaskbar() {
437         if (mOverviewProxyService.getProxy() == null) {
438             return;
439         }
440 
441         try {
442             mOverviewProxyService.getProxy().onTaskbarToggled();
443         } catch (RemoteException e) {
444             Log.e(TAG, "onTaskbarToggled() failed", e);
445         }
446     }
447 
clearTransient()448     private void clearTransient() {
449         if (mTaskbarTransientShowing) {
450             mTaskbarTransientShowing = false;
451             onTransientStateChanged();
452         }
453     }
454 
onTransientStateChanged()455     private void onTransientStateChanged() {
456         mEdgeBackGestureHandler.onNavBarTransientStateChanged(mTaskbarTransientShowing);
457 
458         final int transitionMode = transitionMode(mTaskbarTransientShowing, mAppearance);
459         if (updateTransitionMode(transitionMode)) {
460             mLightBarController.onNavigationBarModeChanged(transitionMode);
461         }
462     }
463 
updateTransitionMode(int barMode)464     private boolean updateTransitionMode(int barMode) {
465         if (mTransitionMode != barMode) {
466             mTransitionMode = barMode;
467             if (mAutoHideController != null) {
468                 mAutoHideController.touchAutoHide();
469             }
470             return true;
471         }
472         return false;
473     }
474 
475     @Override
onRecentsAnimationStateChanged(boolean running)476     public void onRecentsAnimationStateChanged(boolean running) {
477     }
478 
479     @Override
onNavigationModeChanged(int mode)480     public void onNavigationModeChanged(int mode) {
481         mNavigationMode = mode;
482         mEdgeBackGestureHandler.onNavigationModeChanged(mode);
483     }
484 
isWindowVisible()485     private boolean isWindowVisible() {
486         return mTaskBarWindowState == WINDOW_STATE_SHOWING;
487     }
488 
allowSystemGestureIgnoringBarVisibility()489     private boolean allowSystemGestureIgnoringBarVisibility() {
490         return mBehavior != BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
491     }
492 
isImmersiveMode()493     private boolean isImmersiveMode() {
494         return mBehavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
495     }
496 
onConfigurationChanged(Configuration configuration)497     public void onConfigurationChanged(Configuration configuration) {
498         mEdgeBackGestureHandler.onConfigurationChanged(configuration);
499     }
500 
501     @Override
showPinningEnterExitToast(boolean entering)502     public void showPinningEnterExitToast(boolean entering) {
503         updateSysuiFlags();
504         if (mScreenPinningNotify == null) {
505             return;
506         }
507         if (entering) {
508             mScreenPinningNotify.showPinningStartToast();
509         } else {
510             mScreenPinningNotify.showPinningExitToast();
511         }
512     }
513 
514     @Override
showPinningEscapeToast()515     public void showPinningEscapeToast() {
516         updateSysuiFlags();
517         if (mScreenPinningNotify == null) {
518             return;
519         }
520         mScreenPinningNotify.showEscapeToast(QuickStepContract.isGesturalMode(mNavigationMode),
521                 !QuickStepContract.isGesturalMode(mNavigationMode));
522     }
523 
524     @VisibleForTesting
getNavigationMode()525     int getNavigationMode() {
526         return mNavigationMode;
527     }
528 
529     @Override
dump(@onNull PrintWriter pw, @NonNull String[] args)530     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
531         pw.println("TaskbarDelegate (displayId=" + mDisplayId + "):");
532         pw.println("  mNavigationIconHints=" + mNavigationIconHints);
533         pw.println("  mNavigationMode=" + mNavigationMode);
534         pw.println("  mDisabledFlags=" + mDisabledFlags);
535         pw.println("  mTaskBarWindowState=" + mTaskBarWindowState);
536         pw.println("  mBehavior=" + mBehavior);
537         pw.println("  mTaskbarTransientShowing=" + mTaskbarTransientShowing);
538         mEdgeBackGestureHandler.dump(pw);
539     }
540 }
541