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 
26 import com.android.internal.R;
27 import com.android.internal.util.ArrayUtils;
28 
29 /**
30  * AmbientDisplayConfiguration encapsulates reading access to the configuration of ambient display.
31  *
32  * {@hide}
33  */
34 @TestApi
35 public class AmbientDisplayConfiguration {
36     private static final String TAG = "AmbientDisplayConfig";
37     private final Context mContext;
38     private final boolean mAlwaysOnByDefault;
39 
40     /** {@hide} */
41     @TestApi
AmbientDisplayConfiguration(Context context)42     public AmbientDisplayConfiguration(Context context) {
43         mContext = context;
44         mAlwaysOnByDefault = mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnEnabled);
45     }
46 
47     /** {@hide} */
enabled(int user)48     public boolean enabled(int user) {
49         return pulseOnNotificationEnabled(user)
50                 || pulseOnLongPressEnabled(user)
51                 || alwaysOnEnabled(user)
52                 || wakeLockScreenGestureEnabled(user)
53                 || wakeDisplayGestureEnabled(user)
54                 || pickupGestureEnabled(user)
55                 || tapGestureEnabled(user)
56                 || doubleTapGestureEnabled(user)
57                 || quickPickupSensorEnabled(user)
58                 || screenOffUdfpsEnabled(user);
59     }
60 
61     /** {@hide} */
pulseOnNotificationEnabled(int user)62     public boolean pulseOnNotificationEnabled(int user) {
63         return boolSettingDefaultOn(Settings.Secure.DOZE_ENABLED, user)
64                 && pulseOnNotificationAvailable();
65     }
66 
67     /** {@hide} */
pulseOnNotificationAvailable()68     public boolean pulseOnNotificationAvailable() {
69         return ambientDisplayAvailable();
70     }
71 
72     /** {@hide} */
pickupGestureEnabled(int user)73     public boolean pickupGestureEnabled(int user) {
74         return boolSettingDefaultOn(Settings.Secure.DOZE_PICK_UP_GESTURE, user)
75                 && dozePickupSensorAvailable();
76     }
77 
78     /** {@hide} */
dozePickupSensorAvailable()79     public boolean dozePickupSensorAvailable() {
80         return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup);
81     }
82 
83     /** {@hide} */
tapGestureEnabled(int user)84     public boolean tapGestureEnabled(int user) {
85         return boolSettingDefaultOn(Settings.Secure.DOZE_TAP_SCREEN_GESTURE, user)
86                 && tapSensorAvailable();
87     }
88 
89     /** {@hide} */
tapSensorAvailable()90     public boolean tapSensorAvailable() {
91         for (String tapType : tapSensorTypeMapping()) {
92             if (!TextUtils.isEmpty(tapType)) {
93                 return true;
94             }
95         }
96         return false;
97     }
98 
99     /** {@hide} */
doubleTapGestureEnabled(int user)100     public boolean doubleTapGestureEnabled(int user) {
101         return boolSettingDefaultOn(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, user)
102                 && doubleTapSensorAvailable();
103     }
104 
105     /** {@hide} */
doubleTapSensorAvailable()106     public boolean doubleTapSensorAvailable() {
107         return !TextUtils.isEmpty(doubleTapSensorType());
108     }
109 
110     /** {@hide} */
quickPickupSensorEnabled(int user)111     public boolean quickPickupSensorEnabled(int user) {
112         return boolSettingDefaultOn(Settings.Secure.DOZE_QUICK_PICKUP_GESTURE, user)
113                 && !TextUtils.isEmpty(quickPickupSensorType())
114                 && pickupGestureEnabled(user)
115                 && !alwaysOnEnabled(user);
116     }
117 
118     /** {@hide} */
screenOffUdfpsEnabled(int user)119     public boolean screenOffUdfpsEnabled(int user) {
120         return !TextUtils.isEmpty(udfpsLongPressSensorType())
121             && boolSettingDefaultOff("screen_off_udfps_enabled", user);
122     }
123 
124     /** {@hide} */
wakeScreenGestureAvailable()125     public boolean wakeScreenGestureAvailable() {
126         return mContext.getResources()
127                 .getBoolean(R.bool.config_dozeWakeLockScreenSensorAvailable);
128     }
129 
130     /** {@hide} */
wakeLockScreenGestureEnabled(int user)131     public boolean wakeLockScreenGestureEnabled(int user) {
132         return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
133                 && wakeScreenGestureAvailable();
134     }
135 
136     /** {@hide} */
wakeDisplayGestureEnabled(int user)137     public boolean wakeDisplayGestureEnabled(int user) {
138         return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, user)
139                 && wakeScreenGestureAvailable();
140     }
141 
142     /** {@hide} */
getWakeLockScreenDebounce()143     public long getWakeLockScreenDebounce() {
144         return mContext.getResources().getInteger(R.integer.config_dozeWakeLockScreenDebounce);
145     }
146 
147     /** {@hide} */
doubleTapSensorType()148     public String doubleTapSensorType() {
149         return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType);
150     }
151 
152     /** {@hide}
153      * May support multiple postures.
154      */
tapSensorTypeMapping()155     public String[] tapSensorTypeMapping() {
156         String[] postureMapping =
157                 mContext.getResources().getStringArray(R.array.config_dozeTapSensorPostureMapping);
158         if (ArrayUtils.isEmpty(postureMapping)) {
159             return new String[] {
160                     mContext.getResources().getString(R.string.config_dozeTapSensorType)
161             };
162         }
163         return postureMapping;
164     }
165 
166     /** {@hide} */
longPressSensorType()167     public String longPressSensorType() {
168         return mContext.getResources().getString(R.string.config_dozeLongPressSensorType);
169     }
170 
171     /** {@hide} */
udfpsLongPressSensorType()172     public String udfpsLongPressSensorType() {
173         return mContext.getResources().getString(R.string.config_dozeUdfpsLongPressSensorType);
174     }
175 
176     /** {@hide} */
quickPickupSensorType()177     public String quickPickupSensorType() {
178         return mContext.getResources().getString(R.string.config_quickPickupSensorType);
179     }
180 
181     /** {@hide} */
pulseOnLongPressEnabled(int user)182     public boolean pulseOnLongPressEnabled(int user) {
183         return pulseOnLongPressAvailable() && boolSettingDefaultOff(
184                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, user);
185     }
186 
pulseOnLongPressAvailable()187     private boolean pulseOnLongPressAvailable() {
188         return !TextUtils.isEmpty(longPressSensorType());
189     }
190 
191     /**
192      * Returns if Always-on-Display functionality is enabled on the display for a specified user.
193      *
194      * {@hide}
195      */
196     @TestApi
alwaysOnEnabled(int user)197     public boolean alwaysOnEnabled(int user) {
198         return boolSetting(Settings.Secure.DOZE_ALWAYS_ON, user, mAlwaysOnByDefault ? 1 : 0)
199                 && alwaysOnAvailable() && !accessibilityInversionEnabled(user);
200     }
201 
202     /**
203      * Returns if Always-on-Display functionality is available on the display.
204      *
205      * {@hide}
206      */
207     @TestApi
alwaysOnAvailable()208     public boolean alwaysOnAvailable() {
209         return (alwaysOnDisplayDebuggingEnabled() || alwaysOnDisplayAvailable())
210                 && ambientDisplayAvailable();
211     }
212 
213     /**
214      * Returns if Always-on-Display functionality is available on the display for a specified user.
215      *
216      *  {@hide}
217      */
218     @TestApi
alwaysOnAvailableForUser(int user)219     public boolean alwaysOnAvailableForUser(int user) {
220         return alwaysOnAvailable() && !accessibilityInversionEnabled(user);
221     }
222 
223     /** {@hide} */
ambientDisplayComponent()224     public String ambientDisplayComponent() {
225         return mContext.getResources().getString(R.string.config_dozeComponent);
226     }
227 
228     /** {@hide} */
accessibilityInversionEnabled(int user)229     public boolean accessibilityInversionEnabled(int user) {
230         return boolSettingDefaultOff(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, user);
231     }
232 
233     /** {@hide} */
ambientDisplayAvailable()234     public boolean ambientDisplayAvailable() {
235         return !TextUtils.isEmpty(ambientDisplayComponent());
236     }
237 
238     /** {@hide} */
dozeSuppressed(int user)239     public boolean dozeSuppressed(int user) {
240         return boolSettingDefaultOff(Settings.Secure.SUPPRESS_DOZE, user);
241     }
242 
alwaysOnDisplayAvailable()243     private boolean alwaysOnDisplayAvailable() {
244         return mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnDisplayAvailable);
245     }
246 
alwaysOnDisplayDebuggingEnabled()247     private boolean alwaysOnDisplayDebuggingEnabled() {
248         return SystemProperties.getBoolean("debug.doze.aod", false) && Build.IS_DEBUGGABLE;
249     }
250 
boolSettingDefaultOn(String name, int user)251     private boolean boolSettingDefaultOn(String name, int user) {
252         return boolSetting(name, user, 1);
253     }
254 
boolSettingDefaultOff(String name, int user)255     private boolean boolSettingDefaultOff(String name, int user) {
256         return boolSetting(name, user, 0);
257     }
258 
boolSetting(String name, int user, int def)259     private boolean boolSetting(String name, int user, int def) {
260         return Settings.Secure.getIntForUser(mContext.getContentResolver(), name, def, user) != 0;
261     }
262 }
263