• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.hardware.display;
18 
19 import android.annotation.TestApi;
20 import android.content.Context;
21 import android.os.Build;
22 import android.os.SystemProperties;
23 import android.provider.Settings;
24 import android.text.TextUtils;
25 import android.util.ArrayMap;
26 import android.util.SparseArray;
27 
28 import com.android.internal.R;
29 import com.android.internal.util.ArrayUtils;
30 
31 import java.util.Map;
32 
33 /**
34  * AmbientDisplayConfiguration encapsulates reading access to the configuration of ambient display.
35  *
36  * @hide
37  */
38 @TestApi
39 public class AmbientDisplayConfiguration {
40     private static final String TAG = "AmbientDisplayConfig";
41     private final Context mContext;
42     private final boolean mAlwaysOnByDefault;
43     private final boolean mPickupGestureEnabledByDefault;
44 
45     /** Copied from android.provider.Settings.Secure since these keys are hidden. */
46     private static final String[] DOZE_SETTINGS = {
47             Settings.Secure.DOZE_ENABLED,
48             Settings.Secure.DOZE_ALWAYS_ON,
49             Settings.Secure.DOZE_PICK_UP_GESTURE,
50             Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
51             Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
52             Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
53             Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
54             Settings.Secure.DOZE_TAP_SCREEN_GESTURE
55     };
56 
57     /** Non-user configurable doze settings */
58     private static final String[] NON_USER_CONFIGURABLE_DOZE_SETTINGS = {
59             Settings.Secure.DOZE_QUICK_PICKUP_GESTURE
60     };
61 
62     final SparseArray<Map<String, String>> mUsersInitialValues = new SparseArray<>();
63 
64     /** @hide */
65     @TestApi
AmbientDisplayConfiguration(Context context)66     public AmbientDisplayConfiguration(Context context) {
67         mContext = context;
68         mAlwaysOnByDefault = mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnEnabled);
69         mPickupGestureEnabledByDefault =
70                 mContext.getResources().getBoolean(R.bool.config_dozePickupGestureEnabled);
71     }
72 
73     /** @hide */
enabled(int user)74     public boolean enabled(int user) {
75         return pulseOnNotificationEnabled(user)
76                 || pulseOnLongPressEnabled(user)
77                 || alwaysOnEnabled(user)
78                 || wakeLockScreenGestureEnabled(user)
79                 || wakeDisplayGestureEnabled(user)
80                 || pickupGestureEnabled(user)
81                 || tapGestureEnabled(user)
82                 || doubleTapGestureEnabled(user)
83                 || quickPickupSensorEnabled(user)
84                 || screenOffUdfpsEnabled(user);
85     }
86 
87     /** @hide */
pulseOnNotificationEnabled(int user)88     public boolean pulseOnNotificationEnabled(int user) {
89         return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user)
90                 && pulseOnNotificationAvailable();
91     }
92 
93     /** @hide */
pulseOnNotificationAvailable()94     public boolean pulseOnNotificationAvailable() {
95         return mContext.getResources().getBoolean(R.bool.config_pulseOnNotificationsAvailable)
96                 && ambientDisplayAvailable();
97     }
98 
99     /** @hide */
pickupGestureEnabled(int user)100     public boolean pickupGestureEnabled(int user) {
101         return boolSetting(Settings.Secure.DOZE_PICK_UP_GESTURE, user,
102                 mPickupGestureEnabledByDefault ? 1 : 0)
103                 && dozePickupSensorAvailable();
104     }
105 
106     /** @hide */
dozePickupSensorAvailable()107     public boolean dozePickupSensorAvailable() {
108         return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup);
109     }
110 
111     /** @hide */
tapGestureEnabled(int user)112     public boolean tapGestureEnabled(int user) {
113         return boolSettingDefaultOn(Settings.Secure.DOZE_TAP_SCREEN_GESTURE, user)
114                 && tapSensorAvailable();
115     }
116 
117     /** @hide */
tapSensorAvailable()118     public boolean tapSensorAvailable() {
119         for (String tapType : tapSensorTypeMapping()) {
120             if (!TextUtils.isEmpty(tapType)) {
121                 return true;
122             }
123         }
124         return false;
125     }
126 
127     /** @hide */
doubleTapGestureEnabled(int user)128     public boolean doubleTapGestureEnabled(int user) {
129         return boolSettingDefaultOn(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, user)
130                 && doubleTapSensorAvailable();
131     }
132 
133     /** @hide */
doubleTapSensorAvailable()134     public boolean doubleTapSensorAvailable() {
135         return !TextUtils.isEmpty(doubleTapSensorType());
136     }
137 
138     /** @hide */
quickPickupSensorEnabled(int user)139     public boolean quickPickupSensorEnabled(int user) {
140         return boolSettingDefaultOn(Settings.Secure.DOZE_QUICK_PICKUP_GESTURE, user)
141                 && !TextUtils.isEmpty(quickPickupSensorType())
142                 && pickupGestureEnabled(user)
143                 && !alwaysOnEnabled(user);
144     }
145 
146     /** @hide */
screenOffUdfpsEnabled(int user)147     public boolean screenOffUdfpsEnabled(int user) {
148         return !TextUtils.isEmpty(udfpsLongPressSensorType())
149             && boolSettingDefaultOff("screen_off_udfps_enabled", user);
150     }
151 
152     /** @hide */
wakeScreenGestureAvailable()153     public boolean wakeScreenGestureAvailable() {
154         return mContext.getResources()
155                 .getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable);
156     }
157 
158     /** @hide */
wakeLockScreenGestureEnabled(int user)159     public boolean wakeLockScreenGestureEnabled(int user) {
160         return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
161                 && wakeScreenGestureAvailable();
162     }
163 
164     /** @hide */
wakeDisplayGestureEnabled(int user)165     public boolean wakeDisplayGestureEnabled(int user) {
166         return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, user)
167                 && wakeScreenGestureAvailable();
168     }
169 
170     /** @hide */
getWakeLockScreenDebounce()171     public long getWakeLockScreenDebounce() {
172         return mContext.getResources().getInteger(R.integer.config_dozeWakeLockScreenDebounce);
173     }
174 
175     /** @hide */
doubleTapSensorType()176     public String doubleTapSensorType() {
177         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
178     }
179 
180     /** @hide
181      * May support multiple postures.
182      */
tapSensorTypeMapping()183     public String[] tapSensorTypeMapping() {
184         String[] postureMapping =
185                 mContext.getResources().getStringArray(R.array.config_dozeTapSensorPostureMapping);
186         if (ArrayUtils.isEmpty(postureMapping)) {
187             return new String[] {
188                     mContext.getResources().getString(R.string.config_dozeTapSensorType)
189             };
190         }
191         return postureMapping;
192     }
193 
194     /** @hide */
longPressSensorType()195     public String longPressSensorType() {
196         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
197     }
198 
199     /** @hide */
udfpsLongPressSensorType()200     public String udfpsLongPressSensorType() {
201         return mContext.getResources().getString(R.string.config_dozeUdfpsLongPressSensorType);
202     }
203 
204     /** @hide */
quickPickupSensorType()205     public String quickPickupSensorType() {
206         return mContext.getResources().getString(R.string.config_quickPickupSensorType);
207     }
208 
209     /** @hide */
pulseOnLongPressEnabled(int user)210     public boolean pulseOnLongPressEnabled(int user) {
211         return pulseOnLongPressAvailable() && boolSettingDefaultOff(
212                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
213     }
214 
pulseOnLongPressAvailable()215     private boolean pulseOnLongPressAvailable() {
216         return !TextUtils.isEmpty(longPressSensorType());
217     }
218 
219     /**
220      * Returns if Always-on-Display functionality is enabled on the display for a specified user.
221      *
222      * @hide
223      */
224     @TestApi
alwaysOnEnabled(int user)225     public boolean alwaysOnEnabled(int user) {
226         return boolSetting(Settings.Secure.DOZE_ALWAYS_ON, user, mAlwaysOnByDefault ? 1 : 0)
227                 && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
228     }
229 
230     /**
231      * Returns if Always-on-Display functionality is available on the display.
232      *
233      * @hide
234      */
235     @TestApi
alwaysOnAvailable()236     public boolean alwaysOnAvailable() {
237         return (alwaysOnDisplayDebuggingEnabled() || alwaysOnDisplayAvailable())
238                 && ambientDisplayAvailable();
239     }
240 
241     /**
242      * Returns if Always-on-Display functionality is available on the display for a specified user.
243      *
244      *  @hide
245      */
246     @TestApi
alwaysOnAvailableForUser(int user)247     public boolean alwaysOnAvailableForUser(int user) {
248         return alwaysOnAvailable() && !accessibilityInversionEnabled(user);
249     }
250 
251     /** @hide */
ambientDisplayComponent()252     public String ambientDisplayComponent() {
253         return mContext.getResources().getString(R.string.config_dozeComponent);
254     }
255 
256     /** @hide */
accessibilityInversionEnabled(int user)257     public boolean accessibilityInversionEnabled(int user) {
258         return boolSettingDefaultOff(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, user);
259     }
260 
261     /** @hide */
ambientDisplayAvailable()262     public boolean ambientDisplayAvailable() {
263         return !TextUtils.isEmpty(ambientDisplayComponent());
264     }
265 
266     /** @hide */
dozeSuppressed(int user)267     public boolean dozeSuppressed(int user) {
268         return boolSettingDefaultOff(Settings.Secure.SUPPRESS_DOZE, user);
269     }
270 
alwaysOnDisplayAvailable()271     private boolean alwaysOnDisplayAvailable() {
272         return mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnDisplayAvailable);
273     }
274 
alwaysOnDisplayDebuggingEnabled()275     private boolean alwaysOnDisplayDebuggingEnabled() {
276         return SystemProperties.getBoolean("debug.doze.aod", false) && Build.IS_DEBUGGABLE;
277     }
278 
boolSettingDefaultOn(String name, int user)279     private boolean boolSettingDefaultOn(String name, int user) {
280         return boolSetting(name, user, 1);
281     }
282 
boolSettingDefaultOff(String name, int user)283     private boolean boolSettingDefaultOff(String name, int user) {
284         return boolSetting(name, user, 0);
285     }
286 
boolSetting(String name, int user, int def)287     private boolean boolSetting(String name, int user, int def) {
288         return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, def, user) != 0;
289     }
290 
291     /** @hide */
292     @TestApi
disableDozeSettings(int userId)293     public void disableDozeSettings(int userId) {
294         disableDozeSettings(false /* shouldDisableNonUserConfigurable */, userId);
295     }
296 
297     /** @hide */
298     @TestApi
disableDozeSettings(boolean shouldDisableNonUserConfigurable, int userId)299     public void disableDozeSettings(boolean shouldDisableNonUserConfigurable, int userId) {
300         Map<String, String> initialValues = mUsersInitialValues.get(userId);
301         if (initialValues != null && !initialValues.isEmpty()) {
302             throw new IllegalStateException("Don't call #disableDozeSettings more than once,"
303                     + "without first calling #restoreDozeSettings");
304         }
305         initialValues = new ArrayMap<>();
306         for (String name : DOZE_SETTINGS) {
307             initialValues.put(name, getDozeSetting(name, userId));
308             putDozeSetting(name, "0", userId);
309         }
310         if (shouldDisableNonUserConfigurable) {
311             for (String name : NON_USER_CONFIGURABLE_DOZE_SETTINGS) {
312                 initialValues.put(name, getDozeSetting(name, userId));
313                 putDozeSetting(name, "0", userId);
314             }
315         }
316         mUsersInitialValues.put(userId, initialValues);
317     }
318 
319     /** @hide */
320     @TestApi
restoreDozeSettings(int userId)321     public void restoreDozeSettings(int userId) {
322         final Map<String, String> initialValues = mUsersInitialValues.get(userId);
323         if (initialValues != null && !initialValues.isEmpty()) {
324             for (String name : DOZE_SETTINGS) {
325                 putDozeSetting(name, initialValues.get(name), userId);
326             }
327             mUsersInitialValues.remove(userId);
328         }
329     }
330 
getDozeSetting(String name, int userId)331     private String getDozeSetting(String name, int userId) {
332         return Settings.Secure.getStringForUser(mContext.getContentResolver(), name, userId);
333     }
334 
putDozeSetting(String name, String value, int userId)335     private void putDozeSetting(String name, String value, int userId) {
336         Settings.Secure.putStringForUser(mContext.getContentResolver(), name, value, userId);
337     }
338 }
339