Android Input(2) -- inputReader

Link:

Android Input (1) -- InputManagerService启动

Android Input (2) -- inputReader

Android Input (3) -- inputDispatcher

Android Input (4) -- inputDispatcher到ViewRootImpl

Android Input (5) -- ViewRootImpl 的事件分发(Activity ViewGroup View )

Android Input (6) -- PhoneWindowManager中Power,BACK等按键处理流程

Android Input (7) -- 模块的锁检测

Android Input (8) -- ANR input event原理


这篇文章讲解InputReader线程,从threadloop开始,经过从eventhub获取事件getevent,然后processEventsLocked处理事件,完成事件的映射map,最后通过flush把事件给mInboundQueue中,这里会先使用interceptKeyBeforeQueueing处理部分事件,然后判断过滤事件filterInputEvent,最后通过enqueueInboundEventLocked方法 放入mInboundQueue

 

Input系统—InputReader线程:通过EventHub从/dev/input节点获取事件,转换成EventEntry事件加入到InputDispatcher的mInboundQueue。

Input系统—InputDispatcher线程:从mInboundQueue队列取出事件,转换成DispatchEntry事件加入到connection的outboundQueue队列。再然后开始处理分发事件,取出outbound队列,放入waitQueue.

Input系统—UI线程:创建socket pair,分别位于”InputDispatcher”线程和focused窗口所在进程的UI主线程,可相互通信。

UI主线程:通过setFdEvents(), 监听socket客户端,收到消息后回调NativeInputEventReceiver();

“InputDispatcher”线程: 通过IMS.registerInputChannel(),监听socket服务端,收到消息后回调handleReceiveCallback;

 

 

目录

1.1 InputReaderThread 线程 threadLoop()

2.1 获取事件mEventHub->getEvents

2.2 处理事件 processEventsLocked

2.2.1 processEventsLocked

2.2.2 InputDevice::process()

2.2.3 KeyboardInputMapper::process()

2.2.4 EventHub::mapKey()

2.2.5 getListener()->notifyKey

2.3 mQueuedListener->flush()

2.3.1 args->notify

2.3.2 InputDispatcher::notifyKey拦截事件并放入队列

2.3.2.1 interceptKeyBeforeQueueing

2.3.2.2 filterInputEvent

2.3.2.3 enqueueInboundEventLocked放入mInboundQueue

2.3.2.4 mLooper::wake


 

InputReader流程图

 

Android Input(2) -- inputReader_第1张图片

 

1.1 InputReaderThread 线程 threadLoop()

@frameworks/native/services/inputflinger/InputReader.cpp
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;  //return true会一直执行
}

void InputReader::loopOnce() {
    ...
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  // 2.1 EVENT_BUFFER_SIZE = 256;  RawEvent mEventBuffer[EVENT_BUFFER_SIZE];

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        if (count) {
            processEventsLocked(mEventBuffer, count);   //2.2 处理事件
        }
        ...
        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);  // 输入设备发生改变
    }

    mQueuedListener->flush();  //2.3 发送事件到nputDispatcher
}

//构建为RawEvent

 

//mEventBuffer
RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
struct RawEvent {
    nsecs_t when;
    int32_t deviceId;
    int32_t type;
    int32_t code;
    int32_t value;
};

struct input_event {
 struct timeval time; //事件发生的时间点
 __u16 type;
 __u16 code;
 __s32 value;
};

2.1 获取事件mEventHub->getEvents

主要就是获取kernel的event, 这里事件不仅包括input,还包括输入设备的add/remove等相关事件。

加入的输入设备在没有事件的时候,会block在EventHub中的epoll处,当有事件产生后,epoll_wait就会返回,然后针对变化的事件进行处理。

 

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ...
    for (;;) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();   //扫描设备
            mNeedToSendFinishedDeviceScan = true;
        }

        while (mOpeningDevices != NULL) {
            Device* device = mOpeningDevices;
            ALOGV("Reporting device opened: id=%d, name=%s\n",
                 device->id, device->path.string());
            mOpeningDevices = device->next;
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
            event->type = DEVICE_ADDED;  //添加设备的事件
            event += 1;
        }
            ...
            Device* device = mDevices.valueAt(deviceIndex);
            if (eventItem.events & EPOLLIN) {
            //从设备不断读取事件,放入到readBuffer
                int32_t readSize = read(device->fd, readBuffer,
                        sizeof(struct input_event) * capacity);
                    int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;

                    size_t count = size_t(readSize) / sizeof(struct input_event);
                    for (size_t i = 0; i < count; i++) {
                        struct input_event& iev = readBuffer[i];   //读取事件
                         ...
                        //将input_event信息, 封装成RawEvent
                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
                        capacity -= 1;
                    }

                }
            ...
        }
                mLock.unlock(); // release lock before poll, must be before release_wake_lock
        release_wake_lock(WAKE_LOCK_ID);

        //poll之前先释放锁 等待input事件的到来
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

        acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);

        } else {
            // Some events occurred.
            mPendingEventCount = size_t(pollResult);
        }
    }

    // All done, return the number of events we read.
    return event - buffer;
}

