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