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

Commit 53ecc102 authored by Christine Franks's avatar Christine Franks
Browse files

Check virtual displays for ime dispatch

Bug: 184615313
Test: atest -a inputflinger_tests and atest -a libinput_tests
Change-Id: Ide4d7a0530e00eee3e2b7456d1d93df753b70afd
parent 6629f13e
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -117,6 +117,11 @@ interface IInputManager {
    // static association for the cleared input port will be restored.
    void removePortAssociation(in String inputPort);

    // Add a runtime association between the input device and display.
    void addUniqueIdAssociation(in String inputDeviceName, in String displayUniqueId);
    // Remove the runtime association between the input device and display.
    void removeUniqueIdAssociation(in String inputDeviceName);

    InputSensorInfo[] getSensorList(int deviceId);

    boolean registerSensorListener(IInputSensorEventListener listener);
+37 −2
Original line number Diff line number Diff line
@@ -1293,7 +1293,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.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT}.
     * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
@@ -1310,7 +1310,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.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT}.
     * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
@@ -1322,6 +1322,41 @@ public final class InputManager {
        }
    }

    /**
     * Add a runtime association between the input device name and display, by unique id. Input
     * device names are expected to be unique.
     * @param inputDeviceName The name of the input device.
     * @param displayUniqueId The unique id of the associated display.
     * <p>
     * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    public void addUniqueIdAssociation(@NonNull String inputDeviceName,
            @NonNull String displayUniqueId) {
        try {
            mIm.addUniqueIdAssociation(inputDeviceName, displayUniqueId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Removes a runtime association between the input device and display.
     * @param inputDeviceName The name of the input device.
     * <p>
     * Requires {@link android.Manifest.permissions.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
     * </p>
     * @hide
     */
    public void removeUniqueIdAssociation(@NonNull String inputDeviceName) {
        try {
            mIm.removeUniqueIdAssociation(inputDeviceName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private void populateInputDevicesLocked() {
        if (mInputDevicesChangedListener == null) {
            final InputDevicesChangedListener listener = new InputDevicesChangedListener();
+1 −1
Original line number Diff line number Diff line
@@ -5632,7 +5632,7 @@
                android:protectionLevel="signature|recents" />
    <!--  Allows the caller to change the associations between input devices and displays.
        Very dangerous! @hide -->
    <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT"
    <permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
                android:protectionLevel="signature" />

    <!-- Allows query of any normal app on the device, regardless of manifest declarations.
+63 −8
Original line number Diff line number Diff line
@@ -270,6 +270,8 @@ public class InputManagerService extends IInputManager.Stub
    private final Object mAssociationsLock = new Object();
    @GuardedBy("mAssociationLock")
    private final Map<String, Integer> mRuntimeAssociations = new ArrayMap<String, Integer>();
    @GuardedBy("mAssociationLock")
    private final Map<String, String> mUniqueIdAssociations = new ArrayMap<>();

    private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);
@@ -340,6 +342,7 @@ public class InputManagerService extends IInputManager.Stub
            boolean enabled);
    private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
    private static native void nativeNotifyPortAssociationsChanged(long ptr);
    private static native void nativeChangeUniqueIdAssociation(long ptr);
    private static native void nativeSetMotionClassifierEnabled(long ptr, boolean enabled);
    private static native InputSensorInfo[] nativeGetSensorList(long ptr, int deviceId);
    private static native boolean nativeFlushSensor(long ptr, int deviceId, int sensorType);
@@ -2222,10 +2225,10 @@ public class InputManagerService extends IInputManager.Stub
    @Override // Binder call
    public void addPortAssociation(@NonNull String inputPort, int displayPort) {
        if (!checkCallingPermission(
                android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT,
                android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
                "addPortAssociation()")) {
            throw new SecurityException(
                    "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT permission");
                    "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
        }

        Objects.requireNonNull(inputPort);
@@ -2243,10 +2246,10 @@ public class InputManagerService extends IInputManager.Stub
    @Override // Binder call
    public void removePortAssociation(@NonNull String inputPort) {
        if (!checkCallingPermission(
                android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT,
                android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
                "clearPortAssociations()")) {
            throw new SecurityException(
                    "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY_BY_PORT permission");
                    "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
        }

        Objects.requireNonNull(inputPort);
@@ -2256,6 +2259,49 @@ public class InputManagerService extends IInputManager.Stub
        nativeNotifyPortAssociationsChanged(mPtr);
    }

    /**
     * Add a runtime association between the input device name and the display unique id.
     * @param inputDeviceName The name of the input device.
     * @param displayUniqueId The unique id of the associated display.
     */
    @Override // Binder call
    public void addUniqueIdAssociation(@NonNull String inputDeviceName,
            @NonNull String displayUniqueId) {
        if (!checkCallingPermission(
                android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
                "addNameAssociation()")) {
            throw new SecurityException(
                    "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
        }

        Objects.requireNonNull(inputDeviceName);
        Objects.requireNonNull(displayUniqueId);
        synchronized (mAssociationsLock) {
            mUniqueIdAssociations.put(inputDeviceName, displayUniqueId);
        }
        nativeChangeUniqueIdAssociation(mPtr);
    }

    /**
     * Remove the runtime association between the input device and the display.
     * @param inputDeviceName The port of the input device to be cleared.
     */
    @Override // Binder call
    public void removeUniqueIdAssociation(@NonNull String inputDeviceName) {
        if (!checkCallingPermission(
                android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
                "removeUniqueIdAssociation()")) {
            throw new SecurityException(
                    "Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
        }

        Objects.requireNonNull(inputDeviceName);
        synchronized (mAssociationsLock) {
            mUniqueIdAssociations.remove(inputDeviceName);
        }
        nativeChangeUniqueIdAssociation(mPtr);
    }

    @Override // Binder call
    public InputSensorInfo[] getSensorList(int deviceId) {
        return nativeGetSensorList(mPtr, deviceId);
@@ -2790,13 +2836,13 @@ public class InputManagerService extends IInputManager.Stub
     * key.
     * @return Flattened list
     */
    private static List<String> flatten(@NonNull Map<String, Integer> map) {
    private static <T> String[] flatten(@NonNull Map<String, T> map) {
        final List<String> list = new ArrayList<>(map.size() * 2);
        map.forEach((k, v)-> {
            list.add(k);
            list.add(v.toString());
        });
        return list;
        return list.toArray(new String[0]);
    }

    /**
@@ -2828,8 +2874,17 @@ public class InputManagerService extends IInputManager.Stub
            associations.putAll(mRuntimeAssociations);
        }

        final List<String> associationList = flatten(associations);
        return associationList.toArray(new String[0]);
        return flatten(associations);
    }

    // Native callback
    private String[] getInputUniqueIdAssociations() {
        final Map<String, String> associations;
        synchronized (mAssociationsLock) {
            associations = new HashMap<>(mUniqueIdAssociations);
        }

        return flatten(associations);
    }

    /**
+26 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ static struct {
    jmethodID getVirtualKeyQuietTimeMillis;
    jmethodID getExcludedDeviceNames;
    jmethodID getInputPortAssociations;
    jmethodID getInputUniqueIdAssociations;
    jmethodID getKeyRepeatTimeout;
    jmethodID getKeyRepeatDelay;
    jmethodID getHoverTapTimeout;
@@ -579,6 +580,21 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
        }
        env->DeleteLocalRef(portAssociations);
    }
    outConfig->uniqueIdAssociations.clear();
    jobjectArray uniqueIdAssociations = jobjectArray(
            env->CallObjectMethod(mServiceObj, gServiceClassInfo.getInputUniqueIdAssociations));
    if (!checkAndClearExceptionFromCallback(env, "getInputUniqueIdAssociations") &&
        uniqueIdAssociations) {
        jsize length = env->GetArrayLength(uniqueIdAssociations);
        for (jsize i = 0; i < length / 2; i++) {
            std::string inputDeviceUniqueId =
                    getStringElementFromJavaArray(env, uniqueIdAssociations, 2 * i);
            std::string displayUniqueId =
                    getStringElementFromJavaArray(env, uniqueIdAssociations, 2 * i + 1);
            outConfig->uniqueIdAssociations.insert({inputDeviceUniqueId, displayUniqueId});
        }
        env->DeleteLocalRef(uniqueIdAssociations);
    }

    jint hoverTapTimeout = env->CallIntMethod(mServiceObj,
            gServiceClassInfo.getHoverTapTimeout);
@@ -2134,6 +2150,12 @@ static void nativeNotifyPortAssociationsChanged(JNIEnv* env, jclass /* clazz */,
            InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}

static void nativeChangeUniqueIdAssociation(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    im->getInputManager()->getReader()->requestRefreshConfiguration(
            InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}

static void nativeSetMotionClassifierEnabled(JNIEnv* /* env */, jclass /* clazz */, jlong ptr,
                                             jboolean enabled) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
@@ -2316,6 +2338,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
         (void*)nativeSetCustomPointerIcon},
        {"nativeCanDispatchToDisplay", "(JII)Z", (void*)nativeCanDispatchToDisplay},
        {"nativeNotifyPortAssociationsChanged", "(J)V", (void*)nativeNotifyPortAssociationsChanged},
        {"nativeChangeUniqueIdAssociation", "(J)V", (void*)nativeChangeUniqueIdAssociation},
        {"nativeSetMotionClassifierEnabled", "(JZ)V", (void*)nativeSetMotionClassifierEnabled},
        {"nativeGetSensorList", "(JI)[Landroid/hardware/input/InputSensorInfo;",
         (void*)nativeGetSensorList},
@@ -2425,6 +2448,9 @@ int register_android_server_InputManager(JNIEnv* env) {
    GET_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz,
            "getInputPortAssociations", "()[Ljava/lang/String;");

    GET_METHOD_ID(gServiceClassInfo.getInputUniqueIdAssociations, clazz,
                  "getInputUniqueIdAssociations", "()[Ljava/lang/String;");

    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
            "getKeyRepeatTimeout", "()I");