1 /* 2 * Copyright (C) 2016 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.doze; 18 19 import android.annotation.Nullable; 20 import android.app.AlarmManager; 21 import android.app.UiModeManager; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.res.Configuration; 27 import android.hardware.display.AmbientDisplayConfiguration; 28 import android.metrics.LogMaker; 29 import android.os.SystemClock; 30 import android.os.UserHandle; 31 import android.text.format.Formatter; 32 import android.util.Log; 33 import android.view.Display; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.internal.logging.MetricsLogger; 37 import com.android.internal.logging.UiEvent; 38 import com.android.internal.logging.UiEventLogger; 39 import com.android.internal.logging.UiEventLoggerImpl; 40 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 41 import com.android.internal.util.IndentingPrintWriter; 42 import com.android.systemui.Dependency; 43 import com.android.systemui.broadcast.BroadcastDispatcher; 44 import com.android.systemui.dock.DockManager; 45 import com.android.systemui.statusbar.phone.DozeParameters; 46 import com.android.systemui.util.Assert; 47 import com.android.systemui.util.sensors.AsyncSensorManager; 48 import com.android.systemui.util.sensors.ProximitySensor; 49 import com.android.systemui.util.wakelock.WakeLock; 50 51 import java.io.PrintWriter; 52 import java.util.Optional; 53 import java.util.function.Consumer; 54 55 /** 56 * Handles triggers for ambient state changes. 57 */ 58 public class DozeTriggers implements DozeMachine.Part { 59 60 private static final String TAG = "DozeTriggers"; 61 private static final boolean DEBUG = DozeService.DEBUG; 62 63 /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */ 64 private static final String PULSE_ACTION = "com.android.systemui.doze.pulse"; 65 66 private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl(); 67 68 /** 69 * Last value sent by the wake-display sensor. 70 * Assuming that the screen should start on. 71 */ 72 private static boolean sWakeDisplaySensorState = true; 73 74 private static final int PROXIMITY_TIMEOUT_DELAY_MS = 500; 75 76 private final Context mContext; 77 private final DozeMachine mMachine; 78 private final DozeLog mDozeLog; 79 private final DozeSensors mDozeSensors; 80 private final DozeHost mDozeHost; 81 private final AmbientDisplayConfiguration mConfig; 82 private final DozeParameters mDozeParameters; 83 private final AsyncSensorManager mSensorManager; 84 private final WakeLock mWakeLock; 85 private final boolean mAllowPulseTriggers; 86 private final UiModeManager mUiModeManager; 87 private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver(); 88 private final DockEventListener mDockEventListener = new DockEventListener(); 89 private final DockManager mDockManager; 90 private final ProximitySensor.ProximityCheck mProxCheck; 91 private final BroadcastDispatcher mBroadcastDispatcher; 92 93 private long mNotificationPulseTime; 94 private boolean mPulsePending; 95 96 private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); 97 private boolean mWantProx; 98 private boolean mWantSensors; 99 private boolean mWantTouchScreenSensors; 100 101 @VisibleForTesting 102 public enum DozingUpdateUiEvent implements UiEventLogger.UiEventEnum { 103 @UiEvent(doc = "Dozing updated due to notification.") 104 DOZING_UPDATE_NOTIFICATION(433), 105 106 @UiEvent(doc = "Dozing updated due to sigmotion.") 107 DOZING_UPDATE_SIGMOTION(434), 108 109 @UiEvent(doc = "Dozing updated because sensor was picked up.") 110 DOZING_UPDATE_SENSOR_PICKUP(435), 111 112 @UiEvent(doc = "Dozing updated because sensor was double tapped.") 113 DOZING_UPDATE_SENSOR_DOUBLE_TAP(436), 114 115 @UiEvent(doc = "Dozing updated because sensor was long squeezed.") 116 DOZING_UPDATE_SENSOR_LONG_SQUEEZE(437), 117 118 @UiEvent(doc = "Dozing updated due to docking.") 119 DOZING_UPDATE_DOCKING(438), 120 121 @UiEvent(doc = "Dozing updated because sensor woke up.") 122 DOZING_UPDATE_SENSOR_WAKEUP(439), 123 124 @UiEvent(doc = "Dozing updated because sensor woke up the lockscreen.") 125 DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN(440), 126 127 @UiEvent(doc = "Dozing updated because sensor was tapped.") 128 DOZING_UPDATE_SENSOR_TAP(441); 129 130 private final int mId; 131 DozingUpdateUiEvent(int id)132 DozingUpdateUiEvent(int id) { 133 mId = id; 134 } 135 136 @Override getId()137 public int getId() { 138 return mId; 139 } 140 fromReason(int reason)141 static DozingUpdateUiEvent fromReason(int reason) { 142 switch (reason) { 143 case 1: return DOZING_UPDATE_NOTIFICATION; 144 case 2: return DOZING_UPDATE_SIGMOTION; 145 case 3: return DOZING_UPDATE_SENSOR_PICKUP; 146 case 4: return DOZING_UPDATE_SENSOR_DOUBLE_TAP; 147 case 5: return DOZING_UPDATE_SENSOR_LONG_SQUEEZE; 148 case 6: return DOZING_UPDATE_DOCKING; 149 case 7: return DOZING_UPDATE_SENSOR_WAKEUP; 150 case 8: return DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN; 151 case 9: return DOZING_UPDATE_SENSOR_TAP; 152 default: return null; 153 } 154 } 155 } 156 DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost, AlarmManager alarmManager, AmbientDisplayConfiguration config, DozeParameters dozeParameters, AsyncSensorManager sensorManager, WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager, ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proxCheck, DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher)157 public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost, 158 AlarmManager alarmManager, AmbientDisplayConfiguration config, 159 DozeParameters dozeParameters, AsyncSensorManager sensorManager, 160 WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager, 161 ProximitySensor proximitySensor, ProximitySensor.ProximityCheck proxCheck, 162 DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) { 163 mContext = context; 164 mMachine = machine; 165 mDozeHost = dozeHost; 166 mConfig = config; 167 mDozeParameters = dozeParameters; 168 mSensorManager = sensorManager; 169 mWakeLock = wakeLock; 170 mAllowPulseTriggers = allowPulseTriggers; 171 mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters, 172 config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor); 173 mUiModeManager = mContext.getSystemService(UiModeManager.class); 174 mDockManager = dockManager; 175 mProxCheck = proxCheck; 176 mDozeLog = dozeLog; 177 mBroadcastDispatcher = broadcastDispatcher; 178 } 179 180 @Override destroy()181 public void destroy() { 182 mDozeSensors.destroy(); 183 } 184 onNotification(Runnable onPulseSuppressedListener)185 private void onNotification(Runnable onPulseSuppressedListener) { 186 if (DozeMachine.DEBUG) { 187 Log.d(TAG, "requestNotificationPulse"); 188 } 189 if (!sWakeDisplaySensorState) { 190 Log.d(TAG, "Wake display false. Pulse denied."); 191 runIfNotNull(onPulseSuppressedListener); 192 mDozeLog.tracePulseDropped("wakeDisplaySensor"); 193 return; 194 } 195 mNotificationPulseTime = SystemClock.elapsedRealtime(); 196 if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) { 197 runIfNotNull(onPulseSuppressedListener); 198 mDozeLog.tracePulseDropped("pulseOnNotificationsDisabled"); 199 return; 200 } 201 if (mDozeHost.isDozeSuppressed()) { 202 runIfNotNull(onPulseSuppressedListener); 203 mDozeLog.tracePulseDropped("dozeSuppressed"); 204 return; 205 } 206 requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */, 207 onPulseSuppressedListener); 208 mDozeLog.traceNotificationPulse(); 209 } 210 runIfNotNull(Runnable runnable)211 private static void runIfNotNull(Runnable runnable) { 212 if (runnable != null) { 213 runnable.run(); 214 } 215 } 216 proximityCheckThenCall(Consumer<Boolean> callback, boolean alreadyPerformedProxCheck, int reason)217 private void proximityCheckThenCall(Consumer<Boolean> callback, 218 boolean alreadyPerformedProxCheck, 219 int reason) { 220 Boolean cachedProxNear = mDozeSensors.isProximityCurrentlyNear(); 221 if (alreadyPerformedProxCheck) { 222 callback.accept(null); 223 } else if (cachedProxNear != null) { 224 callback.accept(cachedProxNear); 225 } else { 226 final long start = SystemClock.uptimeMillis(); 227 mProxCheck.check(PROXIMITY_TIMEOUT_DELAY_MS, near -> { 228 final long end = SystemClock.uptimeMillis(); 229 mDozeLog.traceProximityResult( 230 near == null ? false : near, 231 end - start, 232 reason); 233 callback.accept(near); 234 mWakeLock.release(TAG); 235 }); 236 mWakeLock.acquire(TAG); 237 } 238 } 239 240 @VisibleForTesting onSensor(int pulseReason, float screenX, float screenY, float[] rawValues)241 void onSensor(int pulseReason, float screenX, float screenY, float[] rawValues) { 242 boolean isDoubleTap = pulseReason == DozeLog.REASON_SENSOR_DOUBLE_TAP; 243 boolean isTap = pulseReason == DozeLog.REASON_SENSOR_TAP; 244 boolean isPickup = pulseReason == DozeLog.REASON_SENSOR_PICKUP; 245 boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS; 246 boolean isWakeDisplay = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP; 247 boolean isWakeLockScreen = pulseReason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN; 248 boolean wakeEvent = rawValues != null && rawValues.length > 0 && rawValues[0] != 0; 249 250 if (isWakeDisplay) { 251 onWakeScreen(wakeEvent, mMachine.isExecutingTransition() ? null : mMachine.getState()); 252 } else if (isLongPress) { 253 requestPulse(pulseReason, true /* alreadyPerformedProxCheck */, 254 null /* onPulseSupressedListener */); 255 } else if (isWakeLockScreen) { 256 if (wakeEvent) { 257 requestPulse(pulseReason, true /* alreadyPerformedProxCheck */, 258 null /* onPulseSupressedListener */); 259 } 260 } else { 261 proximityCheckThenCall((result) -> { 262 if (result != null && result) { 263 // In pocket, drop event. 264 return; 265 } 266 if (isDoubleTap || isTap) { 267 if (screenX != -1 && screenY != -1) { 268 mDozeHost.onSlpiTap(screenX, screenY); 269 } 270 gentleWakeUp(pulseReason); 271 } else if (isPickup) { 272 gentleWakeUp(pulseReason); 273 } else { 274 mDozeHost.extendPulse(pulseReason); 275 } 276 }, true /* alreadyPerformedProxCheck */, pulseReason); 277 } 278 279 if (isPickup) { 280 final long timeSinceNotification = 281 SystemClock.elapsedRealtime() - mNotificationPulseTime; 282 final boolean withinVibrationThreshold = 283 timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); 284 mDozeLog.tracePickupWakeUp(withinVibrationThreshold); 285 } 286 } 287 288 private void gentleWakeUp(int reason) { 289 // Log screen wake up reason (lift/pickup, tap, double-tap) 290 mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) 291 .setType(MetricsEvent.TYPE_UPDATE) 292 .setSubtype(reason)); 293 Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason)) 294 .ifPresent(UI_EVENT_LOGGER::log); 295 if (mDozeParameters.getDisplayNeedsBlanking()) { 296 // Let's prepare the display to wake-up by drawing black. 297 // This will cover the hardware wake-up sequence, where the display 298 // becomes black for a few frames. 299 mDozeHost.setAodDimmingScrim(1f); 300 } 301 mMachine.wakeUp(); 302 } 303 304 private void onProximityFar(boolean far) { 305 // Proximity checks are asynchronous and the user might have interacted with the phone 306 // when a new event is arriving. This means that a state transition might have happened 307 // and the proximity check is now obsolete. 308 if (mMachine.isExecutingTransition()) { 309 Log.w(TAG, "onProximityFar called during transition. Ignoring sensor response."); 310 return; 311 } 312 313 final boolean near = !far; 314 final DozeMachine.State state = mMachine.getState(); 315 final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED); 316 final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING); 317 final boolean aod = (state == DozeMachine.State.DOZE_AOD); 318 319 if (state == DozeMachine.State.DOZE_PULSING 320 || state == DozeMachine.State.DOZE_PULSING_BRIGHT) { 321 boolean ignoreTouch = near; 322 if (DEBUG) { 323 Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch); 324 } 325 mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch); 326 } 327 328 if (far && (paused || pausing)) { 329 if (DEBUG) { 330 Log.i(TAG, "Prox FAR, unpausing AOD"); 331 } 332 mMachine.requestState(DozeMachine.State.DOZE_AOD); 333 } else if (near && aod) { 334 if (DEBUG) { 335 Log.i(TAG, "Prox NEAR, pausing AOD"); 336 } 337 mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING); 338 } 339 } 340 341 /** 342 * When a wake screen event is received from a sensor 343 * @param wake {@code true} when it's time to wake up, {@code false} when we should sleep. 344 * @param state The current state, or null if the state could not be determined due to enqueued 345 * transitions. 346 */ 347 private void onWakeScreen(boolean wake, @Nullable DozeMachine.State state) { 348 mDozeLog.traceWakeDisplay(wake); 349 sWakeDisplaySensorState = wake; 350 351 if (wake) { 352 proximityCheckThenCall((result) -> { 353 if (result != null && result) { 354 // In pocket, drop event. 355 return; 356 } 357 if (state == DozeMachine.State.DOZE) { 358 mMachine.requestState(DozeMachine.State.DOZE_AOD); 359 // Logs AOD open due to sensor wake up. 360 mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) 361 .setType(MetricsEvent.TYPE_OPEN) 362 .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP)); 363 } 364 }, true /* alreadyPerformedProxCheck */, DozeLog.REASON_SENSOR_WAKE_UP); 365 } else { 366 boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED); 367 boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING); 368 if (!pausing && !paused) { 369 mMachine.requestState(DozeMachine.State.DOZE); 370 // Logs AOD close due to sensor wake up. 371 mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) 372 .setType(MetricsEvent.TYPE_CLOSE) 373 .setSubtype(DozeLog.REASON_SENSOR_WAKE_UP)); 374 } 375 } 376 } 377 378 @Override transitionTo(DozeMachine.State oldState, DozeMachine.State newState)379 public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { 380 switch (newState) { 381 case INITIALIZED: 382 mBroadcastReceiver.register(mBroadcastDispatcher); 383 mDozeHost.addCallback(mHostCallback); 384 mDockManager.addListener(mDockEventListener); 385 mDozeSensors.requestTemporaryDisable(); 386 checkTriggersAtInit(); 387 break; 388 case DOZE: 389 case DOZE_AOD: 390 mWantProx = newState != DozeMachine.State.DOZE; 391 mWantSensors = true; 392 mWantTouchScreenSensors = true; 393 if (newState == DozeMachine.State.DOZE_AOD && !sWakeDisplaySensorState) { 394 onWakeScreen(false, newState); 395 } 396 break; 397 case DOZE_AOD_PAUSED: 398 case DOZE_AOD_PAUSING: 399 mWantProx = true; 400 break; 401 case DOZE_PULSING: 402 case DOZE_PULSING_BRIGHT: 403 mWantProx = true; 404 mWantTouchScreenSensors = false; 405 break; 406 case DOZE_AOD_DOCKED: 407 mWantProx = false; 408 mWantTouchScreenSensors = false; 409 break; 410 case DOZE_PULSE_DONE: 411 mDozeSensors.requestTemporaryDisable(); 412 break; 413 case FINISH: 414 mBroadcastReceiver.unregister(mBroadcastDispatcher); 415 mDozeHost.removeCallback(mHostCallback); 416 mDockManager.removeListener(mDockEventListener); 417 mDozeSensors.setListening(false, false); 418 mDozeSensors.setProxListening(false); 419 mWantSensors = false; 420 mWantProx = false; 421 mWantTouchScreenSensors = false; 422 break; 423 default: 424 } 425 mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors); 426 } 427 428 @Override onScreenState(int state)429 public void onScreenState(int state) { 430 mDozeSensors.onScreenState(state); 431 mDozeSensors.setProxListening(mWantProx && (state == Display.STATE_DOZE 432 || state == Display.STATE_DOZE_SUSPEND 433 || state == Display.STATE_OFF)); 434 mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors); 435 } 436 checkTriggersAtInit()437 private void checkTriggersAtInit() { 438 if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR 439 || mDozeHost.isBlockingDoze() 440 || !mDozeHost.isProvisioned()) { 441 mMachine.requestState(DozeMachine.State.FINISH); 442 } 443 } 444 requestPulse(final int reason, boolean performedProxCheck, Runnable onPulseSuppressedListener)445 private void requestPulse(final int reason, boolean performedProxCheck, 446 Runnable onPulseSuppressedListener) { 447 Assert.isMainThread(); 448 mDozeHost.extendPulse(reason); 449 450 // When already pulsing we're allowed to show the wallpaper directly without 451 // requesting a new pulse. 452 if (mMachine.getState() == DozeMachine.State.DOZE_PULSING 453 && reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN) { 454 mMachine.requestState(DozeMachine.State.DOZE_PULSING_BRIGHT); 455 return; 456 } 457 458 if (mPulsePending || !mAllowPulseTriggers || !canPulse()) { 459 if (mAllowPulseTriggers) { 460 mDozeLog.tracePulseDropped(mPulsePending, mMachine.getState(), 461 mDozeHost.isPulsingBlocked()); 462 } 463 runIfNotNull(onPulseSuppressedListener); 464 return; 465 } 466 467 mPulsePending = true; 468 proximityCheckThenCall((result) -> { 469 if (result != null && result) { 470 // in pocket, abort pulse 471 mDozeLog.tracePulseDropped("inPocket"); 472 mPulsePending = false; 473 runIfNotNull(onPulseSuppressedListener); 474 } else { 475 // not in pocket, continue pulsing 476 continuePulseRequest(reason); 477 } 478 }, !mDozeParameters.getProxCheckBeforePulse() || performedProxCheck, reason); 479 480 // Logs request pulse reason on AOD screen. 481 mMetricsLogger.write(new LogMaker(MetricsEvent.DOZING) 482 .setType(MetricsEvent.TYPE_UPDATE).setSubtype(reason)); 483 Optional.ofNullable(DozingUpdateUiEvent.fromReason(reason)) 484 .ifPresent(UI_EVENT_LOGGER::log); 485 } 486 canPulse()487 private boolean canPulse() { 488 return mMachine.getState() == DozeMachine.State.DOZE 489 || mMachine.getState() == DozeMachine.State.DOZE_AOD 490 || mMachine.getState() == DozeMachine.State.DOZE_AOD_DOCKED; 491 } 492 continuePulseRequest(int reason)493 private void continuePulseRequest(int reason) { 494 mPulsePending = false; 495 if (mDozeHost.isPulsingBlocked() || !canPulse()) { 496 mDozeLog.tracePulseDropped(mPulsePending, mMachine.getState(), 497 mDozeHost.isPulsingBlocked()); 498 return; 499 } 500 mMachine.requestPulse(reason); 501 } 502 503 @Override dump(PrintWriter pw)504 public void dump(PrintWriter pw) { 505 pw.print(" notificationPulseTime="); 506 pw.println(Formatter.formatShortElapsedTime(mContext, mNotificationPulseTime)); 507 508 pw.println(" pulsePending=" + mPulsePending); 509 pw.println("DozeSensors:"); 510 IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 511 idpw.increaseIndent(); 512 mDozeSensors.dump(idpw); 513 } 514 515 private class TriggerReceiver extends BroadcastReceiver { 516 private boolean mRegistered; 517 518 @Override onReceive(Context context, Intent intent)519 public void onReceive(Context context, Intent intent) { 520 if (PULSE_ACTION.equals(intent.getAction())) { 521 if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent"); 522 requestPulse(DozeLog.PULSE_REASON_INTENT, false, /* performedProxCheck */ 523 null /* onPulseSupressedListener */); 524 } 525 if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) { 526 mMachine.requestState(DozeMachine.State.FINISH); 527 } 528 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 529 mDozeSensors.onUserSwitched(); 530 } 531 } 532 register(BroadcastDispatcher broadcastDispatcher)533 public void register(BroadcastDispatcher broadcastDispatcher) { 534 if (mRegistered) { 535 return; 536 } 537 IntentFilter filter = new IntentFilter(PULSE_ACTION); 538 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); 539 filter.addAction(Intent.ACTION_USER_SWITCHED); 540 broadcastDispatcher.registerReceiver(this, filter); 541 mRegistered = true; 542 } 543 unregister(BroadcastDispatcher broadcastDispatcher)544 public void unregister(BroadcastDispatcher broadcastDispatcher) { 545 if (!mRegistered) { 546 return; 547 } 548 broadcastDispatcher.unregisterReceiver(this); 549 mRegistered = false; 550 } 551 } 552 553 private class DockEventListener implements DockManager.DockEventListener { 554 @Override onEvent(int event)555 public void onEvent(int event) { 556 if (DEBUG) Log.d(TAG, "dock event = " + event); 557 switch (event) { 558 case DockManager.STATE_DOCKED: 559 case DockManager.STATE_DOCKED_HIDE: 560 mDozeSensors.ignoreTouchScreenSensorsSettingInterferingWithDocking(true); 561 break; 562 case DockManager.STATE_NONE: 563 mDozeSensors.ignoreTouchScreenSensorsSettingInterferingWithDocking(false); 564 break; 565 default: 566 // no-op 567 } 568 } 569 } 570 571 private DozeHost.Callback mHostCallback = new DozeHost.Callback() { 572 @Override 573 public void onNotificationAlerted(Runnable onPulseSuppressedListener) { 574 onNotification(onPulseSuppressedListener); 575 } 576 577 @Override 578 public void onPowerSaveChanged(boolean active) { 579 if (mDozeHost.isPowerSaveActive()) { 580 mMachine.requestState(DozeMachine.State.DOZE); 581 } else if (mMachine.getState() == DozeMachine.State.DOZE 582 && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)) { 583 mMachine.requestState(DozeMachine.State.DOZE_AOD); 584 } 585 } 586 587 @Override 588 public void onDozeSuppressedChanged(boolean suppressed) { 589 final DozeMachine.State nextState; 590 if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) && !suppressed) { 591 nextState = DozeMachine.State.DOZE_AOD; 592 } else { 593 nextState = DozeMachine.State.DOZE; 594 } 595 mMachine.requestState(nextState); 596 } 597 }; 598 } 599