blob: 89bd1b6b79f8ab0298c59e57b8262fb8b93baa16 [file] [log] [blame]
John Spurlockd06aa572014-09-10 10:40:49 -04001/*
2 * Copyright (C) 2014 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.statusbar.phone;
18
19import android.content.Context;
Issei Suzukica19e6e2019-02-26 12:39:11 +010020import android.hardware.display.AmbientDisplayConfiguration;
Lucas Dupin16cfe452018-02-08 13:14:50 -080021import android.os.PowerManager;
John Spurlockd06aa572014-09-10 10:40:49 -040022import android.os.SystemProperties;
Adrian Roosb7e4e102016-10-14 13:03:45 -070023import android.os.UserHandle;
Adrian Roosebea7a72016-10-26 12:51:26 -070024import android.provider.Settings;
John Spurlockd06aa572014-09-10 10:40:49 -040025import android.text.TextUtils;
John Spurlockd06aa572014-09-10 10:40:49 -040026import android.util.MathUtils;
Adrian Roos5753f052016-07-13 10:30:37 -070027import android.util.SparseBooleanArray;
John Spurlockd06aa572014-09-10 10:40:49 -040028
Lucas Dupin16cfe452018-02-08 13:14:50 -080029import com.android.internal.annotations.VisibleForTesting;
Lucas Dupindff8cdf2018-01-09 13:01:01 -080030import com.android.systemui.Dependency;
John Spurlockd06aa572014-09-10 10:40:49 -040031import com.android.systemui.R;
Lucas Dupin82aa1632017-12-13 00:13:57 -080032import com.android.systemui.doze.AlwaysOnDisplayPolicy;
Lucas Dupincbe05962018-04-26 16:44:05 -070033import com.android.systemui.doze.DozeScreenState;
Lucas Dupindff8cdf2018-01-09 13:01:01 -080034import com.android.systemui.tuner.TunerService;
John Spurlockd06aa572014-09-10 10:40:49 -040035
36import java.io.PrintWriter;
John Spurlockd06aa572014-09-10 10:40:49 -040037
Beverly1488f692019-06-07 09:32:46 -040038/**
39 * Retrieve doze information
40 */
41public class DozeParameters implements TunerService.Tunable,
42 com.android.systemui.plugins.statusbar.DozeParameters {
Selim Cinekbb998c92015-09-22 10:05:29 +020043 private static final int MAX_DURATION = 60 * 1000;
Adrian Roos7a1654e2017-02-14 14:06:29 +010044 public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
Selim Cinek0dd5a6b2018-05-15 13:15:42 -070045 public static final boolean FORCE_NO_BLANKING =
46 SystemProperties.getBoolean("debug.force_no_blanking", false);
Lucas Dupinee63c372018-08-03 11:58:24 -070047 public static final boolean FORCE_BLANKING =
48 SystemProperties.getBoolean("debug.force_blanking", false);
John Spurlockd06aa572014-09-10 10:40:49 -040049
Lucas Dupin16cfe452018-02-08 13:14:50 -080050 private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
51 private static DozeParameters sInstance;
52
John Spurlockd06aa572014-09-10 10:40:49 -040053 private final Context mContext;
Adrian Roos0261fb22017-03-07 20:20:35 +000054 private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
Lucas Dupin16cfe452018-02-08 13:14:50 -080055 private final PowerManager mPowerManager;
John Spurlockd06aa572014-09-10 10:40:49 -040056
Lucas Dupin82aa1632017-12-13 00:13:57 -080057 private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
Adrian Roos5753f052016-07-13 10:30:37 -070058
Lucas Dupindff8cdf2018-01-09 13:01:01 -080059 private boolean mDozeAlwaysOn;
Lucas Dupin16cfe452018-02-08 13:14:50 -080060 private boolean mControlScreenOffAnimation;
Lucas Dupindff8cdf2018-01-09 13:01:01 -080061
Lucas Dupin16cfe452018-02-08 13:14:50 -080062 public static DozeParameters getInstance(Context context) {
63 if (sInstance == null) {
64 sInstance = new DozeParameters(context);
65 }
66 return sInstance;
67 }
68
69 @VisibleForTesting
70 protected DozeParameters(Context context) {
Adrian Roos2f5a3852018-04-23 17:48:08 +020071 mContext = context.getApplicationContext();
Adrian Roos0261fb22017-03-07 20:20:35 +000072 mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
Adrian Roos2f5a3852018-04-23 17:48:08 +020073 mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(mContext);
Lucas Dupindff8cdf2018-01-09 13:01:01 -080074
Lucas Dupin16cfe452018-02-08 13:14:50 -080075 mControlScreenOffAnimation = !getDisplayNeedsBlanking();
76 mPowerManager = mContext.getSystemService(PowerManager.class);
77 mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
78
Lucas Dupindff8cdf2018-01-09 13:01:01 -080079 Dependency.get(TunerService.class).addTunable(this, Settings.Secure.DOZE_ALWAYS_ON,
80 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
John Spurlockd06aa572014-09-10 10:40:49 -040081 }
82
83 public void dump(PrintWriter pw) {
84 pw.println(" DozeParameters:");
John Spurlock190d0262014-09-14 15:39:13 -040085 pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080086 pw.print(" getPulseDuration(): "); pw.println(getPulseDuration());
87 pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration());
John Spurlockd06aa572014-09-10 10:40:49 -040088 pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
89 pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
John Spurlock190d0262014-09-14 15:39:13 -040090 pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
91 pw.print(" getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion());
John Spurlock190d0262014-09-14 15:39:13 -040092 pw.print(" getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
John Spurlock686e4d52014-11-20 21:48:09 -050093 pw.print(" getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
John Spurlock50a8ea62014-09-16 09:12:03 -040094 pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
Adrian Roos5753f052016-07-13 10:30:37 -070095 pw.print(" getPickupSubtypePerformsProxCheck(): ");pw.println(
96 dumpPickupSubtypePerformsProxCheck());
97 }
98
99 private String dumpPickupSubtypePerformsProxCheck() {
100 // Refresh sPickupSubtypePerformsProxMatcher
101 getPickupSubtypePerformsProxCheck(0);
102
103 if (sPickupSubtypePerformsProxMatcher == null) {
104 return "fallback: " + mContext.getResources().getBoolean(
105 R.bool.doze_pickup_performs_proximity_check);
106 } else {
107 return "spec: " + sPickupSubtypePerformsProxMatcher.mSpec;
108 }
John Spurlock190d0262014-09-14 15:39:13 -0400109 }
110
111 public boolean getDisplayStateSupported() {
112 return getBoolean("doze.display.supported", R.bool.doze_display_state_supported);
John Spurlockd06aa572014-09-10 10:40:49 -0400113 }
114
Adrian Roosa1e6b312017-03-28 16:20:34 -0700115 public boolean getDozeSuspendDisplayStateSupported() {
116 return mContext.getResources().getBoolean(R.bool.doze_suspend_display_state_supported);
117 }
118
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800119 public int getPulseDuration() {
120 return getPulseInDuration() + getPulseVisibleDuration() + getPulseOutDuration();
John Spurlockd06aa572014-09-10 10:40:49 -0400121 }
122
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700123 public float getScreenBrightnessDoze() {
124 return mContext.getResources().getInteger(
125 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
126 }
127
Lucas Dupin9e3fa102017-11-08 17:16:55 -0800128 public int getPulseInDuration() {
129 return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
John Spurlockd06aa572014-09-10 10:40:49 -0400130 }
131
132 public int getPulseVisibleDuration() {
133 return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible);
134 }
135
136 public int getPulseOutDuration() {
137 return getInt("doze.pulse.duration.out", R.integer.doze_pulse_duration_out);
138 }
139
John Spurlock190d0262014-09-14 15:39:13 -0400140 public boolean getPulseOnSigMotion() {
141 return getBoolean("doze.pulse.sigmotion", R.bool.doze_pulse_on_significant_motion);
John Spurlockd06aa572014-09-10 10:40:49 -0400142 }
143
John Spurlock190d0262014-09-14 15:39:13 -0400144 public boolean getVibrateOnSigMotion() {
145 return SystemProperties.getBoolean("doze.vibrate.sigmotion", false);
146 }
147
John Spurlock190d0262014-09-14 15:39:13 -0400148 public boolean getVibrateOnPickup() {
149 return SystemProperties.getBoolean("doze.vibrate.pickup", false);
150 }
151
John Spurlock686e4d52014-11-20 21:48:09 -0500152 public boolean getProxCheckBeforePulse() {
153 return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
154 }
155
John Spurlock50a8ea62014-09-16 09:12:03 -0400156 public int getPickupVibrationThreshold() {
157 return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
158 }
159
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700160 /**
Lucas Dupin82aa1632017-12-13 00:13:57 -0800161 * For how long a wallpaper can be visible in AoD before it fades aways.
162 * @return duration in millis.
163 */
164 public long getWallpaperAodDuration() {
Lucas Dupin00be88f2019-01-03 17:50:52 -0800165 if (shouldControlScreenOff()) {
Lucas Dupinde64ee02018-12-21 14:45:12 -0800166 return DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY;
167 }
168 return mAlwaysOnPolicy.wallpaperVisibilityDuration;
Lucas Dupin82aa1632017-12-13 00:13:57 -0800169 }
170
171 /**
172 * How long it takes for the wallpaper fade away (Animation duration.)
173 * @return duration in millis.
174 */
175 public long getWallpaperFadeOutDuration() {
176 return mAlwaysOnPolicy.wallpaperFadeOutDuration;
177 }
178
179 /**
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700180 * Checks if always on is available and enabled for the current user.
181 * @return {@code true} if enabled and available.
182 */
Adrian Roosebea7a72016-10-26 12:51:26 -0700183 public boolean getAlwaysOn() {
Lucas Dupindff8cdf2018-01-09 13:01:01 -0800184 return mDozeAlwaysOn;
Adrian Roosebea7a72016-10-26 12:51:26 -0700185 }
186
Lucas Dupin43d0d732017-11-16 11:23:49 -0800187 /**
188 * Some screens need to be completely black before changing the display power mode,
189 * unexpected behavior might happen if this parameter isn't respected.
190 *
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700191 * @return {@code true} if screen needs to be completely black before a power transition.
Lucas Dupin43d0d732017-11-16 11:23:49 -0800192 */
193 public boolean getDisplayNeedsBlanking() {
Lucas Dupinee63c372018-08-03 11:58:24 -0700194 return FORCE_BLANKING || !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
Lucas Dupin43d0d732017-11-16 11:23:49 -0800195 com.android.internal.R.bool.config_displayBlanksAfterDoze);
196 }
197
Lucas Dupin16cfe452018-02-08 13:14:50 -0800198 public boolean shouldControlScreenOff() {
199 return mControlScreenOffAnimation;
200 }
201
202 public void setControlScreenOffAnimation(boolean controlScreenOffAnimation) {
203 if (mControlScreenOffAnimation == controlScreenOffAnimation) {
204 return;
205 }
206 mControlScreenOffAnimation = controlScreenOffAnimation;
207 getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation);
208 }
209
210 @VisibleForTesting
211 protected PowerManager getPowerManager() {
212 return mPowerManager;
Lucas Dupin43d0d732017-11-16 11:23:49 -0800213 }
214
John Spurlock190d0262014-09-14 15:39:13 -0400215 private boolean getBoolean(String propName, int resId) {
216 return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
John Spurlockd06aa572014-09-10 10:40:49 -0400217 }
218
219 private int getInt(String propName, int resId) {
220 int value = SystemProperties.getInt(propName, mContext.getResources().getInteger(resId));
221 return MathUtils.constrain(value, 0, MAX_DURATION);
222 }
223
224 private String getString(String propName, int resId) {
225 return SystemProperties.get(propName, mContext.getString(resId));
226 }
227
Adrian Roos5753f052016-07-13 10:30:37 -0700228 public boolean getPickupSubtypePerformsProxCheck(int subType) {
229 String spec = getString("doze.pickup.proxcheck",
230 R.string.doze_pickup_subtype_performs_proximity_check);
231
232 if (TextUtils.isEmpty(spec)) {
233 // Fall back to non-subtype based property.
234 return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
235 }
236
237 if (sPickupSubtypePerformsProxMatcher == null
238 || !TextUtils.equals(spec, sPickupSubtypePerformsProxMatcher.mSpec)) {
239 sPickupSubtypePerformsProxMatcher = new IntInOutMatcher(spec);
240 }
241
242 return sPickupSubtypePerformsProxMatcher.isIn(subType);
243 }
244
Adrian Roos67cca742017-04-13 16:52:51 -0700245 public int getPulseVisibleDurationExtended() {
246 return 2 * getPulseVisibleDuration();
247 }
248
Adrian Roos44198f52017-06-02 12:50:38 -0700249 public boolean doubleTapReportsTouchCoordinates() {
250 return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
251 }
252
Lucas Dupindff8cdf2018-01-09 13:01:01 -0800253 @Override
254 public void onTuningChanged(String key, String newValue) {
255 mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
256 }
Adrian Roos5753f052016-07-13 10:30:37 -0700257
Adrian Roos2f5a3852018-04-23 17:48:08 +0200258 public AlwaysOnDisplayPolicy getPolicy() {
259 return mAlwaysOnPolicy;
260 }
261
Adrian Roos5753f052016-07-13 10:30:37 -0700262 /**
263 * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
264 * listed, will not match numbers that are listed with a ! prefix, and will match / not match
265 * unlisted numbers depending on whether * or !* is present.
266 *
267 * * -> match any numbers that are not explicitly listed
268 * !* -> don't match any numbers that are not explicitly listed
269 * 2 -> match 2
270 * !3 -> don't match 3
271 *
272 * It is illegal to specify:
273 * - an empty spec
274 * - a spec containing that are empty, or a lone !
275 * - a spec for anything other than numbers or *
276 * - multiple terms for the same number / multiple *s
277 */
278 public static class IntInOutMatcher {
279 private static final String WILDCARD = "*";
280 private static final char OUT_PREFIX = '!';
281
282 private final SparseBooleanArray mIsIn;
283 private final boolean mDefaultIsIn;
284 final String mSpec;
285
286 public IntInOutMatcher(String spec) {
287 if (TextUtils.isEmpty(spec)) {
288 throw new IllegalArgumentException("Spec must not be empty");
289 }
290
291 boolean defaultIsIn = false;
292 boolean foundWildcard = false;
293
294 mSpec = spec;
295 mIsIn = new SparseBooleanArray();
296
297 for (String itemPrefixed : spec.split(",", -1)) {
298 if (itemPrefixed.length() == 0) {
299 throw new IllegalArgumentException(
300 "Illegal spec, must not have zero-length items: `" + spec + "`");
301 }
302 boolean isIn = itemPrefixed.charAt(0) != OUT_PREFIX;
303 String item = isIn ? itemPrefixed : itemPrefixed.substring(1);
304
305 if (itemPrefixed.length() == 0) {
306 throw new IllegalArgumentException(
307 "Illegal spec, must not have zero-length items: `" + spec + "`");
308 }
309
310 if (WILDCARD.equals(item)) {
311 if (foundWildcard) {
312 throw new IllegalArgumentException("Illegal spec, `" + WILDCARD +
313 "` must not appear multiple times in `" + spec + "`");
314 }
315 defaultIsIn = isIn;
316 foundWildcard = true;
317 } else {
318 int key = Integer.parseInt(item);
319 if (mIsIn.indexOfKey(key) >= 0) {
320 throw new IllegalArgumentException("Illegal spec, `" + key +
321 "` must not appear multiple times in `" + spec + "`");
322 }
323 mIsIn.put(key, isIn);
324 }
325 }
326
327 if (!foundWildcard) {
328 throw new IllegalArgumentException("Illegal spec, must specify either * or !*");
329 }
330
331 mDefaultIsIn = defaultIsIn;
332 }
333
334 public boolean isIn(int value) {
335 return (mIsIn.get(value, mDefaultIsIn));
336 }
337 }
John Spurlockd06aa572014-09-10 10:40:49 -0400338}