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