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

Commit 52a2b511 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge changes I9ea5a635,I3b6e0f30,Ie35baae9,I15ad5082

* changes:
  Move USI version configuration from config.xml to DisplayDeviceConfig
  InputManager: Fix compiler warnings and issues in documentation
  Provide Context to InputManager and deprecate getInstance
  Add InputManager as a member in ViewRootImpl
parents 0345d61b df8ae818
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -510,11 +510,12 @@ public final class SystemServiceRegistry {
                return new BinaryTransparencyManager(ctx, service);
            }});

        // InputManager stores its own static instance for historical purposes.
        registerService(Context.INPUT_SERVICE, InputManager.class,
                new StaticServiceFetcher<InputManager>() {
                new ServiceFetcher<InputManager>() {
            @Override
            public InputManager createService() {
                return InputManager.getInstance();
            public InputManager getService(ContextImpl ctx) {
                return InputManager.getInstance(ctx);
            }});

        registerService(Context.DISPLAY_SERVICE, DisplayManager.class,
+9 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.companion.virtual.IVirtualDevice;
import android.graphics.Point;
import android.hardware.SensorManager;
import android.hardware.input.HostUsiVersion;
import android.os.Handler;
import android.os.PowerManager;
import android.util.IntArray;
@@ -402,6 +403,14 @@ public abstract class DisplayManagerInternal {
     */
    public abstract SurfaceControl.DisplayPrimaries getDisplayNativePrimaries(int displayId);

    /**
     * Get the version of the Universal Stylus Initiative (USI) Protocol supported by the display.
     * @param displayId The id of the display.
     * @return The USI version, or null if not supported
     */
    @Nullable
    public abstract HostUsiVersion getHostUsiVersion(int displayId);

    /**
     * Describes the requested power state of the display.
     *
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.hardware.input;

import android.graphics.Rect;
import android.hardware.input.HostUsiVersion;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
@@ -233,4 +234,6 @@ interface IInputManager {
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
            + "android.Manifest.permission.MONITOR_KEYBOARD_BACKLIGHT)")
    void unregisterKeyboardBacklightListener(IKeyboardBacklightListener listener);

    HostUsiVersion getHostUsiVersionFromDisplayConfig(int displayId);
}
+108 −102
Original line number Diff line number Diff line
@@ -55,8 +55,6 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.util.DisplayUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
@@ -71,7 +69,6 @@ import android.view.WindowManager.LayoutParams;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
@@ -102,19 +99,33 @@ public final class InputManager {
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final IInputManager mIm;

    private final boolean mIsStylusPointerIconEnabled;
    /**
     * InputManager has historically used its own static getter {@link #getInstance()} that doesn't
     * provide a context. We provide a Context to the InputManager instance through the
     * {@link android.app.SystemServiceRegistry}. Methods that need a Context must use
     * {@link #getContext()} to obtain it.
     */
    @Nullable
    private Context mLateInitContext;

    /**
     * Whether a PointerIcon is shown for stylus pointers.
     * Obtain using {@link #isStylusPointerIconEnabled()}.
     */
    @Nullable
    private Boolean mIsStylusPointerIconEnabled = null;

    // Guarded by mInputDevicesLock
    private final Object mInputDevicesLock = new Object();
    private SparseArray<InputDevice> mInputDevices;
    private InputDevicesChangedListener mInputDevicesChangedListener;
    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
            new ArrayList<InputDeviceListenerDelegate>();
    private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners = new ArrayList<>();

    // Guarded by mTabletModeLock
    private final Object mTabletModeLock = new Object();
    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
    private TabletModeChangedListener mTabletModeChangedListener;
    private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
    private ArrayList<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;

    private final Object mBatteryListenersLock = new Object();
    // Maps a deviceId whose battery is currently being monitored to an entry containing the
@@ -126,7 +137,7 @@ public final class InputManager {

    private final Object mKeyboardBacklightListenerLock = new Object();
    @GuardedBy("mKeyboardBacklightListenerLock")
    private List<KeyboardBacklightListenerDelegate> mKeyboardBacklightListeners;
    private ArrayList<KeyboardBacklightListenerDelegate> mKeyboardBacklightListeners;
    @GuardedBy("mKeyboardBacklightListenerLock")
    private IKeyboardBacklightListener mKeyboardBacklightListener;

@@ -326,15 +337,6 @@ public final class InputManager {
        } catch (RemoteException ex) {
            Log.w(TAG, "Could not get VelocityTracker strategy: " + ex);
        }

        // TODO(b/266013036): Pass a Context into InputManager constructor.
        final Context context = ActivityThread.currentApplication();
        if (context != null) {
            mIsStylusPointerIconEnabled = context.getResources()
                    .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon);
        } else {
            mIsStylusPointerIconEnabled = false;
        }
    }

    /**
@@ -368,24 +370,47 @@ public final class InputManager {
     * Gets an instance of the input manager.
     *
     * @return The input manager instance.
     *
     * @deprecated Use {@link Context#getSystemService(Class)} or {@link #getInstance(Context)}
     * to obtain the InputManager instance.
     * @hide
     */
    @Deprecated
    @UnsupportedAppUsage
    public static InputManager getInstance() {
        return getInstance(ActivityThread.currentApplication());
    }

    /**
     * Gets an instance of the input manager.
     *
     * @return The input manager instance.
     * @hide
     */
    public static InputManager getInstance(Context context) {
        synchronized (InputManager.class) {
            if (sInstance == null) {
                try {
                    sInstance = new InputManager(IInputManager.Stub
                            .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE)));

                } catch (ServiceNotFoundException e) {
                    throw new IllegalStateException(e);
                }
            }
            if (sInstance.mLateInitContext == null) {
                sInstance.mLateInitContext = context;
            }
            return sInstance;
        }
    }

    @NonNull
    private Context getContext() {
        return Objects.requireNonNull(mLateInitContext,
                "A context is required for InputManager. Get the InputManager instance using "
                        + "Context#getSystemService before calling this method.");
    }

    /**
     * Get the current VelocityTracker strategy. Only works when the system has fully booted up.
     * @hide
@@ -499,7 +524,7 @@ public final class InputManager {
    /**
     * Enables an InputDevice.
     * <p>
     * Requires {@link android.Manifest.permission.DISABLE_INPUT_DEVICE}.
     * Requires {@link android.Manifest.permission#DISABLE_INPUT_DEVICE}.
     * </p>
     *
     * @param id The input device Id.
@@ -518,7 +543,7 @@ public final class InputManager {
    /**
     * Disables an InputDevice.
     * <p>
     * Requires {@link android.Manifest.permission.DISABLE_INPUT_DEVICE}.
     * Requires {@link android.Manifest.permission#DISABLE_INPUT_DEVICE}.
     * </p>
     *
     * @param id The input device Id.
@@ -975,6 +1000,7 @@ public final class InputManager {
     */
    @TestApi
    @NonNull
    @SuppressWarnings("unchecked")
    @RequiresPermission(Manifest.permission.REMAP_MODIFIER_KEYS)
    public Map<Integer, Integer> getModifierKeyRemapping() {
        try {
@@ -1005,7 +1031,7 @@ public final class InputManager {
     * Sets the TouchCalibration to apply to the specified input device's coordinates.
     * <p>
     * This method may have the side-effect of causing the input device in question
     * to be reconfigured. Requires {@link android.Manifest.permission.SET_INPUT_CALIBRATION}.
     * to be reconfigured. Requires {@link android.Manifest.permission#SET_INPUT_CALIBRATION}.
     * </p>
     *
     * @param inputDeviceDescriptor The input device descriptor.
@@ -1121,19 +1147,14 @@ public final class InputManager {
     * @hide
     */
    public int getPointerSpeed(Context context) {
        int speed = DEFAULT_POINTER_SPEED;
        try {
            speed = Settings.System.getInt(context.getContentResolver(),
                    Settings.System.POINTER_SPEED);
        } catch (SettingNotFoundException snfe) {
        }
        return speed;
        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}.
     * Requires {@link android.Manifest.permission#WRITE_SETTINGS}.
     * </p>
     *
     * @param context The application context.
@@ -1154,7 +1175,7 @@ public final class InputManager {
    /**
     * Changes the mouse pointer speed temporarily, but does not save the setting.
     * <p>
     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
     * Requires {@link android.Manifest.permission#SET_POINTER_SPEED}.
     * </p>
     *
     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
@@ -1188,8 +1209,7 @@ public final class InputManager {
     */
    @FloatRange(from = 0, to = 1)
    public float getMaximumObscuringOpacityForTouch() {
        Context context = ActivityThread.currentApplication();
        return Settings.Global.getFloat(context.getContentResolver(),
        return Settings.Global.getFloat(getContext().getContentResolver(),
                Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH,
                DEFAULT_MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH);
    }
@@ -1225,8 +1245,7 @@ public final class InputManager {
            throw new IllegalArgumentException(
                    "Maximum obscuring opacity for touch should be >= 0 and <= 1");
        }
        Context context = ActivityThread.currentApplication();
        Settings.Global.putFloat(context.getContentResolver(),
        Settings.Global.putFloat(getContext().getContentResolver(),
                Settings.Global.MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH, opacity);
    }

@@ -1307,7 +1326,7 @@ public final class InputManager {
     * The synchronization mode determines whether the method blocks while waiting for
     * input injection to proceed.
     * <p>
     * Requires the {@link android.Manifest.permission.INJECT_EVENTS} permission.
     * Requires the {@link android.Manifest.permission#INJECT_EVENTS} permission.
     * </p><p>
     * Make sure you correctly set the event time and input source of the event
     * before calling this method.
@@ -1315,9 +1334,9 @@ public final class InputManager {
     *
     * @param event The event to inject.
     * @param mode The synchronization mode.  One of:
     * {@link android.os.InputEventInjectionSync.NONE},
     * {@link android.os.InputEventInjectionSync.WAIT_FOR_RESULT}, or
     * {@link android.os.InputEventInjectionSync.WAIT_FOR_FINISHED}.
     * {@link android.os.InputEventInjectionSync#NONE},
     * {@link android.os.InputEventInjectionSync#WAIT_FOR_RESULT}, or
     * {@link android.os.InputEventInjectionSync#WAIT_FOR_FINISHED}.
     * @param targetUid The uid to target, or {@link android.os.Process#INVALID_UID} to target all
     *                 windows.
     * @return True if input event injection succeeded.
@@ -1347,7 +1366,7 @@ public final class InputManager {
     * The synchronization mode determines whether the method blocks while waiting for
     * input injection to proceed.
     * <p>
     * Requires the {@link android.Manifest.permission.INJECT_EVENTS} permission.
     * Requires the {@link android.Manifest.permission#INJECT_EVENTS} permission.
     * </p><p>
     * Make sure you correctly set the event time and input source of the event
     * before calling this method.
@@ -1355,9 +1374,9 @@ public final class InputManager {
     *
     * @param event The event to inject.
     * @param mode The synchronization mode.  One of:
     * {@link android.os.InputEventInjectionSync.NONE},
     * {@link android.os.InputEventInjectionSync.WAIT_FOR_RESULT}, or
     * {@link android.os.InputEventInjectionSync.WAIT_FOR_FINISHED}.
     * {@link android.os.InputEventInjectionSync#NONE},
     * {@link android.os.InputEventInjectionSync#WAIT_FOR_RESULT}, or
     * {@link android.os.InputEventInjectionSync#WAIT_FOR_FINISHED}.
     * @return True if input event injection succeeded.
     *
     * @hide
@@ -1381,7 +1400,8 @@ public final class InputManager {
     * {@link android.view.InputEvent}
     *         {@code null} if the event could not be verified.
     */
    public @Nullable VerifiedInputEvent verifyInputEvent(@NonNull InputEvent event) {
    @Nullable
    public VerifiedInputEvent verifyInputEvent(@NonNull InputEvent event) {
        try {
            return mIm.verifyInputEvent(event);
        } catch (RemoteException ex) {
@@ -1393,7 +1413,7 @@ public final class InputManager {
     * Changes the mouse pointer's icon shape into the specified id.
     *
     * @param iconId The id of the pointer graphic, as a value between
     * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_HANDWRITING}.
     * {@link PointerIcon#TYPE_ARROW} and {@link PointerIcon#TYPE_HANDWRITING}.
     *
     * @hide
     */
@@ -1422,6 +1442,10 @@ public final class InputManager {
     * stylus pointer, false if there is no pointer icon shown for styluses.
     */
    public boolean isStylusPointerIconEnabled() {
        if (mIsStylusPointerIconEnabled == null) {
            mIsStylusPointerIconEnabled = getContext().getResources()
                    .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon);
        }
        return mIsStylusPointerIconEnabled;
    }

@@ -1543,7 +1567,7 @@ public final class InputManager {
     * @param inputPort The port of the input device.
     * @param displayPort The physical port of the associated display.
     * <p>
     * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
@@ -1560,7 +1584,7 @@ public final class InputManager {
     * static association for the cleared input port will be restored.
     * @param inputPort The port of the input device to be cleared.
     * <p>
     * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
@@ -1578,7 +1602,7 @@ public final class InputManager {
     * @param inputPort The port of the input device.
     * @param displayUniqueId The unique id of the associated display.
     * <p>
     * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
@@ -1595,7 +1619,7 @@ public final class InputManager {
     * Removes a runtime association between the input device and display.
     * @param inputPort The port of the input device.
     * <p>
     * Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * Requires {@link android.Manifest.permission#ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
@@ -1637,35 +1661,11 @@ public final class InputManager {
        // If there are no input devices that report a valid USI version, see if there is a config
        // that specifies the USI version for the display. This is to handle cases where the USI
        // input device is not registered by the kernel/driver all the time.
        return findConfigUsiVersionForDisplay(display);
    }

    private HostUsiVersion findConfigUsiVersionForDisplay(@NonNull Display display) {
        final Context context = Objects.requireNonNull(ActivityThread.currentApplication());
        final String[] displayUniqueIds = context.getResources().getStringArray(
                R.array.config_displayUniqueIdArray);
        final int index;
        if (displayUniqueIds.length == 0 && display.getDisplayId() == context.getDisplayId()) {
            index = 0;
        } else {
            index = DisplayUtils.getDisplayUniqueIdConfigIndex(context.getResources(),
                    display.getUniqueId());
        }

        final String[] versions = context.getResources().getStringArray(
                R.array.config_displayUsiVersionArray);
        if (index < 0 || index >= versions.length) {
            return null;
        }
        final String version = versions[index];
        if (version == null || version.isEmpty()) {
            return null;
        }
        final String[] majorMinor = version.split("\\.");
        if (majorMinor.length != 2) {
            throw new IllegalStateException("Failed to parse USI version: " + version);
        try {
            return mIm.getHostUsiVersionFromDisplayConfig(display.getDisplayId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return new HostUsiVersion(Integer.parseInt(majorMinor[0]), Integer.parseInt(majorMinor[1]));
    }

    private void populateInputDevicesLocked() {
@@ -1687,9 +1687,9 @@ public final class InputManager {
                throw ex.rethrowFromSystemServer();
            }

            mInputDevices = new SparseArray<InputDevice>();
            for (int i = 0; i < ids.length; i++) {
                mInputDevices.put(ids[i], null);
            mInputDevices = new SparseArray<>();
            for (int id : ids) {
                mInputDevices.put(id, null);
            }
        }
    }
@@ -1761,8 +1761,8 @@ public final class InputManager {
                    + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
        }
        synchronized (mTabletModeLock) {
            final int N = mOnTabletModeChangedListeners.size();
            for (int i = 0; i < N; i++) {
            final int numListeners = mOnTabletModeChangedListeners.size();
            for (int i = 0; i < numListeners; i++) {
                OnTabletModeChangedListenerDelegate listener =
                        mOnTabletModeChangedListeners.get(i);
                listener.sendTabletModeChanged(whenNanos, inTabletMode);
@@ -1965,7 +1965,7 @@ public final class InputManager {
            }
            List<LightState> lightStateList = request.getLightStates();
            mIm.setLightStates(deviceId, lightIds,
                    lightStateList.toArray(new LightState[lightStateList.size()]),
                    lightStateList.toArray(new LightState[0]),
                    token);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
@@ -2072,8 +2072,11 @@ public final class InputManager {
            } else {
                // The deviceId is already being monitored for battery changes.
                // Ensure that the listener is not already registered.
                for (InputDeviceBatteryListenerDelegate delegate : listenersForDevice.mDelegates) {
                    if (Objects.equals(listener, delegate.mListener)) {
                final int numDelegates = listenersForDevice.mDelegates.size();
                for (int i = 0; i < numDelegates; i++) {
                    InputDeviceBatteryListener registeredListener =
                            listenersForDevice.mDelegates.get(i).mListener;
                    if (Objects.equals(listener, registeredListener)) {
                        throw new IllegalArgumentException(
                                "Attempting to register an InputDeviceBatteryListener that has "
                                        + "already been registered for deviceId: "
@@ -2208,7 +2211,7 @@ public final class InputManager {
     * Changes the touchpad pointer speed temporarily, but does not save the setting.
     *
     * The new speed will only apply to gesture-compatible touchpads.
     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
     * Requires {@link android.Manifest.permission#SET_POINTER_SPEED}.
     *
     * @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}.
@@ -2398,8 +2401,9 @@ public final class InputManager {
                    throw e.rethrowFromSystemServer();
                }
            }
            for (KeyboardBacklightListenerDelegate delegate : mKeyboardBacklightListeners) {
                if (delegate.mListener == listener) {
            final int numListeners = mKeyboardBacklightListeners.size();
            for (int i = 0; i < numListeners; i++) {
                if (mKeyboardBacklightListeners.get(i).mListener == listener) {
                    throw new IllegalArgumentException("Listener has already been registered!");
                }
            }
@@ -2572,21 +2576,19 @@ public final class InputManager {

        public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
            SomeArgs args = SomeArgs.obtain();
            args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
            args.argi1 = (int) whenNanos;
            args.argi2 = (int) (whenNanos >> 32);
            args.arg1 = (Boolean) inTabletMode;
            args.arg1 = inTabletMode;
            obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_TABLET_MODE_CHANGED:
            if (msg.what == MSG_TABLET_MODE_CHANGED) {
                SomeArgs args = (SomeArgs) msg.obj;
                    long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
                long whenNanos = (args.argi1 & 0xFFFFFFFFL) | ((long) args.argi2 << 32);
                boolean inTabletMode = (boolean) args.arg1;
                mListener.onTabletModeChanged(whenNanos, inTabletMode);
                    break;
            }
        }
    }
@@ -2654,8 +2656,10 @@ public final class InputManager {
                if (entry == null) return;

                entry.mInputDeviceBatteryState = state;
                for (InputDeviceBatteryListenerDelegate delegate : entry.mDelegates) {
                    delegate.notifyBatteryStateChanged(entry.mInputDeviceBatteryState);
                final int numDelegates = entry.mDelegates.size();
                for (int i = 0; i < numDelegates; i++) {
                    entry.mDelegates.get(i)
                            .notifyBatteryStateChanged(entry.mInputDeviceBatteryState);
                }
            }
        }
@@ -2668,8 +2672,8 @@ public final class InputManager {
        private final int mBrightnessLevel;
        private final int mMaxBrightnessLevel;

        LocalKeyboardBacklightState(int brightnesslevel, int maxBrightnessLevel) {
            mBrightnessLevel = brightnesslevel;
        LocalKeyboardBacklightState(int brightnessLevel, int maxBrightnessLevel) {
            mBrightnessLevel = brightnessLevel;
            mMaxBrightnessLevel = maxBrightnessLevel;
        }

@@ -2709,8 +2713,10 @@ public final class InputManager {
                boolean isTriggeredByKeyPress) {
            synchronized (mKeyboardBacklightListenerLock) {
                if (mKeyboardBacklightListeners == null) return;
                for (KeyboardBacklightListenerDelegate delegate : mKeyboardBacklightListeners) {
                    delegate.notifyKeyboardBacklightChange(deviceId, state, isTriggeredByKeyPress);
                final int numListeners = mKeyboardBacklightListeners.size();
                for (int i = 0; i < numListeners; i++) {
                    mKeyboardBacklightListeners.get(i)
                            .notifyKeyboardBacklightChange(deviceId, state, isTriggeredByKeyPress);
                }
            }
        }
Loading