blob: 6d85fb37e3744751ef423b4d967e052ea45f9ba5 [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;
20import android.os.SystemProperties;
Adrian Roosb7e4e102016-10-14 13:03:45 -070021import android.os.UserHandle;
Adrian Roosebea7a72016-10-26 12:51:26 -070022import android.provider.Settings;
John Spurlockd06aa572014-09-10 10:40:49 -040023import android.text.TextUtils;
John Spurlockd06aa572014-09-10 10:40:49 -040024import android.util.MathUtils;
Adrian Roos5753f052016-07-13 10:30:37 -070025import android.util.SparseBooleanArray;
John Spurlockd06aa572014-09-10 10:40:49 -040026
Adrian Roos0261fb22017-03-07 20:20:35 +000027import com.android.internal.hardware.AmbientDisplayConfiguration;
John Spurlockd06aa572014-09-10 10:40:49 -040028import com.android.systemui.R;
Lucas Dupin82aa1632017-12-13 00:13:57 -080029import com.android.systemui.doze.AlwaysOnDisplayPolicy;
John Spurlockd06aa572014-09-10 10:40:49 -040030
31import java.io.PrintWriter;
John Spurlockd06aa572014-09-10 10:40:49 -040032
33public class DozeParameters {
Selim Cinekbb998c92015-09-22 10:05:29 +020034 private static final int MAX_DURATION = 60 * 1000;
Adrian Roos7a1654e2017-02-14 14:06:29 +010035 public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
John Spurlockd06aa572014-09-10 10:40:49 -040036
37 private final Context mContext;
Adrian Roos0261fb22017-03-07 20:20:35 +000038 private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
John Spurlockd06aa572014-09-10 10:40:49 -040039
Adrian Roos5753f052016-07-13 10:30:37 -070040 private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
Lucas Dupin82aa1632017-12-13 00:13:57 -080041 private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
Adrian Roos5753f052016-07-13 10:30:37 -070042
John Spurlockd06aa572014-09-10 10:40:49 -040043 public DozeParameters(Context context) {
44 mContext = context;
Adrian Roos0261fb22017-03-07 20:20:35 +000045 mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
Lucas Dupin82aa1632017-12-13 00:13:57 -080046 mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(context);
John Spurlockd06aa572014-09-10 10:40:49 -040047 }
48
49 public void dump(PrintWriter pw) {
50 pw.println(" DozeParameters:");
John Spurlock190d0262014-09-14 15:39:13 -040051 pw.print(" getDisplayStateSupported(): "); pw.println(getDisplayStateSupported());
Lucas Dupin9e3fa102017-11-08 17:16:55 -080052 pw.print(" getPulseDuration(): "); pw.println(getPulseDuration());
53 pw.print(" getPulseInDuration(): "); pw.println(getPulseInDuration());
John Spurlockd06aa572014-09-10 10:40:49 -040054 pw.print(" getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
55 pw.print(" getPulseOutDuration(): "); pw.println(getPulseOutDuration());
John Spurlock190d0262014-09-14 15:39:13 -040056 pw.print(" getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
57 pw.print(" getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion());
John Spurlock190d0262014-09-14 15:39:13 -040058 pw.print(" getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
John Spurlock686e4d52014-11-20 21:48:09 -050059 pw.print(" getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
John Spurlock50a8ea62014-09-16 09:12:03 -040060 pw.print(" getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
Adrian Roos5753f052016-07-13 10:30:37 -070061 pw.print(" getPickupSubtypePerformsProxCheck(): ");pw.println(
62 dumpPickupSubtypePerformsProxCheck());
63 }
64
65 private String dumpPickupSubtypePerformsProxCheck() {
66 // Refresh sPickupSubtypePerformsProxMatcher
67 getPickupSubtypePerformsProxCheck(0);
68
69 if (sPickupSubtypePerformsProxMatcher == null) {
70 return "fallback: " + mContext.getResources().getBoolean(
71 R.bool.doze_pickup_performs_proximity_check);
72 } else {
73 return "spec: " + sPickupSubtypePerformsProxMatcher.mSpec;
74 }
John Spurlock190d0262014-09-14 15:39:13 -040075 }
76
77 public boolean getDisplayStateSupported() {
78 return getBoolean("doze.display.supported", R.bool.doze_display_state_supported);
John Spurlockd06aa572014-09-10 10:40:49 -040079 }
80
Adrian Roosa1e6b312017-03-28 16:20:34 -070081 public boolean getDozeSuspendDisplayStateSupported() {
82 return mContext.getResources().getBoolean(R.bool.doze_suspend_display_state_supported);
83 }
84
Lucas Dupin9e3fa102017-11-08 17:16:55 -080085 public int getPulseDuration() {
86 return getPulseInDuration() + getPulseVisibleDuration() + getPulseOutDuration();
John Spurlockd06aa572014-09-10 10:40:49 -040087 }
88
Lucas Dupin7517b5d2017-08-22 12:51:25 -070089 public float getScreenBrightnessDoze() {
90 return mContext.getResources().getInteger(
91 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
92 }
93
Lucas Dupin9e3fa102017-11-08 17:16:55 -080094 public int getPulseInDuration() {
95 return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
John Spurlockd06aa572014-09-10 10:40:49 -040096 }
97
98 public int getPulseVisibleDuration() {
99 return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible);
100 }
101
102 public int getPulseOutDuration() {
103 return getInt("doze.pulse.duration.out", R.integer.doze_pulse_duration_out);
104 }
105
John Spurlock190d0262014-09-14 15:39:13 -0400106 public boolean getPulseOnSigMotion() {
107 return getBoolean("doze.pulse.sigmotion", R.bool.doze_pulse_on_significant_motion);
John Spurlockd06aa572014-09-10 10:40:49 -0400108 }
109
John Spurlock190d0262014-09-14 15:39:13 -0400110 public boolean getVibrateOnSigMotion() {
111 return SystemProperties.getBoolean("doze.vibrate.sigmotion", false);
112 }
113
John Spurlock190d0262014-09-14 15:39:13 -0400114 public boolean getVibrateOnPickup() {
115 return SystemProperties.getBoolean("doze.vibrate.pickup", false);
116 }
117
John Spurlock686e4d52014-11-20 21:48:09 -0500118 public boolean getProxCheckBeforePulse() {
119 return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
120 }
121
John Spurlock50a8ea62014-09-16 09:12:03 -0400122 public int getPickupVibrationThreshold() {
123 return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
124 }
125
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700126 /**
Lucas Dupin82aa1632017-12-13 00:13:57 -0800127 * For how long a wallpaper can be visible in AoD before it fades aways.
128 * @return duration in millis.
129 */
130 public long getWallpaperAodDuration() {
131 return mAlwaysOnPolicy.wallpaperVisibilityDuration;
132 }
133
134 /**
135 * How long it takes for the wallpaper fade away (Animation duration.)
136 * @return duration in millis.
137 */
138 public long getWallpaperFadeOutDuration() {
139 return mAlwaysOnPolicy.wallpaperFadeOutDuration;
140 }
141
142 /**
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700143 * Checks if always on is available and enabled for the current user.
144 * @return {@code true} if enabled and available.
145 */
Adrian Roosebea7a72016-10-26 12:51:26 -0700146 public boolean getAlwaysOn() {
Adrian Roos0261fb22017-03-07 20:20:35 +0000147 return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
Adrian Roosebea7a72016-10-26 12:51:26 -0700148 }
149
Lucas Dupin43d0d732017-11-16 11:23:49 -0800150 /**
151 * Some screens need to be completely black before changing the display power mode,
152 * unexpected behavior might happen if this parameter isn't respected.
153 *
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700154 * @return {@code true} if screen needs to be completely black before a power transition.
Lucas Dupin43d0d732017-11-16 11:23:49 -0800155 */
156 public boolean getDisplayNeedsBlanking() {
157 return mContext.getResources().getBoolean(
158 com.android.internal.R.bool.config_displayBlanksAfterDoze);
159 }
160
161 /**
162 * Whether we can implement our own screen off animation or if we need
163 * to rely on DisplayPowerManager to dim the display.
164 *
Lucas Dupin7517b5d2017-08-22 12:51:25 -0700165 * @return {@code true} if SystemUI can control the screen off animation.
Lucas Dupin43d0d732017-11-16 11:23:49 -0800166 */
167 public boolean getCanControlScreenOffAnimation() {
168 return !mContext.getResources().getBoolean(
169 com.android.internal.R.bool.config_dozeAfterScreenOff);
170 }
171
John Spurlock190d0262014-09-14 15:39:13 -0400172 private boolean getBoolean(String propName, int resId) {
173 return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
John Spurlockd06aa572014-09-10 10:40:49 -0400174 }
175
176 private int getInt(String propName, int resId) {
177 int value = SystemProperties.getInt(propName, mContext.getResources().getInteger(resId));
178 return MathUtils.constrain(value, 0, MAX_DURATION);
179 }
180
181 private String getString(String propName, int resId) {
182 return SystemProperties.get(propName, mContext.getString(resId));
183 }
184
Adrian Roos5753f052016-07-13 10:30:37 -0700185 public boolean getPickupSubtypePerformsProxCheck(int subType) {
186 String spec = getString("doze.pickup.proxcheck",
187 R.string.doze_pickup_subtype_performs_proximity_check);
188
189 if (TextUtils.isEmpty(spec)) {
190 // Fall back to non-subtype based property.
191 return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
192 }
193
194 if (sPickupSubtypePerformsProxMatcher == null
195 || !TextUtils.equals(spec, sPickupSubtypePerformsProxMatcher.mSpec)) {
196 sPickupSubtypePerformsProxMatcher = new IntInOutMatcher(spec);
197 }
198
199 return sPickupSubtypePerformsProxMatcher.isIn(subType);
200 }
201
Adrian Roos67cca742017-04-13 16:52:51 -0700202 public int getPulseVisibleDurationExtended() {
203 return 2 * getPulseVisibleDuration();
204 }
205
Adrian Roos44198f52017-06-02 12:50:38 -0700206 public boolean doubleTapReportsTouchCoordinates() {
207 return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
208 }
209
Adrian Roos5753f052016-07-13 10:30:37 -0700210
211 /**
212 * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
213 * listed, will not match numbers that are listed with a ! prefix, and will match / not match
214 * unlisted numbers depending on whether * or !* is present.
215 *
216 * * -> match any numbers that are not explicitly listed
217 * !* -> don't match any numbers that are not explicitly listed
218 * 2 -> match 2
219 * !3 -> don't match 3
220 *
221 * It is illegal to specify:
222 * - an empty spec
223 * - a spec containing that are empty, or a lone !
224 * - a spec for anything other than numbers or *
225 * - multiple terms for the same number / multiple *s
226 */
227 public static class IntInOutMatcher {
228 private static final String WILDCARD = "*";
229 private static final char OUT_PREFIX = '!';
230
231 private final SparseBooleanArray mIsIn;
232 private final boolean mDefaultIsIn;
233 final String mSpec;
234
235 public IntInOutMatcher(String spec) {
236 if (TextUtils.isEmpty(spec)) {
237 throw new IllegalArgumentException("Spec must not be empty");
238 }
239
240 boolean defaultIsIn = false;
241 boolean foundWildcard = false;
242
243 mSpec = spec;
244 mIsIn = new SparseBooleanArray();
245
246 for (String itemPrefixed : spec.split(",", -1)) {
247 if (itemPrefixed.length() == 0) {
248 throw new IllegalArgumentException(
249 "Illegal spec, must not have zero-length items: `" + spec + "`");
250 }
251 boolean isIn = itemPrefixed.charAt(0) != OUT_PREFIX;
252 String item = isIn ? itemPrefixed : itemPrefixed.substring(1);
253
254 if (itemPrefixed.length() == 0) {
255 throw new IllegalArgumentException(
256 "Illegal spec, must not have zero-length items: `" + spec + "`");
257 }
258
259 if (WILDCARD.equals(item)) {
260 if (foundWildcard) {
261 throw new IllegalArgumentException("Illegal spec, `" + WILDCARD +
262 "` must not appear multiple times in `" + spec + "`");
263 }
264 defaultIsIn = isIn;
265 foundWildcard = true;
266 } else {
267 int key = Integer.parseInt(item);
268 if (mIsIn.indexOfKey(key) >= 0) {
269 throw new IllegalArgumentException("Illegal spec, `" + key +
270 "` must not appear multiple times in `" + spec + "`");
271 }
272 mIsIn.put(key, isIn);
273 }
274 }
275
276 if (!foundWildcard) {
277 throw new IllegalArgumentException("Illegal spec, must specify either * or !*");
278 }
279
280 mDefaultIsIn = defaultIsIn;
281 }
282
283 public boolean isIn(int value) {
284 return (mIsIn.get(value, mDefaultIsIn));
285 }
286 }
John Spurlockd06aa572014-09-10 10:40:49 -0400287}