blob: 3869e77294e7403350ca485ac5fd7cf0c50d2228 [file] [log] [blame]
Adrian Roosff2c4562016-11-03 12:13:36 -07001/*
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
17package com.android.systemui.doze;
18
Lucas Dupinbb83b892019-07-19 11:45:16 -070019import static com.android.systemui.doze.DozeMachine.State.DOZE;
Lucas Dupin4df92c32018-01-08 10:21:52 -080020import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
21
Adrian Roosfe54aa02016-11-07 14:14:25 -080022import android.app.AlarmManager;
Adrian Roosff2c4562016-11-03 12:13:36 -070023import android.content.Context;
Adrian Roosfe54aa02016-11-07 14:14:25 -080024import android.os.Handler;
25import android.os.SystemClock;
Adrian Roose4b564c2017-04-14 14:48:05 -070026import android.text.format.Formatter;
27import android.util.Log;
Adrian Roosfe54aa02016-11-07 14:14:25 -080028
Lucas Dupin16cfe452018-02-08 13:14:50 -080029import com.android.internal.annotations.VisibleForTesting;
30import com.android.keyguard.KeyguardUpdateMonitor;
31import com.android.keyguard.KeyguardUpdateMonitorCallback;
Lucas Dupin43d0d732017-11-16 11:23:49 -080032import com.android.systemui.statusbar.phone.DozeParameters;
Adrian Roosef5cf2b2017-06-28 15:46:03 +020033import com.android.systemui.util.AlarmTimeout;
Adrian Roosc1b50322017-02-27 21:07:58 +010034import com.android.systemui.util.wakelock.WakeLock;
35
Adrian Roosfe54aa02016-11-07 14:14:25 -080036import java.util.Calendar;
Adrian Roosff2c4562016-11-03 12:13:36 -070037
38/**
39 * The policy controlling doze.
40 */
41public class DozeUi implements DozeMachine.Part {
42
Adrian Roose4b564c2017-04-14 14:48:05 -070043 private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
Adrian Roosff2c4562016-11-03 12:13:36 -070044 private final Context mContext;
45 private final DozeHost mHost;
Adrian Roosfe54aa02016-11-07 14:14:25 -080046 private final Handler mHandler;
Adrian Roosc1b50322017-02-27 21:07:58 +010047 private final WakeLock mWakeLock;
Adrian Roosfe54aa02016-11-07 14:14:25 -080048 private final DozeMachine mMachine;
Adrian Roosef5cf2b2017-06-28 15:46:03 +020049 private final AlarmTimeout mTimeTicker;
Lucas Dupin16cfe452018-02-08 13:14:50 -080050 private final boolean mCanAnimateTransition;
51 private final DozeParameters mDozeParameters;
52
53 private boolean mKeyguardShowing;
54 private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
55 new KeyguardUpdateMonitorCallback() {
56
57 @Override
58 public void onKeyguardVisibilityChanged(boolean showing) {
59 mKeyguardShowing = showing;
60 updateAnimateScreenOff();
61 }
62 };
Adrian Roosff2c4562016-11-03 12:13:36 -070063
Adrian Roose4b564c2017-04-14 14:48:05 -070064 private long mLastTimeTickElapsed = 0;
Adrian Roosfe54aa02016-11-07 14:14:25 -080065
66 public DozeUi(Context context, AlarmManager alarmManager, DozeMachine machine,
Lucas Dupin43d0d732017-11-16 11:23:49 -080067 WakeLock wakeLock, DozeHost host, Handler handler,
Lucas Dupin16cfe452018-02-08 13:14:50 -080068 DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor) {
Adrian Roosff2c4562016-11-03 12:13:36 -070069 mContext = context;
70 mMachine = machine;
71 mWakeLock = wakeLock;
72 mHost = host;
Adrian Roosfe54aa02016-11-07 14:14:25 -080073 mHandler = handler;
Lucas Dupin16cfe452018-02-08 13:14:50 -080074 mCanAnimateTransition = !params.getDisplayNeedsBlanking();
75 mDozeParameters = params;
Adrian Roosef5cf2b2017-06-28 15:46:03 +020076 mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
Lucas Dupin16cfe452018-02-08 13:14:50 -080077 keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
78 }
79
80 /**
81 * Decide if we're taking over the screen-off animation
82 * when the device was configured to skip doze after screen off.
83 */
84 private void updateAnimateScreenOff() {
85 if (mCanAnimateTransition) {
Lucas Dupin6edeb182019-09-25 13:39:21 -070086 final boolean controlScreenOff = mDozeParameters.getAlwaysOn() && mKeyguardShowing
87 && !mHost.isPowerSaveActive();
Lucas Dupin16cfe452018-02-08 13:14:50 -080088 mDozeParameters.setControlScreenOffAnimation(controlScreenOff);
89 mHost.setAnimateScreenOff(controlScreenOff);
90 }
Adrian Roosff2c4562016-11-03 12:13:36 -070091 }
92
93 private void pulseWhileDozing(int reason) {
94 mHost.pulseWhileDozing(
95 new DozeHost.PulseCallback() {
96 @Override
97 public void onPulseStarted() {
Lucas Dupin09f85272019-03-08 15:04:06 -080098 try {
Lucas Dupin5f00fa52019-03-27 22:46:53 -070099 mMachine.requestState(
100 reason == DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN
101 ? DozeMachine.State.DOZE_PULSING_BRIGHT
102 : DozeMachine.State.DOZE_PULSING);
Lucas Dupin09f85272019-03-08 15:04:06 -0800103 } catch (IllegalStateException e) {
104 // It's possible that the pulse was asynchronously cancelled while
105 // we were waiting for it to start (under stress conditions.)
106 // In those cases we should just ignore it. b/127657926
107 }
Adrian Roosff2c4562016-11-03 12:13:36 -0700108 }
109
110 @Override
111 public void onPulseFinished() {
112 mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
113 }
114 }, reason);
115 }
116
117 @Override
118 public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
119 switch (newState) {
Adrian Roosfe54aa02016-11-07 14:14:25 -0800120 case DOZE_AOD:
Lucas Dupinbb83b892019-07-19 11:45:16 -0700121 if (oldState == DOZE_AOD_PAUSED || oldState == DOZE) {
Lucas Dupinf9583c42018-04-05 22:20:44 -0700122 // Whenever turning on the display, it's necessary to push a new frame.
123 // The display buffers will be empty and need to be filled.
Lucas Dupin4df92c32018-01-08 10:21:52 -0800124 mHost.dozeTimeTick();
Lucas Dupinf9583c42018-04-05 22:20:44 -0700125 // The first frame may arrive when the display isn't ready yet.
Lucas Dupina11298b2018-06-26 15:09:08 -0700126 mHandler.postDelayed(mWakeLock.wrap(mHost::dozeTimeTick), 500);
Lucas Dupin4df92c32018-01-08 10:21:52 -0800127 }
128 scheduleTimeTick();
129 break;
Adrian Roos6023ccb2017-06-28 16:22:02 +0200130 case DOZE_AOD_PAUSING:
Adrian Roosfe54aa02016-11-07 14:14:25 -0800131 scheduleTimeTick();
132 break;
133 case DOZE:
Adrian Roos67cca742017-04-13 16:52:51 -0700134 case DOZE_AOD_PAUSED:
Lucas Dupin34306c32019-07-16 11:56:53 -0700135 mHost.prepareForGentleWakeUp();
Adrian Roosfe54aa02016-11-07 14:14:25 -0800136 unscheduleTimeTick();
137 break;
Adrian Roosff2c4562016-11-03 12:13:36 -0700138 case DOZE_REQUEST_PULSE:
TYM Tsai25c05492019-01-04 16:59:07 +0800139 scheduleTimeTick();
Adrian Roosd7b9d102017-04-28 15:42:58 -0700140 pulseWhileDozing(mMachine.getPulseReason());
Adrian Roosff2c4562016-11-03 12:13:36 -0700141 break;
142 case INITIALIZED:
143 mHost.startDozing();
144 break;
145 case FINISH:
146 mHost.stopDozing();
Adrian Roosfe54aa02016-11-07 14:14:25 -0800147 unscheduleTimeTick();
Adrian Roosff2c4562016-11-03 12:13:36 -0700148 break;
149 }
Adrian Roos013fc4c2017-08-02 19:32:28 +0200150 updateAnimateWakeup(newState);
Adrian Roos28f90c72017-05-08 17:24:26 -0700151 }
152
Adrian Roos013fc4c2017-08-02 19:32:28 +0200153 private void updateAnimateWakeup(DozeMachine.State state) {
Adrian Roos28f90c72017-05-08 17:24:26 -0700154 switch (state) {
Adrian Roos28f90c72017-05-08 17:24:26 -0700155 case DOZE_REQUEST_PULSE:
156 case DOZE_PULSING:
Lucas Dupin5f00fa52019-03-27 22:46:53 -0700157 case DOZE_PULSING_BRIGHT:
Adrian Roos28f90c72017-05-08 17:24:26 -0700158 case DOZE_PULSE_DONE:
Adrian Roos013fc4c2017-08-02 19:32:28 +0200159 mHost.setAnimateWakeup(true);
160 break;
161 case FINISH:
162 // Keep current state.
163 break;
Adrian Roos28f90c72017-05-08 17:24:26 -0700164 default:
Lucas Dupin16cfe452018-02-08 13:14:50 -0800165 mHost.setAnimateWakeup(mCanAnimateTransition && mDozeParameters.getAlwaysOn());
Adrian Roos013fc4c2017-08-02 19:32:28 +0200166 break;
Adrian Roos28f90c72017-05-08 17:24:26 -0700167 }
Adrian Roosff2c4562016-11-03 12:13:36 -0700168 }
Adrian Roosfe54aa02016-11-07 14:14:25 -0800169
170 private void scheduleTimeTick() {
Adrian Roosef5cf2b2017-06-28 15:46:03 +0200171 if (mTimeTicker.isScheduled()) {
Adrian Roosfe54aa02016-11-07 14:14:25 -0800172 return;
173 }
174
Lucas Dupin69d4b572018-09-06 10:36:08 -0700175 long time = System.currentTimeMillis();
176 long delta = roundToNextMinute(time) - System.currentTimeMillis();
177 boolean scheduled = mTimeTicker.schedule(delta, AlarmTimeout.MODE_IGNORE_IF_SCHEDULED);
178 if (scheduled) {
179 DozeLog.traceTimeTickScheduled(time, time + delta);
180 }
Adrian Roose4b564c2017-04-14 14:48:05 -0700181 mLastTimeTickElapsed = SystemClock.elapsedRealtime();
Adrian Roosfe54aa02016-11-07 14:14:25 -0800182 }
183
184 private void unscheduleTimeTick() {
Adrian Roosef5cf2b2017-06-28 15:46:03 +0200185 if (!mTimeTicker.isScheduled()) {
Adrian Roosfe54aa02016-11-07 14:14:25 -0800186 return;
187 }
Adrian Roose4b564c2017-04-14 14:48:05 -0700188 verifyLastTimeTick();
Adrian Roosef5cf2b2017-06-28 15:46:03 +0200189 mTimeTicker.cancel();
Adrian Roosfe54aa02016-11-07 14:14:25 -0800190 }
191
Adrian Roose4b564c2017-04-14 14:48:05 -0700192 private void verifyLastTimeTick() {
193 long millisSinceLastTick = SystemClock.elapsedRealtime() - mLastTimeTickElapsed;
194 if (millisSinceLastTick > TIME_TICK_DEADLINE_MILLIS) {
195 String delay = Formatter.formatShortElapsedTime(mContext, millisSinceLastTick);
196 DozeLog.traceMissedTick(delay);
197 Log.e(DozeMachine.TAG, "Missed AOD time tick by " + delay);
198 }
199 }
200
Adrian Roosfe54aa02016-11-07 14:14:25 -0800201 private long roundToNextMinute(long timeInMillis) {
Neil Fuller9c610f72018-07-04 16:41:14 +0100202 Calendar calendar = Calendar.getInstance();
Adrian Roosfe54aa02016-11-07 14:14:25 -0800203 calendar.setTimeInMillis(timeInMillis);
204 calendar.set(Calendar.MILLISECOND, 0);
205 calendar.set(Calendar.SECOND, 0);
206 calendar.add(Calendar.MINUTE, 1);
207
208 return calendar.getTimeInMillis();
209 }
210
211 private void onTimeTick() {
Adrian Roose4b564c2017-04-14 14:48:05 -0700212 verifyLastTimeTick();
Adrian Roosfe54aa02016-11-07 14:14:25 -0800213
214 mHost.dozeTimeTick();
215
216 // Keep wakelock until a frame has been pushed.
217 mHandler.post(mWakeLock.wrap(() -> {}));
218
Adrian Roosfe54aa02016-11-07 14:14:25 -0800219 scheduleTimeTick();
220 }
Lucas Dupin16cfe452018-02-08 13:14:50 -0800221
222 @VisibleForTesting
223 KeyguardUpdateMonitorCallback getKeyguardCallback() {
224 return mKeyguardVisibilityCallback;
225 }
Adrian Roosff2c4562016-11-03 12:13:36 -0700226}