EventHub采用INotify + epoll机制实现监听目录/dev/input下的设备节点,经过EventHub将input_event结构体 + deviceId 转换成RawEvent结构体,如下:

 

2.2 处理事件 processEventsLocked

2.2.1 processEventsLocked

 

void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:  //设备添加
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::DEVICE_REMOVED:  //remove
                removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            case EventHubInterface::FINISHED_DEVICE_SCAN:  //scan device
                handleConfigurationChangedLocked(rawEvent->when);
                break;
            default:
                ALOG_ASSERT(false); // can't happen
                break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

//处理事件

 

void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex < 0) {
        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
        return;
    }

    InputDevice* device = mDevices.valueAt(deviceIndex);
    if (device->isIgnored()) {
        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }

    device->process(rawEvents, count);
}

2.2.2 InputDevice::process()

@frameworks/native/libs/input/InputDevice.cpp

 

void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    size_t numMappers = mMappers.size();
    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
        if (mDropUntilNextSync) {
        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
        } else {
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                mapper->process(rawEvent);  //调用各个InputMapper对象来映射mapper
            }
        }
    }
}

//frameworks/native/services/inputflinger/InputReader.h

 

class SwitchInputMapper : public InputMapper {
class VibratorInputMapper : public InputMapper {
class KeyboardInputMapper : public InputMapper {
class CursorInputMapper : public InputMapper {
class RotaryEncoderInputMapper : public InputMapper {
class TouchInputMapper : public InputMapper {
class ExternalStylusInputMapper : public InputMapper {
class JoystickInputMapper : public InputMapper {

2.2.3 KeyboardInputMapper::process()

createDeviceLocked创建设备并添加InputMapper,提到会有多种InputMapper。 这里以 KeyboardInputMapper (按键事件)为例来展开说明

@frameworks/native/services/inputflinger/InputReader.cpp

void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EV_KEY: {
        int32_t scanCode = rawEvent->code;
        int32_t usageCode = mCurrentHidUsage;
        mCurrentHidUsage = 0;

        if (isKeyboardOrGamepadKey(scanCode)) {
            processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);  
        }
        break;
    }
    case EV_MSC: {
    case EV_SYN: {
        ...
    }
}
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
        int32_t usageCode) {
    int32_t keyCode;
    int32_t keyMetaState;
    uint32_t policyFlags;

    if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,   //将事件的扫描码(scanCode)转换成键盘码(Keycode)
                              &keyCode, &keyMetaState, &policyFlags)) {
        keyCode = AKEYCODE_UNKNOWN;
        keyMetaState = mMetaState;
        policyFlags = 0;
    }

