12981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos/* 22981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * Copyright (C) 2017 The Android Open Source Project 32981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * 42981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License"); 52981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * you may not use this file except in compliance with the License. 62981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * You may obtain a copy of the License at 72981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * 82981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * http://www.apache.org/licenses/LICENSE-2.0 92981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * 102981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * Unless required by applicable law or agreed to in writing, software 112981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS, 122981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * See the License for the specific language governing permissions and 142981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * limitations under the License 152981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos */ 162981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos 172981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roospackage com.android.systemui.doze; 182981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos 198db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roosimport android.os.Handler; 205854384a6a32a2e7753a0442453045a66ee3e98fLucas Dupinimport android.util.Log; 212981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roosimport android.view.Display; 222981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos 2312663d30baa5d691f3d132d9242e6186b0791807Lucas Dupinimport com.android.systemui.statusbar.phone.DozeParameters; 2439880be88c3b40c45e189199d7b7a633410bd85dAdrian Roosimport com.android.systemui.util.wakelock.SettableWakeLock; 2516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupinimport com.android.systemui.util.wakelock.WakeLock; 2612663d30baa5d691f3d132d9242e6186b0791807Lucas Dupin 272981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos/** 282981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos * Controls the screen when dozing. 292981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos */ 302981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roospublic class DozeScreenState implements DozeMachine.Part { 315854384a6a32a2e7753a0442453045a66ee3e98fLucas Dupin 325854384a6a32a2e7753a0442453045a66ee3e98fLucas Dupin private static final boolean DEBUG = DozeService.DEBUG; 335854384a6a32a2e7753a0442453045a66ee3e98fLucas Dupin private static final String TAG = "DozeScreenState"; 345854384a6a32a2e7753a0442453045a66ee3e98fLucas Dupin 3516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin /** 3616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin * Delay entering low power mode when animating to make sure that we'll have 3716cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin * time to move all elements into their final positions while still at 60 fps. 3816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin */ 39cbe0596c4d7d438ac840fffe4b819ef5f5bea6f9Lucas Dupin private static final int ENTER_DOZE_DELAY = 6000; 40cbe0596c4d7d438ac840fffe4b819ef5f5bea6f9Lucas Dupin /** 41cbe0596c4d7d438ac840fffe4b819ef5f5bea6f9Lucas Dupin * Hide wallpaper earlier when entering low power mode. The gap between 42cbe0596c4d7d438ac840fffe4b819ef5f5bea6f9Lucas Dupin * hiding the wallpaper and changing the display mode is necessary to hide 43cbe0596c4d7d438ac840fffe4b819ef5f5bea6f9Lucas Dupin * the black frame that's inherent to hardware specs. 44cbe0596c4d7d438ac840fffe4b819ef5f5bea6f9Lucas Dupin */ 4561b8eaf289e736cbc40f489c8c6f270daf094dd1Lucas Dupin public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 4500; 4616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 472981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos private final DozeMachine.Service mDozeService; 488db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos private final Handler mHandler; 49a79ad59d49cdb3ef6f4cf864094063e3e9111586Adrian Roos private final Runnable mApplyPendingScreenState = this::applyPendingScreenState; 5012663d30baa5d691f3d132d9242e6186b0791807Lucas Dupin private final DozeParameters mParameters; 51a79ad59d49cdb3ef6f4cf864094063e3e9111586Adrian Roos 528db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos private int mPendingScreenState = Display.STATE_UNKNOWN; 5339880be88c3b40c45e189199d7b7a633410bd85dAdrian Roos private SettableWakeLock mWakeLock; 542981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos 5512663d30baa5d691f3d132d9242e6186b0791807Lucas Dupin public DozeScreenState(DozeMachine.Service service, Handler handler, 5616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin DozeParameters parameters, WakeLock wakeLock) { 572981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos mDozeService = service; 588db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos mHandler = handler; 5912663d30baa5d691f3d132d9242e6186b0791807Lucas Dupin mParameters = parameters; 6039880be88c3b40c45e189199d7b7a633410bd85dAdrian Roos mWakeLock = new SettableWakeLock(wakeLock); 612981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos } 622981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos 632981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos @Override 642981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { 6512663d30baa5d691f3d132d9242e6186b0791807Lucas Dupin int screenState = newState.screenState(mParameters); 665502b8942f15e7141686a623f6176339e2389b8dAdrian Roos 675502b8942f15e7141686a623f6176339e2389b8dAdrian Roos if (newState == DozeMachine.State.FINISH) { 685502b8942f15e7141686a623f6176339e2389b8dAdrian Roos // Make sure not to apply the screen state after DozeService was destroyed. 695502b8942f15e7141686a623f6176339e2389b8dAdrian Roos mPendingScreenState = Display.STATE_UNKNOWN; 705502b8942f15e7141686a623f6176339e2389b8dAdrian Roos mHandler.removeCallbacks(mApplyPendingScreenState); 715502b8942f15e7141686a623f6176339e2389b8dAdrian Roos 725502b8942f15e7141686a623f6176339e2389b8dAdrian Roos applyScreenState(screenState); 7339880be88c3b40c45e189199d7b7a633410bd85dAdrian Roos mWakeLock.setAcquired(false); 745502b8942f15e7141686a623f6176339e2389b8dAdrian Roos return; 755502b8942f15e7141686a623f6176339e2389b8dAdrian Roos } 765502b8942f15e7141686a623f6176339e2389b8dAdrian Roos 778db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos if (screenState == Display.STATE_UNKNOWN) { 788db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos // We'll keep it in the existing state 798db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos return; 808db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos } 815502b8942f15e7141686a623f6176339e2389b8dAdrian Roos 828db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState); 833d7ccaf8b5e81378770cb3e18ff66d19418b8135Lucas Dupin boolean pulseEnding = oldState == DozeMachine.State.DOZE_PULSE_DONE 843d7ccaf8b5e81378770cb3e18ff66d19418b8135Lucas Dupin && newState == DozeMachine.State.DOZE_AOD; 853d7ccaf8b5e81378770cb3e18ff66d19418b8135Lucas Dupin if (messagePending || oldState == DozeMachine.State.INITIALIZED || pulseEnding) { 868db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos // During initialization, we hide the navigation bar. That is however only applied after 878db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos // a traversal; setting the screen state here is immediate however, so it can happen 888db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos // that the screen turns on again before the navigation bar is hidden. To work around 898db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos // that, wait for a traversal to happen before applying the initial screen state. 908db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos mPendingScreenState = screenState; 9116cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 9216cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin // Delay screen state transitions even longer while animations are running. 9316cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD 9416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin && mParameters.shouldControlScreenOff(); 9516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 9639880be88c3b40c45e189199d7b7a633410bd85dAdrian Roos if (shouldDelayTransition) { 9739880be88c3b40c45e189199d7b7a633410bd85dAdrian Roos mWakeLock.setAcquired(true); 9816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 9916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 1008db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos if (!messagePending) { 10116cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin if (DEBUG) { 10216cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin Log.d(TAG, "Display state changed to " + screenState + " delayed by " 10316cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin + (shouldDelayTransition ? ENTER_DOZE_DELAY : 1)); 10416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 10516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 10616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin if (shouldDelayTransition) { 10716cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY); 10816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } else { 10916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mHandler.post(mApplyPendingScreenState); 11016cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 11116cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } else if (DEBUG) { 11216cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin Log.d(TAG, "Pending display state change to " + screenState); 1138db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos } 11416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } else { 11516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin applyScreenState(screenState); 1168db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos } 1178db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos } 1188db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos 1198db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos private void applyPendingScreenState() { 1208db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos applyScreenState(mPendingScreenState); 1218db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos mPendingScreenState = Display.STATE_UNKNOWN; 1228db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos } 1238db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos 1248db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos private void applyScreenState(int screenState) { 1252981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos if (screenState != Display.STATE_UNKNOWN) { 1265854384a6a32a2e7753a0442453045a66ee3e98fLucas Dupin if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")"); 1272981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos mDozeService.setDozeScreenState(screenState); 1288db9311cb683c58b7d61f812ae4975feca926aa4Adrian Roos mPendingScreenState = Display.STATE_UNKNOWN; 12939880be88c3b40c45e189199d7b7a633410bd85dAdrian Roos mWakeLock.setAcquired(false); 1302981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos } 1312981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos } 1322981eb0d59f3568bfe84ce905c82fc17d62d21c5Adrian Roos} 133