• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.input;
18 
19 import android.Manifest;
20 import android.annotation.FloatRange;
21 import android.annotation.NonNull;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SuppressLint;
24 import android.annotation.TestApi;
25 import android.content.Context;
26 import android.os.UserHandle;
27 import android.provider.Settings;
28 import android.sysprop.InputProperties;
29 
30 /**
31  * InputSettings encapsulates reading and writing settings related to input
32  *
33  * @hide
34  */
35 @TestApi
36 public class InputSettings {
37     /**
38      * Pointer Speed: The minimum (slowest) pointer speed (-7).
39      * @hide
40      */
41     public static final int MIN_POINTER_SPEED = -7;
42 
43     /**
44      * Pointer Speed: The maximum (fastest) pointer speed (7).
45      * @hide
46      */
47     public static final int MAX_POINTER_SPEED = 7;
48 
49     /**
50      * Pointer Speed: The default pointer speed (0).
51      * @hide
52      */
53     public static final int DEFAULT_POINTER_SPEED = 0;
54 
55     /**
56      * The maximum allowed obscuring opacity by UID to propagate touches (0 <= x <= 1).
57      * @hide
58      */
59     public static final float DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH = .8f;
60 
61 
InputSettings()62     private InputSettings() {
63     }
64 
65     /**
66      * Gets the mouse pointer speed.
67      * <p>
68      * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
69      * speed set by {@link InputManager#tryPointerSpeed}.
70      * </p>
71      *
72      * @param context The application context.
73      * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
74      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
75      *
76      * @hide
77      */
78     @SuppressLint("NonUserGetterCalled")
getPointerSpeed(Context context)79     public static int getPointerSpeed(Context context) {
80         return Settings.System.getInt(context.getContentResolver(),
81                 Settings.System.POINTER_SPEED, DEFAULT_POINTER_SPEED);
82     }
83 
84     /**
85      * Sets the mouse pointer speed.
86      * <p>
87      * Requires {@link android.Manifest.permission#WRITE_SETTINGS}.
88      * </p>
89      *
90      * @param context The application context.
91      * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
92      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
93      *
94      * @hide
95      */
96     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setPointerSpeed(Context context, int speed)97     public static void setPointerSpeed(Context context, int speed) {
98         if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
99             throw new IllegalArgumentException("speed out of range");
100         }
101 
102         Settings.System.putInt(context.getContentResolver(),
103                 Settings.System.POINTER_SPEED, speed);
104     }
105 
106     /**
107      * Returns the maximum allowed obscuring opacity per UID to propagate touches.
108      *
109      * <p>For certain window types (e.g. {@link LayoutParams#TYPE_APPLICATION_OVERLAY}),
110      * the decision of honoring {@link LayoutParams#FLAG_NOT_TOUCHABLE} or not depends on
111      * the combined obscuring opacity of the windows above the touch-consuming window, per
112      * UID. Check documentation of {@link LayoutParams#FLAG_NOT_TOUCHABLE} for more details.
113      *
114      * <p>The value returned is between 0 (inclusive) and 1 (inclusive).
115      *
116      * @see LayoutParams#FLAG_NOT_TOUCHABLE
117      *
118      * @hide
119      */
120     @FloatRange(from = 0, to = 1)
getMaximumObscuringOpacityForTouch(Context context)121     public static float getMaximumObscuringOpacityForTouch(Context context) {
122         return Settings.Global.getFloat(context.getContentResolver(),
123                 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
124                 DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
125     }
126 
127     /**
128      * Sets the maximum allowed obscuring opacity by UID to propagate touches.
129      *
130      * <p>For certain window types (e.g. SAWs), the decision of honoring {@link LayoutParams
131      * #FLAG_NOT_TOUCHABLE} or not depends on the combined obscuring opacity of the windows
132      * above the touch-consuming window.
133      *
134      * <p>For a certain UID:
135      * <ul>
136      *     <li>If it's the same as the UID of the touch-consuming window, allow it to propagate
137      *     the touch.
138      *     <li>Otherwise take all its windows of eligible window types above the touch-consuming
139      *     window, compute their combined obscuring opacity considering that {@code
140      *     opacity(A, B) = 1 - (1 - opacity(A))*(1 - opacity(B))}. If the computed value is
141      *     less than or equal to this setting and there are no other windows preventing the
142      *     touch, allow the UID to propagate the touch.
143      * </ul>
144      *
145      * <p>This value should be between 0 (inclusive) and 1 (inclusive).
146      *
147      * @see #getMaximumObscuringOpacityForTouch(Context)
148      *
149      * @hide
150      */
151     @TestApi
152     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
setMaximumObscuringOpacityForTouch( @onNull Context context, @FloatRange(from = 0, to = 1) float opacity)153     public static void setMaximumObscuringOpacityForTouch(
154             @NonNull Context context,
155             @FloatRange(from = 0, to = 1) float opacity) {
156         if (opacity < 0 || opacity > 1) {
157             throw new IllegalArgumentException(
158                     "Maximum obscuring opacity for touch should be >= 0 and <= 1");
159         }
160         Settings.Global.putFloat(context.getContentResolver(),
161                 Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, opacity);
162     }
163 
164     /**
165      * Whether stylus has ever been used on device (false by default).
166      * @hide
167      */
isStylusEverUsed(@onNull Context context)168     public static boolean isStylusEverUsed(@NonNull Context context) {
169         return Settings.Global.getInt(context.getContentResolver(),
170                         Settings.Global.STYLUS_EVER_USED, 0) == 1;
171     }
172 
173     /**
174      * Set whether stylus has ever been used on device.
175      * Should only ever be set to true once after stylus first usage.
176      * @hide
177      */
178     @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
setStylusEverUsed(@onNull Context context, boolean stylusEverUsed)179     public static void setStylusEverUsed(@NonNull Context context, boolean stylusEverUsed) {
180         Settings.Global.putInt(context.getContentResolver(),
181                 Settings.Global.STYLUS_EVER_USED, stylusEverUsed ? 1 : 0);
182     }
183 
184 
185     /**
186      * Gets the touchpad pointer speed.
187      *
188      * The returned value only applies to gesture-compatible touchpads.
189      *
190      * @param context The application context.
191      * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
192      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
193      *
194      * @hide
195      */
getTouchpadPointerSpeed(@onNull Context context)196     public static int getTouchpadPointerSpeed(@NonNull Context context) {
197         return Settings.System.getIntForUser(context.getContentResolver(),
198                 Settings.System.TOUCHPAD_POINTER_SPEED, DEFAULT_POINTER_SPEED,
199                 UserHandle.USER_CURRENT);
200     }
201 
202     /**
203      * Sets the touchpad pointer speed, and saves it in the settings.
204      *
205      * The new speed will only apply to gesture-compatible touchpads.
206      *
207      * @param context The application context.
208      * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
209      * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
210      *
211      * @hide
212      */
213     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadPointerSpeed(@onNull Context context, int speed)214     public static void setTouchpadPointerSpeed(@NonNull Context context, int speed) {
215         if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
216             throw new IllegalArgumentException("speed out of range");
217         }
218 
219         Settings.System.putIntForUser(context.getContentResolver(),
220                 Settings.System.TOUCHPAD_POINTER_SPEED, speed, UserHandle.USER_CURRENT);
221     }
222 
223     /**
224      * Returns true if moving two fingers upwards on the touchpad should
225      * scroll down, which is known as natural scrolling.
226      *
227      * The returned value only applies to gesture-compatible touchpads.
228      *
229      * @param context The application context.
230      * @return Whether the touchpad should use natural scrolling.
231      *
232      * @hide
233      */
useTouchpadNaturalScrolling(@onNull Context context)234     public static boolean useTouchpadNaturalScrolling(@NonNull Context context) {
235         return Settings.System.getIntForUser(context.getContentResolver(),
236                 Settings.System.TOUCHPAD_NATURAL_SCROLLING, 1, UserHandle.USER_CURRENT) == 1;
237     }
238 
239     /**
240      * Sets the natural scroll behavior for the touchpad.
241      *
242      * If natural scrolling is enabled, moving two fingers upwards on the
243      * touchpad will scroll down.
244      *
245      * @param context The application context.
246      * @param enabled Will enable natural scroll if true, disable it if false
247      *
248      * @hide
249      */
250     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadNaturalScrolling(@onNull Context context, boolean enabled)251     public static void setTouchpadNaturalScrolling(@NonNull Context context, boolean enabled) {
252         Settings.System.putIntForUser(context.getContentResolver(),
253                 Settings.System.TOUCHPAD_NATURAL_SCROLLING, enabled ? 1 : 0,
254                 UserHandle.USER_CURRENT);
255     }
256 
257     /**
258      * Returns true if the touchpad should use tap to click.
259      *
260      * The returned value only applies to gesture-compatible touchpads.
261      *
262      * @param context The application context.
263      * @return Whether the touchpad should use tap to click.
264      *
265      * @hide
266      */
useTouchpadTapToClick(@onNull Context context)267     public static boolean useTouchpadTapToClick(@NonNull Context context) {
268         return Settings.System.getIntForUser(context.getContentResolver(),
269                 Settings.System.TOUCHPAD_TAP_TO_CLICK, 1, UserHandle.USER_CURRENT) == 1;
270     }
271 
272     /**
273      * Sets the tap to click behavior for the touchpad.
274      *
275      * The new behavior is only applied to gesture-compatible touchpads.
276      *
277      * @param context The application context.
278      * @param enabled Will enable tap to click if true, disable it if false
279      *
280      * @hide
281      */
282     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadTapToClick(@onNull Context context, boolean enabled)283     public static void setTouchpadTapToClick(@NonNull Context context, boolean enabled) {
284         Settings.System.putIntForUser(context.getContentResolver(),
285                 Settings.System.TOUCHPAD_TAP_TO_CLICK, enabled ? 1 : 0,
286                 UserHandle.USER_CURRENT);
287     }
288 
289     /**
290      * Returns true if the touchpad should use the right click zone.
291      *
292      * The returned value only applies to gesture-compatible touchpads.
293      *
294      * @param context The application context.
295      * @return Whether the touchpad should use the right click zone.
296      *
297      * @hide
298      */
useTouchpadRightClickZone(@onNull Context context)299     public static boolean useTouchpadRightClickZone(@NonNull Context context) {
300         return Settings.System.getIntForUser(context.getContentResolver(),
301                 Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, 0, UserHandle.USER_CURRENT) == 1;
302     }
303 
304     /**
305      * Sets the right click zone behavior for the touchpad.
306      *
307      * The new behavior is only applied to gesture-compatible touchpads.
308      *
309      * @param context The application context.
310      * @param enabled Will enable the right click zone if true, disable it if false
311      *
312      * @hide
313      */
314     @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
setTouchpadRightClickZone(@onNull Context context, boolean enabled)315     public static void setTouchpadRightClickZone(@NonNull Context context, boolean enabled) {
316         Settings.System.putIntForUser(context.getContentResolver(),
317                 Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, enabled ? 1 : 0,
318                 UserHandle.USER_CURRENT);
319     }
320 
321     /**
322      * Whether a pointer icon will be shown over the location of a
323      * stylus pointer.
324      * @hide
325      */
isStylusPointerIconEnabled(@onNull Context context)326     public static boolean isStylusPointerIconEnabled(@NonNull Context context) {
327         return context.getResources()
328                        .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon)
329                || InputProperties.force_enable_stylus_pointer_icon().orElse(false);
330     }
331 }
332