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.statusbar.phone; 18 19 import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION; 20 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; 21 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; 22 23 import android.annotation.Nullable; 24 import android.app.StatusBarManager; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.res.Resources; 29 import android.os.Bundle; 30 import android.os.PowerManager; 31 import android.os.SystemClock; 32 import android.os.VibrationAttributes; 33 import android.os.VibrationEffect; 34 import android.os.Vibrator; 35 import android.util.Log; 36 import android.util.Slog; 37 import android.view.HapticFeedbackConstants; 38 import android.view.KeyEvent; 39 import android.view.WindowInsets; 40 import android.view.WindowInsets.Type.InsetsType; 41 import android.view.WindowInsetsController.Appearance; 42 import android.view.WindowInsetsController.Behavior; 43 44 import androidx.annotation.VisibleForTesting; 45 46 import com.android.internal.logging.MetricsLogger; 47 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 48 import com.android.internal.statusbar.LetterboxDetails; 49 import com.android.internal.view.AppearanceRegion; 50 import com.android.keyguard.KeyguardUpdateMonitor; 51 import com.android.systemui.R; 52 import com.android.systemui.assist.AssistManager; 53 import com.android.systemui.camera.CameraIntents; 54 import com.android.systemui.dagger.qualifiers.DisplayId; 55 import com.android.systemui.dagger.qualifiers.Main; 56 import com.android.systemui.flags.FeatureFlags; 57 import com.android.systemui.keyguard.WakefulnessLifecycle; 58 import com.android.systemui.plugins.ActivityStarter; 59 import com.android.systemui.qs.QSHost; 60 import com.android.systemui.qs.QSPanelController; 61 import com.android.systemui.settings.UserTracker; 62 import com.android.systemui.shade.CameraLauncher; 63 import com.android.systemui.shade.QuickSettingsController; 64 import com.android.systemui.shade.ShadeController; 65 import com.android.systemui.shade.ShadeViewController; 66 import com.android.systemui.statusbar.CommandQueue; 67 import com.android.systemui.statusbar.VibratorHelper; 68 import com.android.systemui.statusbar.disableflags.DisableFlagsLogger; 69 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; 70 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent; 71 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 72 import com.android.systemui.statusbar.policy.HeadsUpManager; 73 import com.android.systemui.statusbar.policy.KeyguardStateController; 74 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; 75 76 import dagger.Lazy; 77 78 import java.util.Optional; 79 80 import javax.inject.Inject; 81 82 /** */ 83 @CentralSurfacesComponent.CentralSurfacesScope 84 public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callbacks { 85 private final CentralSurfaces mCentralSurfaces; 86 private final Context mContext; 87 private final com.android.systemui.shade.ShadeController mShadeController; 88 private final CommandQueue mCommandQueue; 89 private final ShadeViewController mShadeViewController; 90 private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler; 91 private final MetricsLogger mMetricsLogger; 92 private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; 93 private final KeyguardStateController mKeyguardStateController; 94 private final HeadsUpManager mHeadsUpManager; 95 private final WakefulnessLifecycle mWakefulnessLifecycle; 96 private final DeviceProvisionedController mDeviceProvisionedController; 97 private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; 98 private final AssistManager mAssistManager; 99 private final DozeServiceHost mDozeServiceHost; 100 private final NotificationStackScrollLayoutController mNotificationStackScrollLayoutController; 101 private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; 102 private final PowerManager mPowerManager; 103 private final VibratorHelper mVibratorHelper; 104 private final Optional<Vibrator> mVibratorOptional; 105 private final DisableFlagsLogger mDisableFlagsLogger; 106 private final int mDisplayId; 107 private final UserTracker mUserTracker; 108 private final boolean mVibrateOnOpening; 109 private final VibrationEffect mCameraLaunchGestureVibrationEffect; 110 private final SystemBarAttributesListener mSystemBarAttributesListener; 111 private final ActivityStarter mActivityStarter; 112 private final Lazy<CameraLauncher> mCameraLauncherLazy; 113 private final QuickSettingsController mQsController; 114 private final QSHost mQSHost; 115 private final FeatureFlags mFeatureFlags; 116 117 private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES = 118 VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK); 119 120 private int mDisabled1; 121 private int mDisabled2; 122 123 @Inject CentralSurfacesCommandQueueCallbacks( CentralSurfaces centralSurfaces, QuickSettingsController quickSettingsController, Context context, @Main Resources resources, ShadeController shadeController, CommandQueue commandQueue, ShadeViewController shadeViewController, RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, MetricsLogger metricsLogger, KeyguardUpdateMonitor keyguardUpdateMonitor, KeyguardStateController keyguardStateController, HeadsUpManager headsUpManager, WakefulnessLifecycle wakefulnessLifecycle, DeviceProvisionedController deviceProvisionedController, StatusBarKeyguardViewManager statusBarKeyguardViewManager, AssistManager assistManager, DozeServiceHost dozeServiceHost, NotificationStackScrollLayoutController notificationStackScrollLayoutController, StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, PowerManager powerManager, VibratorHelper vibratorHelper, Optional<Vibrator> vibratorOptional, DisableFlagsLogger disableFlagsLogger, @DisplayId int displayId, SystemBarAttributesListener systemBarAttributesListener, Lazy<CameraLauncher> cameraLauncherLazy, UserTracker userTracker, QSHost qsHost, ActivityStarter activityStarter, FeatureFlags featureFlags)124 CentralSurfacesCommandQueueCallbacks( 125 CentralSurfaces centralSurfaces, 126 QuickSettingsController quickSettingsController, 127 Context context, 128 @Main Resources resources, 129 ShadeController shadeController, 130 CommandQueue commandQueue, 131 ShadeViewController shadeViewController, 132 RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler, 133 MetricsLogger metricsLogger, 134 KeyguardUpdateMonitor keyguardUpdateMonitor, 135 KeyguardStateController keyguardStateController, 136 HeadsUpManager headsUpManager, 137 WakefulnessLifecycle wakefulnessLifecycle, 138 DeviceProvisionedController deviceProvisionedController, 139 StatusBarKeyguardViewManager statusBarKeyguardViewManager, 140 AssistManager assistManager, 141 DozeServiceHost dozeServiceHost, 142 NotificationStackScrollLayoutController notificationStackScrollLayoutController, 143 StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager, 144 PowerManager powerManager, 145 VibratorHelper vibratorHelper, 146 Optional<Vibrator> vibratorOptional, 147 DisableFlagsLogger disableFlagsLogger, 148 @DisplayId int displayId, 149 SystemBarAttributesListener systemBarAttributesListener, 150 Lazy<CameraLauncher> cameraLauncherLazy, 151 UserTracker userTracker, 152 QSHost qsHost, 153 ActivityStarter activityStarter, 154 FeatureFlags featureFlags) { 155 mCentralSurfaces = centralSurfaces; 156 mQsController = quickSettingsController; 157 mContext = context; 158 mShadeController = shadeController; 159 mCommandQueue = commandQueue; 160 mShadeViewController = shadeViewController; 161 mRemoteInputQuickSettingsDisabler = remoteInputQuickSettingsDisabler; 162 mMetricsLogger = metricsLogger; 163 mKeyguardUpdateMonitor = keyguardUpdateMonitor; 164 mKeyguardStateController = keyguardStateController; 165 mHeadsUpManager = headsUpManager; 166 mWakefulnessLifecycle = wakefulnessLifecycle; 167 mDeviceProvisionedController = deviceProvisionedController; 168 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager; 169 mAssistManager = assistManager; 170 mDozeServiceHost = dozeServiceHost; 171 mNotificationStackScrollLayoutController = notificationStackScrollLayoutController; 172 mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager; 173 mPowerManager = powerManager; 174 mVibratorHelper = vibratorHelper; 175 mVibratorOptional = vibratorOptional; 176 mDisableFlagsLogger = disableFlagsLogger; 177 mDisplayId = displayId; 178 mCameraLauncherLazy = cameraLauncherLazy; 179 mUserTracker = userTracker; 180 mQSHost = qsHost; 181 mFeatureFlags = featureFlags; 182 183 mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation); 184 mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect( 185 mVibratorOptional, resources); 186 mSystemBarAttributesListener = systemBarAttributesListener; 187 mActivityStarter = activityStarter; 188 } 189 190 @Override abortTransient(int displayId, @InsetsType int types)191 public void abortTransient(int displayId, @InsetsType int types) { 192 if (displayId != mDisplayId) { 193 return; 194 } 195 if ((types & WindowInsets.Type.statusBars()) == 0) { 196 return; 197 } 198 mCentralSurfaces.clearTransient(); 199 } 200 201 @Override addQsTile(ComponentName tile)202 public void addQsTile(ComponentName tile) { 203 mQSHost.addTile(tile); 204 } 205 206 @Override remQsTile(ComponentName tile)207 public void remQsTile(ComponentName tile) { 208 mQSHost.removeTileByUser(tile); 209 } 210 211 @Override clickTile(ComponentName tile)212 public void clickTile(ComponentName tile) { 213 // Can't inject this because it changes with the QS fragment 214 QSPanelController qsPanelController = mCentralSurfaces.getQSPanelController(); 215 if (qsPanelController != null) { 216 qsPanelController.clickTile(tile); 217 } 218 } 219 220 @Override animateCollapsePanels(int flags, boolean force)221 public void animateCollapsePanels(int flags, boolean force) { 222 mShadeController.animateCollapseShade(flags, force, false /* delayed */, 223 1.0f /* speedUpFactor */); 224 } 225 226 @Override animateExpandNotificationsPanel()227 public void animateExpandNotificationsPanel() { 228 if (CentralSurfaces.SPEW) { 229 Log.d(CentralSurfaces.TAG, 230 "animateExpand: mExpandedVisible=" + mShadeController.isExpandedVisible()); 231 } 232 mShadeController.animateExpandShade(); 233 } 234 235 @Override animateExpandSettingsPanel(@ullable String subPanel)236 public void animateExpandSettingsPanel(@Nullable String subPanel) { 237 if (CentralSurfaces.SPEW) { 238 Log.d(CentralSurfaces.TAG, 239 "animateExpand: mExpandedVisible=" + mShadeController.isExpandedVisible()); 240 } 241 mShadeController.animateExpandQs(); 242 } 243 244 @Override appTransitionCancelled(int displayId)245 public void appTransitionCancelled(int displayId) { 246 } 247 248 @Override appTransitionFinished(int displayId)249 public void appTransitionFinished(int displayId) { 250 } 251 252 @Override dismissKeyboardShortcutsMenu()253 public void dismissKeyboardShortcutsMenu() { 254 mCentralSurfaces.resendMessage(CentralSurfaces.MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU); 255 } 256 /** 257 * State is one or more of the DISABLE constants from StatusBarManager. 258 * 259 * @deprecated If you need to react to changes in disable flags, listen to 260 * {@link com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository} 261 * instead. 262 */ 263 @Override 264 @Deprecated disable(int displayId, int state1, int state2, boolean animate)265 public void disable(int displayId, int state1, int state2, boolean animate) { 266 if (displayId != mDisplayId) { 267 return; 268 } 269 270 final int old1 = mDisabled1; 271 final int diff1 = state1 ^ old1; 272 mDisabled1 = state1; 273 274 state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2); 275 final int old2 = mDisabled2; 276 final int diff2 = state2 ^ old2; 277 mDisabled2 = state2; 278 279 if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { 280 if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { 281 mShadeController.animateCollapseShade(); 282 } 283 } 284 285 if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) { 286 if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) { 287 mHeadsUpManager.releaseAllImmediately(); 288 } 289 } 290 291 if ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { 292 if ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0) { 293 mShadeController.animateCollapseShade(); 294 } 295 } 296 297 mShadeViewController.disableHeader(state1, state2, animate); 298 } 299 300 /** 301 * Called for system navigation gestures. First action opens the panel, second opens 302 * settings. Down action closes the entire panel. 303 */ 304 @Override handleSystemKey(KeyEvent key)305 public void handleSystemKey(KeyEvent key) { 306 if (CentralSurfaces.SPEW) { 307 Log.d(CentralSurfaces.TAG, "handleNavigationKey: " + key); 308 } 309 if (!mCommandQueue.panelsEnabled() || !mKeyguardUpdateMonitor.isDeviceInteractive() 310 || mKeyguardStateController.isShowing() && !mKeyguardStateController.isOccluded()) { 311 return; 312 } 313 314 // Panels are not available in setup 315 if (!mDeviceProvisionedController.isCurrentUserSetup()) return; 316 317 if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP == key.getKeyCode()) { 318 mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_UP); 319 mShadeViewController.collapse( 320 false /* delayed */, 1.0f /* speedUpFactor */); 321 } else if (KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN == key.getKeyCode()) { 322 mMetricsLogger.action(MetricsEvent.ACTION_SYSTEM_NAVIGATION_KEY_DOWN); 323 if (mShadeViewController.isFullyCollapsed()) { 324 if (mVibrateOnOpening) { 325 vibrateOnNavigationKeyDown(); 326 } 327 mShadeViewController.expand(true /* animate */); 328 mNotificationStackScrollLayoutController.setWillExpand(true); 329 mHeadsUpManager.unpinAll(true /* userUnpinned */); 330 mMetricsLogger.count("panel_open", 1); 331 } else if (!mQsController.getExpanded() 332 && !mShadeViewController.isExpandingOrCollapsing()) { 333 mQsController.flingQs(0 /* velocity */, 334 ShadeViewController.FLING_EXPAND); 335 mMetricsLogger.count("panel_open_qs", 1); 336 } 337 } 338 339 } 340 341 @Override onCameraLaunchGestureDetected(int source)342 public void onCameraLaunchGestureDetected(int source) { 343 mCentralSurfaces.setLastCameraLaunchSource(source); 344 if (mCentralSurfaces.isGoingToSleep()) { 345 if (CentralSurfaces.DEBUG_CAMERA_LIFT) { 346 Slog.d(CentralSurfaces.TAG, "Finish going to sleep before launching camera"); 347 } 348 mCentralSurfaces.setLaunchCameraOnFinishedGoingToSleep(true); 349 return; 350 } 351 if (!mCameraLauncherLazy.get().canCameraGestureBeLaunched( 352 mShadeViewController.getBarState())) { 353 if (CentralSurfaces.DEBUG_CAMERA_LIFT) { 354 Slog.d(CentralSurfaces.TAG, "Can't launch camera right now"); 355 } 356 return; 357 } 358 if (!mCentralSurfaces.isDeviceInteractive()) { 359 mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_CAMERA_LAUNCH, 360 "com.android.systemui:CAMERA_GESTURE"); 361 } 362 vibrateForCameraGesture(); 363 364 if (source == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) { 365 Log.v(CentralSurfaces.TAG, "Camera launch"); 366 mKeyguardUpdateMonitor.onCameraLaunched(); 367 } 368 369 if (!mKeyguardStateController.isShowing()) { 370 final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext); 371 cameraIntent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source); 372 mActivityStarter.startActivityDismissingKeyguard(cameraIntent, 373 false /* onlyProvisioned */, true /* dismissShade */, 374 true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0, 375 null /* animationController */, mUserTracker.getUserHandle()); 376 } else { 377 if (!mCentralSurfaces.isDeviceInteractive()) { 378 // Avoid flickering of the scrim when we instant launch the camera and the bouncer 379 // comes on. 380 mCentralSurfaces.acquireGestureWakeLock( 381 CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); 382 } 383 if (isWakingUpOrAwake()) { 384 if (CentralSurfaces.DEBUG_CAMERA_LIFT) { 385 Slog.d(CentralSurfaces.TAG, "Launching camera"); 386 } 387 if (mStatusBarKeyguardViewManager.isBouncerShowing()) { 388 mStatusBarKeyguardViewManager.reset(true /* hide */); 389 } 390 mCameraLauncherLazy.get().launchCamera(source, 391 mShadeViewController.isFullyCollapsed()); 392 mCentralSurfaces.updateScrimController(); 393 } else { 394 // We need to defer the camera launch until the screen comes on, since otherwise 395 // we will dismiss us too early since we are waiting on an activity to be drawn and 396 // incorrectly get notified because of the screen on event (which resumes and pauses 397 // some activities) 398 if (CentralSurfaces.DEBUG_CAMERA_LIFT) { 399 Slog.d(CentralSurfaces.TAG, "Deferring until screen turns on"); 400 } 401 mCentralSurfaces.setLaunchCameraOnFinishedWaking(true); 402 } 403 } 404 } 405 406 @Override onEmergencyActionLaunchGestureDetected()407 public void onEmergencyActionLaunchGestureDetected() { 408 Intent emergencyIntent = mCentralSurfaces.getEmergencyActionIntent(); 409 410 if (emergencyIntent == null) { 411 Log.wtf(CentralSurfaces.TAG, "Couldn't find an app to process the emergency intent."); 412 return; 413 } 414 415 if (isGoingToSleep()) { 416 mCentralSurfaces.setLaunchEmergencyActionOnFinishedGoingToSleep(true); 417 return; 418 } 419 420 if (!mCentralSurfaces.isDeviceInteractive()) { 421 mPowerManager.wakeUp(SystemClock.uptimeMillis(), 422 PowerManager.WAKE_REASON_GESTURE, 423 "com.android.systemui:EMERGENCY_GESTURE"); 424 } 425 // TODO(b/169087248) Possibly add haptics here for emergency action. Currently disabled for 426 // app-side haptic experimentation. 427 428 if (!mKeyguardStateController.isShowing()) { 429 mActivityStarter.startActivityDismissingKeyguard(emergencyIntent, 430 false /* onlyProvisioned */, true /* dismissShade */, 431 true /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */, 0, 432 null /* animationController */, mUserTracker.getUserHandle()); 433 return; 434 } 435 436 if (!mCentralSurfaces.isDeviceInteractive()) { 437 // Avoid flickering of the scrim when we instant launch the camera and the bouncer 438 // comes on. 439 mCentralSurfaces.acquireGestureWakeLock( 440 CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); 441 } 442 443 if (isWakingUpOrAwake()) { 444 if (mStatusBarKeyguardViewManager.isBouncerShowing()) { 445 mStatusBarKeyguardViewManager.reset(true /* hide */); 446 } 447 mContext.startActivityAsUser(emergencyIntent, mUserTracker.getUserHandle()); 448 return; 449 } 450 // We need to defer the emergency action launch until the screen comes on, since otherwise 451 // we will dismiss us too early since we are waiting on an activity to be drawn and 452 // incorrectly get notified because of the screen on event (which resumes and pauses 453 // some activities) 454 mCentralSurfaces.setLaunchEmergencyActionOnFinishedWaking(true); 455 } 456 457 @Override onRecentsAnimationStateChanged(boolean running)458 public void onRecentsAnimationStateChanged(boolean running) { 459 mCentralSurfaces.setInteracting(StatusBarManager.WINDOW_NAVIGATION_BAR, running); 460 } 461 462 463 @Override onSystemBarAttributesChanged(int displayId, @Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, LetterboxDetails[] letterboxDetails)464 public void onSystemBarAttributesChanged(int displayId, @Appearance int appearance, 465 AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, 466 @Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, 467 LetterboxDetails[] letterboxDetails) { 468 if (displayId != mDisplayId) { 469 return; 470 } 471 // SystemBarAttributesListener should __always__ be the top-level listener for system bar 472 // attributes changed. 473 mSystemBarAttributesListener.onSystemBarAttributesChanged( 474 displayId, 475 appearance, 476 appearanceRegions, 477 navbarColorManagedByIme, 478 behavior, 479 requestedVisibleTypes, 480 packageName, 481 letterboxDetails 482 ); 483 } 484 485 @Override showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar)486 public void showTransient(int displayId, @InsetsType int types, boolean isGestureOnSystemBar) { 487 if (displayId != mDisplayId) { 488 return; 489 } 490 if ((types & WindowInsets.Type.statusBars()) == 0) { 491 return; 492 } 493 mCentralSurfaces.showTransientUnchecked(); 494 } 495 496 @Override toggleKeyboardShortcutsMenu(int deviceId)497 public void toggleKeyboardShortcutsMenu(int deviceId) { 498 mCentralSurfaces.resendMessage(new CentralSurfaces.KeyboardShortcutsMessage(deviceId)); 499 } 500 501 @Override setTopAppHidesStatusBar(boolean topAppHidesStatusBar)502 public void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { 503 mStatusBarHideIconsForBouncerManager 504 .setTopAppHidesStatusBarAndTriggerUpdate(topAppHidesStatusBar); 505 } 506 507 @Override showAssistDisclosure()508 public void showAssistDisclosure() { 509 mAssistManager.showDisclosure(); 510 } 511 512 @Override showPinningEnterExitToast(boolean entering)513 public void showPinningEnterExitToast(boolean entering) { 514 mCentralSurfaces.showPinningEnterExitToast(entering); 515 } 516 517 @Override showPinningEscapeToast()518 public void showPinningEscapeToast() { 519 mCentralSurfaces.showPinningEscapeToast(); 520 } 521 522 @Override showScreenPinningRequest(int taskId)523 public void showScreenPinningRequest(int taskId) { 524 if (mKeyguardStateController.isShowing()) { 525 // Don't allow apps to trigger this from keyguard. 526 return; 527 } 528 // Show screen pinning request, since this comes from an app, show 'no thanks', button. 529 mCentralSurfaces.showScreenPinningRequest(taskId, true); 530 } 531 532 @Override showWirelessChargingAnimation(int batteryLevel)533 public void showWirelessChargingAnimation(int batteryLevel) { 534 mCentralSurfaces.showWirelessChargingAnimation(batteryLevel); 535 } 536 537 @Override startAssist(Bundle args)538 public void startAssist(Bundle args) { 539 mAssistManager.startAssist(args); 540 } 541 542 @Override suppressAmbientDisplay(boolean suppressed)543 public void suppressAmbientDisplay(boolean suppressed) { 544 mDozeServiceHost.setAlwaysOnSuppressed(suppressed); 545 } 546 547 @Override togglePanel()548 public void togglePanel() { 549 if (mShadeViewController.isPanelExpanded()) { 550 mShadeController.animateCollapseShade(); 551 } else { 552 mShadeController.animateExpandShade(); 553 } 554 } 555 isGoingToSleep()556 private boolean isGoingToSleep() { 557 return mWakefulnessLifecycle.getWakefulness() 558 == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; 559 } 560 isWakingUpOrAwake()561 private boolean isWakingUpOrAwake() { 562 return mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE 563 || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING; 564 } 565 vibrateForCameraGesture()566 private void vibrateForCameraGesture() { 567 mVibratorOptional.ifPresent( 568 v -> v.vibrate(mCameraLaunchGestureVibrationEffect, 569 HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES)); 570 } 571 getCameraGestureVibrationEffect( Optional<Vibrator> vibratorOptional, Resources resources)572 private static VibrationEffect getCameraGestureVibrationEffect( 573 Optional<Vibrator> vibratorOptional, Resources resources) { 574 if (vibratorOptional.isPresent() && vibratorOptional.get().areAllPrimitivesSupported( 575 VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 576 VibrationEffect.Composition.PRIMITIVE_CLICK)) { 577 return VibrationEffect.startComposition() 578 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE) 579 .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 50) 580 .compose(); 581 } 582 if (vibratorOptional.isPresent() && vibratorOptional.get().hasAmplitudeControl()) { 583 // Make sure to pass -1 for repeat so VibratorManagerService doesn't stop us when going 584 // to sleep. 585 return VibrationEffect.createWaveform( 586 CentralSurfaces.CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS, 587 CentralSurfaces.CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES, 588 /* repeat= */ -1); 589 } 590 591 int[] pattern = resources.getIntArray(R.array.config_cameraLaunchGestureVibePattern); 592 long[] timings = new long[pattern.length]; 593 for (int i = 0; i < pattern.length; i++) { 594 timings[i] = pattern[i]; 595 } 596 return VibrationEffect.createWaveform(timings, /* repeat= */ -1); 597 } 598 599 @VisibleForTesting vibrateOnNavigationKeyDown()600 void vibrateOnNavigationKeyDown() { 601 if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) { 602 mShadeViewController.performHapticFeedback( 603 HapticFeedbackConstants.GESTURE_START 604 ); 605 } else { 606 mVibratorHelper.vibrate(VibrationEffect.EFFECT_TICK); 607 } 608 } 609 } 610