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