    if (down) {
    ...
        mDownTime = when;
    } else {
    ...
    }
    //创建NotifyKeyArgs对象, when记录eventTime, downTime记录按下时间
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    getListener()->notifyKey(&args);  //通知key事件
}

2.2.4 EventHub::mapKey()

@EventHub.cpp

 

status_t EventHub::mapKey(int32_t deviceId,
        int32_t scanCode, int32_t usageCode, int32_t metaState,
        int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    status_t status = NAME_NOT_FOUND;

    if (device) {
        // Check the key character map first.
        sp kcm = device->getKeyCharacterMap();
        if (kcm != NULL) {
            if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
                *outFlags = 0;
                status = NO_ERROR;
            }
        }
        // Check the key layout next.
        if (status != NO_ERROR && device->keyMap.haveKeyLayout()) {
            if (!device->keyMap.keyLayoutMap->mapKey(
                    scanCode, usageCode, outKeycode, outFlags)) {
                status = NO_ERROR;
            }
        }

     ...
    }
    return status;
}

mKeyDowns记录着所有按下的键;

mDownTime记录按下时间点;

此处KeyboardInputMapper的mContext指向InputReader,getListener()获取的便是mQueuedListener。 接下来调用该对象的notifyKey.

 

2.2.5 getListener()->notifyKey

 

[-> InputListener.cpp]
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
    mArgsQueue.push(new NotifyKeyArgs(*args));
}

2.3 mQueuedListener->flush()

2.3.1 args->notify

//把值取出来,上面notifyKey push

 

@frameworks/native/services/inputflinger/InputListener.cpp
void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}

遍历整个mArgsQueue数组, 在input架构中NotifyArgs的实现子类主要有以下几类:

 

@frameworks/native/services/inputflinger/InputListener.h
struct NotifyConfigurationChangedArgs : public NotifyArgs {
struct NotifyKeyArgs : public NotifyArgs {
struct NotifyMotionArgs : public NotifyArgs {
struct NotifySwitchArgs : public NotifyArgs {
struct NotifyDeviceResetArgs : public NotifyArgs {
void NotifyKeyArgs::notify(const sp& listener) const {
    listener->notifyKey(this);
}

2.3.2 InputDispatcher::notifyKey拦截事件并放入队列

//listener是inputDispatcher

 

@frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {

    int32_t keyCode = args->keyCode;
    KeyEvent event;
    event.initialize(args->deviceId, args->source, args->action,
            flags, keyCode, args->scanCode, metaState, 0,
            args->downTime, args->eventTime);
    //mPolicy是指NativeInputManager对象
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);   //2.3.2.1 interceptKeyBeforeQueueing

    bool needWake;
    { // acquire lock
        mLock.lock();

        if (shouldSendKeyToInputFilterLocked(args)) {
            mLock.unlock();

            policyFlags |= POLICY_FLAG_FILTERED;
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {  //2.3.2.2 当inputEventObj不为空, 则事件被filter所拦截
                return; // event was consumed by the filter
            }

            mLock.lock();
        }

        int32_t repeatCount = 0;
        KeyEntry* newEntry = new KeyEntry(args->eventTime,   //KeyEntry
                args->deviceId, args->source, policyFlags,
                args->action, flags, keyCode, args->scanCode,
                metaState, repeatCount, args->downTime);

        needWake = enqueueInboundEventLocked(newEntry);    //2.3.2.3 放入mInboundQueue
        mLock.unlock();
    } // release lock

    if (needWake) {
        mLooper->wake();  //2.3.2.4 唤醒 InputDispatcher
    }
}

调用NativeInputManager.interceptKeyBeforeQueueing,加入队列前执行拦截动作,但并不改变流程,调用链:

IMS.interceptKeyBeforeQueueing

InputMonitor.interceptKeyBeforeQueueing (继承IMS.WindowManagerCallbacks)

PhoneWindowManager.interceptKeyBeforeQueueing (继承WindowManagerPolicy)

当mInputFilterEnabled=true(该值默认为false,可通过setInputFilterEnabled设置),则调用NativeInputManager.filterInputEvent过滤输入事件;

当返回值为false则过滤该事件,不再往下分发;

生成KeyEvent,并调用enqueueInboundEventLocked,将该事件加入到InputDispatcherd的成员变量mInboundQueue。

 

2.3.2.1 interceptKeyBeforeQueueing

//mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); mpolicy是InputDispatcherPolicyInterface

 

sp mPolicy;
class InputDispatcherPolicyInterface : public virtual RefBase {
public:

    virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) = 0;

     * This method is expected to set the POLICY_FLAG_PASS_TO_USER policy flag if the event
     * should be dispatched to applications.
     */
    virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags) = 0;

//NativeInputManager 初始化InputManager传入的this,就是InputManager中的dispatcherPolicy

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);
...
    sp eventHub = new EventHub();   //create EventHub
    mInputManager = new InputManager(eventHub, this, this);
}

@frameworks/native/services/inputflinger/InputManager.cpp

InputManager::InputManager(
        const sp& eventHub,
        const sp& readerPolicy,
        const sp& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);   //初始化InputDispatcher
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);   //初始化InputReader
    initialize();
}

//InputDispatcher初始化就赋值 policy 为mPolicy

 

InputDispatcher::InputDispatcher(const sp& policy) :
    mPolicy(policy),  //赋值
    ...
    policy->getDispatcherConfiguration(&mConfig);
}

@frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
        uint32_t& policyFlags) {

    bool interactive = mInteractive.load();
    if (interactive) {
        policyFlags |= POLICY_FLAG_INTERACTIVE;
    }
    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
        nsecs_t when = keyEvent->getEventTime();
        JNIEnv* env = jniEnv();
        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
        jint wmActions;
        if (keyEventObj) {
            wmActions = env->CallIntMethod(mServiceObj,
                    gServiceClassInfo.interceptKeyBeforeQueueing,
                    keyEventObj, policyFlags);
            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
                wmActions = 0;
            }
            android_view_KeyEvent_recycle(env, keyEventObj);
            env->DeleteLocalRef(keyEventObj);
        } else {

        }

        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
    } else {
        if (interactive) {
            policyFlags |= POLICY_FLAG_PASS_TO_USER;
        }
    }
}

//calss InputManagerService method:interceptKeyBeforeQueueing

int register_android_server_InputManager(JNIEnv* env) {
    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
            gInputManagerMethods, NELEM(gInputManagerMethods));
    jclass clazz;
    FIND_CLASS(clazz, "com/android/server/input/InputManagerService");

    GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
            "filterInputEvent", "(Landroid/view/InputEvent;I)Z");

    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");

InputManagerService中的WindowManagerCallbacks是接口 implements InputManagerService.WindowManagerCallbacks

@frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

 

// Native callback.
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
    return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}

public interface WindowManagerCallbacks {
    ...
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
    public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
    public long interceptKeyBeforeDispatching(InputWindowHandle focus,
}

public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
    mWindowManagerCallbacks = callbacks;
}

startOtherServices初始化传入的InputMonitor

 

private void startOtherServices() {
    inputManager = new InputManagerService(context);   //初始化InputManagerService

    wm = WindowManagerService.main(context, inputManager,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
            !mFirstBoot, mOnlyCore, new PhoneWindowManager());
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);  //可以通过IInputManager来binder调用InputManagerService方法
    inputManager.setWindowManagerCallbacks(wm.getInputMonitor());   //setWindowManagerCallbacks
    inputManager.start();  //start inputmanager
}

得到的就是wms的mInputMonitor

@frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public InputMonitor getInputMonitor() {
    return mInputMonitor;
}

//使用WindowManagerPolicy的interceptKeyBeforeQueueing

@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
//使用WindowManagerPolicy的interceptKeyBeforeQueueing
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {   //implements WindowManagerCallbacks
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
    }
}

看谁使用的WindowManagerPolicy接口

 

private final WindowManagerService mService;
final WindowManagerPolicy mPolicy;

@frameworks/base/core/java/android/view/WindowManagerPolicy.java
public interface WindowManagerPolicy {
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
}

PhoneWindowManager是接口WindowManagerPolicy

事件处理和拦截主要在这里,包括POWER灭屏,声音,语言助手,camera,BACK键之类的处理

 

public class PhoneWindowManager implements WindowManagerPolicy {

//可以看下policyFlags这个参数 
   @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
        final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
        final boolean canceled = event.isCanceled();
        final int keyCode = event.getKeyCode();

        boolean useHapticFeedback = down
                && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
                && event.getRepeatCount() == 0;

        // Handle special keys.
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK: {   //返回键
                if (down) {
                    interceptBackKeyDown();
                } else {
                    boolean handled = interceptBackKeyUp(event);

                    // Don't pass back press to app if we've already handled it via long press
                    if (handled) {
                        result &= ~ACTION_PASS_TO_USER;
                    }
                }
                break;
            }

            case KeyEvent.KEYCODE_VOLUME_DOWN:
            case KeyEvent.KEYCODE_VOLUME_UP:
            case KeyEvent.KEYCODE_VOLUME_MUTE: {
                break;
            }
            case KeyEvent.KEYCODE_POWER: {  //POWER键行为控制
                // Any activity on the power button stops the accessibility shortcut
                cancelPendingAccessibilityShortcutAction();
                result &= ~ACTION_PASS_TO_USER;   //看起来~ACTION_PASS_TO_USER是表示拦截事件
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    interceptPowerKeyDown(event, interactive);
                } else {
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }

            //看起来像是导航栏上的事件
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT:
                // fall through
            case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: {
                result &= ~ACTION_PASS_TO_USER;
                interceptSystemNavigationKey(event);
                break;
            }

