1ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos/* 2ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Copyright (C) 2016 The Android Open Source Project 3ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * 4ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License"); 5ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * you may not use this file except in compliance with the License. 6ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * You may obtain a copy of the License at 7ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * 8ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * http://www.apache.org/licenses/LICENSE-2.0 9ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * 10ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Unless required by applicable law or agreed to in writing, software 11ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS, 12ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * See the License for the specific language governing permissions and 14ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * limitations under the License. 15ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos */ 16ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 17ff2c4563cdee60576847e161678549bc501e8d84Adrian Roospackage com.android.systemui.doze; 18ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 194df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupinimport static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED; 204df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupin 21fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roosimport android.app.AlarmManager; 22ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.content.Context; 23fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roosimport android.os.Handler; 24fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roosimport android.os.SystemClock; 25e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roosimport android.text.format.Formatter; 26e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roosimport android.util.Log; 27fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 2816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupinimport com.android.internal.annotations.VisibleForTesting; 2916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupinimport com.android.keyguard.KeyguardUpdateMonitor; 3016cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupinimport com.android.keyguard.KeyguardUpdateMonitorCallback; 3143d0d73d0789025cd92336ec241d2e2e21f558a3Lucas Dupinimport com.android.systemui.statusbar.phone.DozeParameters; 32ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roosimport com.android.systemui.util.AlarmTimeout; 33c1b50324a2286b24b691b8a7190743cbc341727eAdrian Roosimport com.android.systemui.util.wakelock.WakeLock; 34c1b50324a2286b24b691b8a7190743cbc341727eAdrian Roos 35fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roosimport java.util.Calendar; 36fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roosimport java.util.GregorianCalendar; 37ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 38ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos/** 39ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * The policy controlling doze. 40ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos */ 41ff2c4563cdee60576847e161678549bc501e8d84Adrian Roospublic class DozeUi implements DozeMachine.Part { 42ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 43e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min 44ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos private final Context mContext; 45ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos private final DozeHost mHost; 46fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos private final Handler mHandler; 47c1b50324a2286b24b691b8a7190743cbc341727eAdrian Roos private final WakeLock mWakeLock; 48fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos private final DozeMachine mMachine; 49ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roos private final AlarmTimeout mTimeTicker; 5016cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin private final boolean mCanAnimateTransition; 5116cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin private final DozeParameters mDozeParameters; 5216cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 5316cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin private boolean mKeyguardShowing; 5416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback = 5516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin new KeyguardUpdateMonitorCallback() { 5616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 5716cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin @Override 5816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin public void onKeyguardVisibilityChanged(boolean showing) { 5916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mKeyguardShowing = showing; 6016cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin updateAnimateScreenOff(); 6116cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 6216cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin }; 63fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 64e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos private long mLastTimeTickElapsed = 0; 65ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 66fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine, 6743d0d73d0789025cd92336ec241d2e2e21f558a3Lucas Dupin WakeLock wakeLock, DozeHost host, Handler handler, 6816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor) { 69ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mContext = context; 70ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mMachine = machine; 71ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mWakeLock = wakeLock; 72ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mHost = host; 73fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos mHandler = handler; 7416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mCanAnimateTransition = !params.getDisplayNeedsBlanking(); 7516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mDozeParameters = params; 76ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roos mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler); 7716cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback); 7816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 7916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 8016cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin /** 8116cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin * Decide if we're taking over the screen-off animation 8216cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin * when the device was configured to skip doze after screen off. 8316cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin */ 8416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin private void updateAnimateScreenOff() { 8516cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin if (mCanAnimateTransition) { 8616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing; 8716cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mDozeParameters.setControlScreenOffAnimation(controlScreenOff); 8816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mHost.setAnimateScreenOff(controlScreenOff); 8916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 90ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos } 91ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 92ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos private void pulseWhileDozing(int reason) { 93ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mHost.pulseWhileDozing( 94ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos new DozeHost.PulseCallback() { 95ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos @Override 96ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos public void onPulseStarted() { 97ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mMachine.requestState(DozeMachine.State.DOZE_PULSING); 98ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos } 99ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 100ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos @Override 101ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos public void onPulseFinished() { 102ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE); 103ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos } 104ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos }, reason); 105ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos } 106ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos 107ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos @Override 108ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { 109ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos switch (newState) { 110fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos case DOZE_AOD: 1114df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupin if (oldState == DOZE_AOD_PAUSED) { 112f9583c41dce46321bdcd9cea7045a5bedbe0d59dLucas Dupin // Whenever turning on the display, it's necessary to push a new frame. 113f9583c41dce46321bdcd9cea7045a5bedbe0d59dLucas Dupin // The display buffers will be empty and need to be filled. 1144df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupin mHost.dozeTimeTick(); 115f9583c41dce46321bdcd9cea7045a5bedbe0d59dLucas Dupin // The first frame may arrive when the display isn't ready yet. 1163572be2c1c6087b217eb23e1c748bb05a643f459Adrian Roos mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 100); 117370d3272a5fe83499a8af1d1729fb76729268499Adrian Roos // The the delayed frame may arrive when the display isn't ready yet either. 118370d3272a5fe83499a8af1d1729fb76729268499Adrian Roos mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 1000); 1194df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupin } 1204df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupin scheduleTimeTick(); 1214df92c366edbdc9c3429a29ba41b0b57b001411aLucas Dupin break; 1226023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos case DOZE_AOD_PAUSING: 123fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos scheduleTimeTick(); 124fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos break; 125fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos case DOZE: 12667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos case DOZE_AOD_PAUSED: 127fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos unscheduleTimeTick(); 128fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos break; 129ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos case DOZE_REQUEST_PULSE: 130d7b9d10d569438968f75d2453c4293caf89774f2Adrian Roos pulseWhileDozing(mMachine.getPulseReason()); 131ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos break; 132ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos case INITIALIZED: 133ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mHost.startDozing(); 134ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos break; 135ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos case FINISH: 136ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos mHost.stopDozing(); 137fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos unscheduleTimeTick(); 138ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos break; 139ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos } 140013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos updateAnimateWakeup(newState); 14128f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos } 14228f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos 143013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos private void updateAnimateWakeup(DozeMachine.State state) { 14428f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos switch (state) { 14528f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos case DOZE_REQUEST_PULSE: 14628f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos case DOZE_PULSING: 14728f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos case DOZE_PULSE_DONE: 148013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos mHost.setAnimateWakeup(true); 149013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos break; 150013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos case FINISH: 151013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos // Keep current state. 152013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos break; 15328f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos default: 15416cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin mHost.setAnimateWakeup(mCanAnimateTransition && mDozeParameters.getAlwaysOn()); 155013fc4c5e12aa691b2c83f1f869d220bf0f45e08Adrian Roos break; 15628f90c78b213fb436b243126e8bc10c4f554bd1cAdrian Roos } 157ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos } 158fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 159fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos private void scheduleTimeTick() { 160ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roos if (mTimeTicker.isScheduled()) { 161fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos return; 162fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos } 163fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 164fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos long delta = roundToNextMinute(System.currentTimeMillis()) - System.currentTimeMillis(); 165ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roos mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); 166e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos mLastTimeTickElapsed = SystemClock.elapsedRealtime(); 167fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos } 168fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 169fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos private void unscheduleTimeTick() { 170ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roos if (!mTimeTicker.isScheduled()) { 171fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos return; 172fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos } 173e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos verifyLastTimeTick(); 174ef5cf2b4d11f841d3f836b9f536b2e7562ee118bAdrian Roos mTimeTicker.cancel(); 175fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos } 176fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 177e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos private void verifyLastTimeTick() { 178e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos long millisSinceLastTick = SystemClock.elapsedRealtime() - mLastTimeTickElapsed; 179e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos if (millisSinceLastTick > TIME_TICK_DEADLINE_MILLIS) { 180e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos String delay = Formatter.formatShortElapsedTime(mContext, millisSinceLastTick); 181e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos DozeLog.traceMissedTick(delay); 182e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos Log.e(DozeMachine.TAG, "Missed AOD time tick by " + delay); 183e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos } 184e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos } 185e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos 186fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos private long roundToNextMinute(long timeInMillis) { 187fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos Calendar calendar = GregorianCalendar.getInstance(); 188fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos calendar.setTimeInMillis(timeInMillis); 189fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos calendar.set(Calendar.MILLISECOND, 0); 190fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos calendar.set(Calendar.SECOND, 0); 191fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos calendar.add(Calendar.MINUTE, 1); 192fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 193fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos return calendar.getTimeInMillis(); 194fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos } 195fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 196fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos private void onTimeTick() { 197e4b564c856e84f0abe9e7d32cb2d3fd82deaafedAdrian Roos verifyLastTimeTick(); 198fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 199fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos mHost.dozeTimeTick(); 200fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 201fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos // Keep wakelock until a frame has been pushed. 202fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos mHandler.post(mWakeLock.wrap(() -> {})); 203fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos 204fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos scheduleTimeTick(); 205fe54aa00e22c3542b25d7476b44adc5548169688Adrian Roos } 20616cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin 20716cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin @VisibleForTesting 20816cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin KeyguardUpdateMonitorCallback getKeyguardCallback() { 20916cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin return mKeyguardVisibilityCallback; 21016cfe45dec96154d37b36364f67cedce16ca2484Lucas Dupin } 211ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos} 212