Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd4ddfa4 authored by Josep del Río's avatar Josep del Río Committed by Android (Google) Code Review
Browse files

Merge "Add InputSettings for input related settings"

parents e91e866e 7ec4828b
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -1497,10 +1497,13 @@ package android.hardware.input {
    method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void removeKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
    method public void removeUniqueIdAssociation(@NonNull String);
    method @RequiresPermission(android.Manifest.permission.SET_KEYBOARD_LAYOUT) public void setCurrentKeyboardLayoutForInputDevice(@NonNull android.hardware.input.InputDeviceIdentifier, @NonNull String);
    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setMaximumObscuringOpacityForTouch(@FloatRange(from=0, to=1) float);
    field public static final long BLOCK_UNTRUSTED_TOUCHES = 158002302L; // 0x96aec7eL
  }

  public class InputSettings {
    method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public static void setMaximumObscuringOpacityForTouch(@NonNull android.content.Context, @FloatRange(from=0, to=1) float);
  }

}

package android.hardware.lights {
+5 −321
Original line number Diff line number Diff line
@@ -51,11 +51,9 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.provider.Settings;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -214,30 +212,6 @@ public final class InputManager {
    public static final String META_DATA_KEYBOARD_LAYOUTS =
            "android.hardware.input.metadata.KEYBOARD_LAYOUTS";

    /**
     * Pointer Speed: The minimum (slowest) pointer speed (-7).
     * @hide
     */
    public static final int MIN_POINTER_SPEED = -7;

    /**
     * Pointer Speed: The maximum (fastest) pointer speed (7).
     * @hide
     */
    public static final int MAX_POINTER_SPEED = 7;

    /**
     * Pointer Speed: The default pointer speed (0).
     * @hide
     */
    public static final int DEFAULT_POINTER_SPEED = 0;

    /**
     * The maximum allowed obscuring opacity by UID to propagate touches (0 <= x <= 1).
     * @hide
     */
    public static final float DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH = .8f;

    /**
     * Prevent touches from being consumed by apps if these touches passed through a non-trusted
     * window from a different UID and are considered unsafe.
@@ -1134,59 +1108,19 @@ public final class InputManager {
        }
    }

    /**
     * Gets the mouse pointer speed.
     * <p>
     * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
     * speed set by {@link #tryPointerSpeed}.
     * </p>
     *
     * @param context The application context.
     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
     *
     * @hide
     */
    public int getPointerSpeed(Context context) {
        return Settings.System.getInt(context.getContentResolver(),
                Settings.System.POINTER_SPEED, DEFAULT_POINTER_SPEED);
    }

    /**
     * Sets the mouse pointer speed.
     * <p>
     * Requires {@link android.Manifest.permission#WRITE_SETTINGS}.
     * </p>
     *
     * @param context The application context.
     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
    public void setPointerSpeed(Context context, int speed) {
        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
            throw new IllegalArgumentException("speed out of range");
        }

        Settings.System.putInt(context.getContentResolver(),
                Settings.System.POINTER_SPEED, speed);
    }

    /**
     * Changes the mouse pointer speed temporarily, but does not save the setting.
     * <p>
     * Requires {@link android.Manifest.permission#SET_POINTER_SPEED}.
     * </p>
     *
     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
     * @param speed The pointer speed as a value between {@link InputSettings#MIN_POINTER_SPEED} and
     * {@link InputSettings#MAX_POINTER_SPEED}, or the default value {@link InputSettings#DEFAULT_POINTER_SPEED}.
     *
     * @hide
     */
    public void tryPointerSpeed(int speed) {
        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
        if (speed < InputSettings.MIN_POINTER_SPEED || speed > InputSettings.MAX_POINTER_SPEED) {
            throw new IllegalArgumentException("speed out of range");
        }

@@ -1211,44 +1145,8 @@ public final class InputManager {
     */
    @FloatRange(from = 0, to = 1)
    public float getMaximumObscuringOpacityForTouch() {
        return Settings.Global.getFloat(getContext().getContentResolver(),
                Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
                DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
    }

    /**
     * Sets the maximum allowed obscuring opacity by UID to propagate touches.
     *
     * <p>For certain window types (eg. SAWs), the decision of honoring {@link LayoutParams
     * #FLAG_NOT_TOUCHABLE} or not depends on the combined obscuring opacity of the windows
     * above the touch-consuming window.
     *
     * <p>For a certain UID:
     * <ul>
     *     <li>If it's the same as the UID of the touch-consuming window, allow it to propagate
     *     the touch.
     *     <li>Otherwise take all its windows of eligible window types above the touch-consuming
     *     window, compute their combined obscuring opacity considering that {@code
     *     opacity(A, B) = 1 - (1 - opacity(A))*(1 - opacity(B))}. If the computed value is
     *     lesser than or equal to this setting and there are no other windows preventing the
     *     touch, allow the UID to propagate the touch.
     * </ul>
     *
     * <p>This value should be between 0 (inclusive) and 1 (inclusive).
     *
     * @see #getMaximumObscuringOpacityForTouch()
     *
     * @hide
     */
    @TestApi
    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
    public void setMaximumObscuringOpacityForTouch(@FloatRange(from = 0, to = 1) float opacity) {
        if (opacity < 0 || opacity > 1) {
            throw new IllegalArgumentException(
                    "Maximum obscuring opacity for touch should be >= 0 and <= 1");
        }
        Settings.Global.putFloat(getContext().getContentResolver(),
                Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, opacity);
        Context context = ActivityThread.currentApplication();
        return InputSettings.getMaximumObscuringOpacityForTouch(context);
    }

    /**
@@ -2144,26 +2042,6 @@ public final class InputManager {
        }
    }

    /**
     * Whether stylus has ever been used on device (false by default).
     * @hide
     */
    public boolean isStylusEverUsed(@NonNull Context context) {
        return Settings.Global.getInt(context.getContentResolver(),
                        Settings.Global.STYLUS_EVER_USED, 0) == 1;
    }

    /**
     * Set whether stylus has ever been used on device.
     * Should only ever be set to true once after stylus first usage.
     * @hide
     */
    @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
    public void setStylusEverUsed(@NonNull Context context, boolean stylusEverUsed) {
        Settings.Global.putInt(context.getContentResolver(),
                Settings.Global.STYLUS_EVER_USED, stylusEverUsed ? 1 : 0);
    }

    /**
     * Whether there is a gesture-compatible touchpad connected to the device.
     * @hide
@@ -2173,200 +2051,6 @@ public final class InputManager {
        return true;
    }

    /**
     * Gets the touchpad pointer speed.
     *
     * The returned value only applies to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
     *
     * @hide
     */
    public int getTouchpadPointerSpeed(@NonNull Context context) {
        return Settings.System.getIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_POINTER_SPEED, DEFAULT_POINTER_SPEED,
                UserHandle.USER_CURRENT);
    }

    /**
     * Sets the touchpad pointer speed, and saves it in the settings.
     *
     * The new speed will only apply to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
    public void setTouchpadPointerSpeed(@NonNull Context context, int speed) {
        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
            throw new IllegalArgumentException("speed out of range");
        }

        Settings.System.putIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_POINTER_SPEED, speed, UserHandle.USER_CURRENT);
    }

    /**
     * Returns true if the touchpad should use pointer acceleration.
     *
     * The returned value only applies to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @return Whether the touchpad should use pointer acceleration.
     *
     * @hide
     */
    public boolean useTouchpadPointerAcceleration(@NonNull Context context) {
        // TODO: obtain the actual behavior from the settings
        return true;
    }

    /**
     * Sets the pointer acceleration behavior for the touchpad.
     *
     * The new behavior is only applied to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @param enabled Will enable pointer acceleration if true, disable it if false
     *
     * @hide
     */
    public void setTouchpadPointerAcceleration(@NonNull Context context, boolean enabled) {
        // TODO: set the right setting
    }

    /**
     * Returns true if moving two fingers upwards on the touchpad should
     * scroll down, which is known as natural scrolling.
     *
     * The returned value only applies to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @return Whether the touchpad should use natural scrolling.
     *
     * @hide
     */
    public boolean useTouchpadNaturalScrolling(@NonNull Context context) {
        return Settings.System.getIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_NATURAL_SCROLLING, 0, UserHandle.USER_CURRENT) == 1;
    }

    /**
     * Sets the natural scroll behavior for the touchpad.
     *
     * If natural scrolling is enabled, moving two fingers upwards on the
     * touchpad will scroll down.
     *
     * @param context The application context.
     * @param enabled Will enable natural scroll if true, disable it if false
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
    public void setTouchpadNaturalScrolling(@NonNull Context context, boolean enabled) {
        Settings.System.putIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_NATURAL_SCROLLING, enabled ? 1 : 0,
                UserHandle.USER_CURRENT);
    }

    /**
     * Returns true if the touchpad should use tap to click.
     *
     * The returned value only applies to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @return Whether the touchpad should use tap to click.
     *
     * @hide
     */
    public boolean useTouchpadTapToClick(@NonNull Context context) {
        return Settings.System.getIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_TAP_TO_CLICK, 0, UserHandle.USER_CURRENT) == 1;
    }

    /**
     * Sets the tap to click behavior for the touchpad.
     *
     * The new behavior is only applied to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @param enabled Will enable tap to click if true, disable it if false
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
    public void setTouchpadTapToClick(@NonNull Context context, boolean enabled) {
        Settings.System.putIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_TAP_TO_CLICK, enabled ? 1 : 0,
                UserHandle.USER_CURRENT);
    }

    /**
     * Returns true if the touchpad should use tap dragging.
     *
     * The returned value only applies to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @return Whether the touchpad should use tap dragging.
     *
     * @hide
     */
    public boolean useTouchpadTapDragging(@NonNull Context context) {
        // TODO: obtain the actual behavior from the settings
        return true;
    }

    /**
     * Sets the tap dragging behavior for the touchpad.
     *
     * The new behavior is only applied to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @param enabled Will enable tap dragging if true, disable it if false
     *
     * @hide
     */
    public void setTouchpadTapDragging(@NonNull Context context, boolean enabled) {
        // TODO: set the right setting
    }

    /**
     * Returns true if the touchpad should use the right click zone.
     *
     * The returned value only applies to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @return Whether the touchpad should use the right click zone.
     *
     * @hide
     */
    public boolean useTouchpadRightClickZone(@NonNull Context context) {
        return Settings.System.getIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, 0, UserHandle.USER_CURRENT) == 1;
    }

    /**
     * Sets the right click zone behavior for the touchpad.
     *
     * The new behavior is only applied to gesture-compatible touchpads.
     *
     * @param context The application context.
     * @param enabled Will enable the right click zone if true, disable it if false
     *
     * @hide
     */
    @RequiresPermission(Manifest.permission.WRITE_SETTINGS)
    public void setTouchpadRightClickZone(@NonNull Context context, boolean enabled) {
        Settings.System.putIntForUser(context.getContentResolver(),
                Settings.System.TOUCHPAD_RIGHT_CLICK_ZONE, enabled ? 1 : 0,
                UserHandle.USER_CURRENT);
    }

    /**
     * Registers a Keyboard backlight change listener to be notified about {@link
     * KeyboardBacklightState} changes for connected keyboard devices.
+319 −0

File added.

Preview size limit exceeded, changes collapsed.

+3 −2
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothDevice
import android.content.Context
import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.hardware.input.InputSettings
import android.os.Handler
import android.util.ArrayMap
import android.util.Log
@@ -235,9 +236,9 @@ constructor(
     */
    private fun onStylusUsed() {
        if (!featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)) return
        if (inputManager.isStylusEverUsed(context)) return
        if (InputSettings.isStylusEverUsed(context)) return

        inputManager.setStylusEverUsed(context, true)
        InputSettings.setStylusEverUsed(context, true)
        executeStylusCallbacks { cb -> cb.onStylusFirstUsed() }
    }