            case KeyEvent.KEYCODE_SLEEP: {
                break;
            }
            case KeyEvent.KEYCODE_MEDIA_PLAY:
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
            case KeyEvent.KEYCODE_HEADSETHOOK:
            case KeyEvent.KEYCODE_MUTE:
            case KeyEvent.KEYCODE_MEDIA_STOP:
            case KeyEvent.KEYCODE_MEDIA_NEXT:
                ...
            case KeyEvent.KEYCODE_CALL: {
                break;
            }
            case KeyEvent.KEYCODE_VOICE_ASSIST: {   //看起来是唤醒语音助手
                    Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
                            keyguardActive ? 1 : 0, 0);
                break;
            }

        if (useHapticFeedback) {   //震动反馈
            performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
        }
        if (isWakeKey) {
            wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
        }
        return result;
    }
    
    //经过一系列判断后,调用vibrate实现振动
    public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
        mVibrator.vibrate(owningUid, owningPackage, effect, VIBRATION_ATTRIBUTES);
        return true;
    }

}

2.3.2.2 filterInputEvent

//return false才会拦截事件,return true正常分发事件

 

bool NativeInputManager::filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) {
    ATRACE_CALL();
    jobject inputEventObj;

    JNIEnv* env = jniEnv();
    switch (inputEvent->getType()) {
    case AINPUT_EVENT_TYPE_KEY:
        inputEventObj = android_view_KeyEvent_fromNative(env,
                static_cast(inputEvent));
        break;
    case AINPUT_EVENT_TYPE_MOTION:
        inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                static_cast(inputEvent));
        break;
    default:
        return true; // dispatch the event normally
    }

    if (!inputEventObj) {
        ALOGE("Failed to obtain input event object for filterInputEvent.");
        return true; // dispatch the event normally
    }

    // The callee is responsible for recycling the event.
    jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
            inputEventObj, policyFlags);
    if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
        pass = true;
    }
    env->DeleteLocalRef(inputEventObj);
    return pass;
}

@frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

/ Native callback.
final boolean filterInputEvent(InputEvent event, int policyFlags) {
    synchronized (mInputFilterLock) {
        if (mInputFilter != null) {   //mInputFilter != null拦截
            try {
                mInputFilter.filterInputEvent(event, policyFlags);
            } catch (RemoteException e) {
                /* ignore */
            }
            return false;  //拦截
        }
    }
    event.recycle();
    return true;
}

final public void filterInputEvent(InputEvent event, int policyFlags) {
    mH.obtainMessage(MSG_INPUT_EVENT, policyFlags, 0, event).sendToTarget();
}

2.3.2.3 enqueueInboundEventLocked放入mInboundQueue

3处理逻辑如下, 把event放入到mInboundQueue后,mLooper->wake()唤醒dispatcher线程

 

KeyEntry* newEntry = new KeyEntry(args->eventTime,   //KeyEntry
        args->deviceId, args->source, policyFlags,
        args->action, flags, keyCode, args->scanCode,
        metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);    //放入mInboundQueue

//唤醒InputDispatcher线程
if (needWake) {
    mLooper->wake();
}

enqueueInboundEventLocked把事件放入InboundQueue中

@frameworks/native/services/inputflinger/InputDispatcher.cpp

 

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    mInboundQueue.enqueueAtTail(entry);   //入queue
    traceInboundQueueLengthLocked();

    switch (entry->type) {
    case EventEntry::TYPE_KEY: {
        // Optimize app switch latency.
        // If the application takes too long to catch up then we drop all events preceding
        // the app switch key.
        KeyEntry* keyEntry = static_cast(entry);
        if (isAppSwitchKeyEventLocked(keyEntry)) {
            if (keyEntry->action == AKEY_EVENT_ACTION_DOWN) {
                mAppSwitchSawKeyDown = true;
            } else if (keyEntry->action == AKEY_EVENT_ACTION_UP) {
                if (mAppSwitchSawKeyDown) {
                    mAppSwitchDueTime = keyEntry->eventTime + APP_SWITCH_TIMEOUT;
                    mAppSwitchSawKeyDown = false;
                    needWake = true;
                }
            }
        }
        break;
    }

    case EventEntry::TYPE_MOTION: {
    }

    return needWake;
}

2.3.2.4 mLooper::wake

 

你可能感兴趣的:(Input)