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

Commit aa46f324 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move key remapping to InputReader thread(2/n)" into main

parents 21b6c759 fefc2640
Loading
Loading
Loading
Loading
+19 −47
Original line number Diff line number Diff line
@@ -17,27 +17,24 @@
package com.android.server.input;

import android.content.Context;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.ArrayMap;
import android.util.FeatureFlagUtils;
import android.view.InputDevice;

import com.android.internal.annotations.GuardedBy;

import java.util.Map;
import java.util.Objects;

/**
 * A component of {@link InputManagerService} responsible for managing key remappings.
 *
 * @hide
 */
final class KeyRemapper implements InputManager.InputDeviceListener {
final class KeyRemapper {

    private static final int MSG_UPDATE_EXISTING_DEVICES = 1;
    private static final int MSG_UPDATE_EXISTING_KEY_REMAPPING = 1;
    private static final int MSG_REMAP_KEY = 2;
    private static final int MSG_CLEAR_ALL_REMAPPING = 3;

@@ -57,13 +54,7 @@ final class KeyRemapper implements InputManager.InputDeviceListener {
    }

    public void systemRunning() {
        InputManager inputManager = Objects.requireNonNull(
                mContext.getSystemService(InputManager.class));
        inputManager.registerInputDeviceListener(this, mHandler);

        Message msg = Message.obtain(mHandler, MSG_UPDATE_EXISTING_DEVICES,
                inputManager.getInputDeviceIds());
        mHandler.sendMessage(msg);
        Message.obtain(mHandler, MSG_UPDATE_EXISTING_KEY_REMAPPING).sendToTarget();
    }

    public void remapKey(int fromKey, int toKey) {
@@ -91,19 +82,19 @@ final class KeyRemapper implements InputManager.InputDeviceListener {
        }
    }

