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