+26 −9
Original line number Diff line number Diff line
@@ -19,10 +19,16 @@ import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.hardware.BatteryState
import android.hardware.input.InputManager
import android.hardware.input.InputSettings
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.view.InputDevice
import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.ExtendedMockito.never
import com.android.dx.mockito.inline.extended.ExtendedMockito.times
import com.android.dx.mockito.inline.extended.ExtendedMockito.verify
import com.android.dx.mockito.inline.extended.StaticMockitoSession
import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FeatureFlags
@@ -30,18 +36,17 @@ import com.android.systemui.flags.Flags
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import java.util.concurrent.Executor
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
import org.mockito.quality.Strictness

@RunWith(AndroidTestingRunner::class)
@SmallTest
@@ -67,11 +72,17 @@ class StylusManagerTest : SysuiTestCase() {

    @Mock lateinit var otherStylusBatteryCallback: StylusManager.StylusBatteryCallback

    private lateinit var mockitoSession: StaticMockitoSession
    private lateinit var stylusManager: StylusManager

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        mockitoSession =
            mockitoSession()
                .mockStatic(InputSettings::class.java)
                .strictness(Strictness.LENIENT)
                .startMocking()

        whenever(handler.post(any())).thenAnswer {
            (it.arguments[0] as Runnable).run()
@@ -103,19 +114,25 @@ class StylusManagerTest : SysuiTestCase() {
        whenever(inputManager.getInputDevice(STYLUS_DEVICE_ID)).thenReturn(stylusDevice)
        whenever(inputManager.getInputDevice(BT_STYLUS_DEVICE_ID)).thenReturn(btStylusDevice)
        whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(STYLUS_DEVICE_ID))
        whenever(inputManager.isStylusEverUsed(mContext)).thenReturn(false)

        whenever(bluetoothAdapter.getRemoteDevice(STYLUS_BT_ADDRESS)).thenReturn(bluetoothDevice)
        whenever(bluetoothDevice.address).thenReturn(STYLUS_BT_ADDRESS)

        whenever(featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)).thenReturn(true)

        whenever(InputSettings.isStylusEverUsed(mContext)).thenReturn(false)

        stylusManager.startListener()
        stylusManager.registerCallback(stylusCallback)
        stylusManager.registerBatteryCallback(stylusBatteryCallback)
        clearInvocations(inputManager)
    }

    @After
    fun tearDown() {
        mockitoSession.finishMocking()
    }

    @Test
    fun startListener_hasNotStarted_registersInputDeviceListener() {
        stylusManager =
@@ -209,8 +226,7 @@ class StylusManagerTest : SysuiTestCase() {
    @Test
    fun onInputDeviceAdded_btStylus_firstUsed_setsFlag() {
        stylusManager.onInputDeviceAdded(BT_STYLUS_DEVICE_ID)

        verify(inputManager, times(1)).setStylusEverUsed(mContext, true)
        verify({ InputSettings.setStylusEverUsed(mContext, true) }, times(1))
    }

    @Test
@@ -484,7 +500,7 @@ class StylusManagerTest : SysuiTestCase() {

        stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)

        verify(inputManager).setStylusEverUsed(mContext, true)
        verify({ InputSettings.setStylusEverUsed(mContext, true) }, times(1))
    }

    @Test
@@ -539,12 +555,13 @@ class StylusManagerTest : SysuiTestCase() {

    @Test
    fun onBatteryStateChanged_batteryPresent_stylusUsed_doesNotUpdateEverUsedFlag() {
        whenever(inputManager.isStylusEverUsed(mContext)).thenReturn(true)
        whenever(InputSettings.isStylusEverUsed(mContext)).thenReturn(true)

        whenever(batteryState.isPresent).thenReturn(true)

        stylusManager.onBatteryStateChanged(STYLUS_DEVICE_ID, 1, batteryState)

        verify(inputManager, never()).setStylusEverUsed(mContext, true)
        verify({ InputSettings.setStylusEverUsed(mContext, true) }, never())
    }

    @Test
Loading