    private void addKeyRemapping(int fromKey, int toKey) {
        InputManager inputManager = Objects.requireNonNull(
                mContext.getSystemService(InputManager.class));
        for (int deviceId : inputManager.getInputDeviceIds()) {
            InputDevice inputDevice = inputManager.getInputDevice(deviceId);
            if (inputDevice != null && !inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
                mNative.addKeyRemapping(deviceId, fromKey, toKey);
            }
    private void setKeyRemapping(Map<Integer, Integer> keyRemapping) {
        int index = 0;
        int[] fromKeycodesArr = new int[keyRemapping.size()];
        int[] toKeycodesArr = new int[keyRemapping.size()];
        for (Map.Entry<Integer, Integer> entry : keyRemapping.entrySet()) {
            fromKeycodesArr[index] = entry.getKey();
            toKeycodesArr[index] = entry.getValue();
            index++;
        }
        mNative.setKeyRemapping(fromKeycodesArr, toKeycodesArr);
    }

    private void remapKeyInternal(int fromKey, int toKey) {
        addKeyRemapping(fromKey, toKey);
        synchronized (mDataStore) {
            try {
                if (fromKey == toKey) {
@@ -114,6 +105,7 @@ final class KeyRemapper implements InputManager.InputDeviceListener {
            } finally {
                mDataStore.saveIfNeeded();
            }
            setKeyRemapping(mDataStore.getKeyRemapping());
        }
    }

@@ -123,45 +115,25 @@ final class KeyRemapper implements InputManager.InputDeviceListener {
                Map<Integer, Integer> keyRemapping = mDataStore.getKeyRemapping();
                for (int fromKey : keyRemapping.keySet()) {
                    mDataStore.clearMappedKey(fromKey);

                    // Remapping to itself will clear the remapping on native side
                    addKeyRemapping(fromKey, fromKey);
                }
            } finally {
                mDataStore.saveIfNeeded();
            }
            setKeyRemapping(mDataStore.getKeyRemapping());
        }
    }

    @Override
    public void onInputDeviceAdded(int deviceId) {
    public void updateExistingKeyMapping() {
        if (!supportRemapping()) {
            return;
        }
        InputManager inputManager = Objects.requireNonNull(
                mContext.getSystemService(InputManager.class));
        InputDevice inputDevice = inputManager.getInputDevice(deviceId);
        if (inputDevice != null && !inputDevice.isVirtual() && inputDevice.isFullKeyboard()) {
            Map<Integer, Integer> remapping = getKeyRemapping();
            remapping.forEach(
                    (fromKey, toKey) -> mNative.addKeyRemapping(deviceId, fromKey, toKey));
        }
    }

    @Override
    public void onInputDeviceRemoved(int deviceId) {
    }

    @Override
    public void onInputDeviceChanged(int deviceId) {
        setKeyRemapping(getKeyRemapping());
    }

    private boolean handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_UPDATE_EXISTING_DEVICES:
                for (int deviceId : (int[]) msg.obj) {
                    onInputDeviceAdded(deviceId);
                }
            case MSG_UPDATE_EXISTING_KEY_REMAPPING:
                updateExistingKeyMapping();
                return true;
            case MSG_REMAP_KEY:
                remapKeyInternal(msg.arg1, msg.arg2);
+2 −2
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ interface NativeInputManagerService {

    int getSwitchState(int deviceId, int sourceMask, int sw);

    void addKeyRemapping(int deviceId, int fromKeyCode, int toKeyCode);
    void setKeyRemapping(int[] fromKeyCodes, int[] toKeyCodes);

    boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);

@@ -311,7 +311,7 @@ interface NativeInputManagerService {
        public native int getSwitchState(int deviceId, int sourceMask, int sw);

        @Override
        public native void addKeyRemapping(int deviceId, int fromKeyCode, int toKeyCode);
        public native void setKeyRemapping(int[] fromKeyCodes, int[] toKeyCodes);

        @Override
        public native boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes,
+30 −5
Original line number Diff line number Diff line
@@ -357,6 +357,7 @@ public:
    FloatPoint getMouseCursorPosition(ui::LogicalDisplayId displayId);
    void setStylusPointerIconEnabled(bool enabled);
    void setInputMethodConnectionIsActive(bool isActive);
    void setKeyRemapping(const std::map<int32_t, int32_t>& keyRemapping);

    /* --- InputReaderPolicyInterface implementation --- */

@@ -504,6 +505,9 @@ private:

        // True if there is an active input method connection.
        bool isInputMethodConnectionActive{false};

        // Keycodes to be remapped.
        std::map<int32_t /* fromKeyCode */, int32_t /* toKeyCode */> keyRemapping{};
    } mLocked GUARDED_BY(mLock);

    std::atomic<bool> mInteractive;
@@ -761,6 +765,8 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
        outConfig->stylusButtonMotionEventsEnabled = mLocked.stylusButtonMotionEventsEnabled;

        outConfig->stylusPointerIconEnabled = mLocked.stylusPointerIconEnabled;

        outConfig->keyRemapping = mLocked.keyRemapping;
    } // release lock
}

@@ -1910,6 +1916,16 @@ void NativeInputManager::setInputMethodConnectionIsActive(bool isActive) {
    mInputManager->getDispatcher().setInputMethodConnectionIsActive(isActive);
}

void NativeInputManager::setKeyRemapping(const std::map<int32_t, int32_t>& keyRemapping) {
    { // acquire lock
        std::scoped_lock _l(mLock);
        mLocked.keyRemapping = keyRemapping;
    } // release lock

    mInputManager->getReader().requestRefreshConfiguration(
            InputReaderConfiguration::Change::KEY_REMAPPING);
}

// ----------------------------------------------------------------------------

static NativeInputManager* getNativeInputManager(JNIEnv* env, jobject clazz) {
@@ -1983,10 +1999,19 @@ static std::vector<int32_t> getIntArray(JNIEnv* env, jintArray arr) {
    return vec;
}

static void nativeAddKeyRemapping(JNIEnv* env, jobject nativeImplObj, jint deviceId,
                                  jint fromKeyCode, jint toKeyCode) {
static void nativeSetKeyRemapping(JNIEnv* env, jobject nativeImplObj, jintArray fromKeyCodesArr,
                                  jintArray toKeyCodesArr) {
    const std::vector<int32_t> fromKeycodes = getIntArray(env, fromKeyCodesArr);
    const std::vector<int32_t> toKeycodes = getIntArray(env, toKeyCodesArr);
    if (fromKeycodes.size() != toKeycodes.size()) {
        jniThrowRuntimeException(env, "FromKeycodes and toKeycodes cannot match.");
    }
    NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
    im->getInputManager()->getReader().addKeyRemapping(deviceId, fromKeyCode, toKeyCode);
    std::map<int32_t, int32_t> keyRemapping;
    for (int i = 0; i < fromKeycodes.size(); i++) {
        keyRemapping.insert_or_assign(fromKeycodes[i], toKeycodes[i]);
    }
    im->setKeyRemapping(keyRemapping);
}

static jboolean nativeHasKeys(JNIEnv* env, jobject nativeImplObj, jint deviceId, jint sourceMask,
@@ -2491,7 +2516,7 @@ static jobject nativeGetLights(JNIEnv* env, jobject nativeImplObj, jint deviceId
            jTypeId = env->GetStaticIntField(gLightClassInfo.clazz,
                                             gLightClassInfo.lightTypeKeyboardMicMute);
        } else {
            ALOGW("Unknown light type %d", lightInfo.type);
            ALOGW("Unknown light type %s", ftl::enum_string(lightInfo.type).c_str());
            continue;
        }

@@ -2955,7 +2980,7 @@ static const JNINativeMethod gInputManagerMethods[] = {
        {"getScanCodeState", "(III)I", (void*)nativeGetScanCodeState},
        {"getKeyCodeState", "(III)I", (void*)nativeGetKeyCodeState},
        {"getSwitchState", "(III)I", (void*)nativeGetSwitchState},
        {"addKeyRemapping", "(III)V", (void*)nativeAddKeyRemapping},
        {"setKeyRemapping", "([I[I)V", (void*)nativeSetKeyRemapping},
        {"hasKeys", "(II[I[Z)Z", (void*)nativeHasKeys},
        {"getKeyCodeForKeyLocation", "(II)I", (void*)nativeGetKeyCodeForKeyLocation},
        {"createInputChannel", "(Ljava/lang/String;)Landroid/view/InputChannel;",