Event处理参考代码2_3

WindowManagerService.java

WindowManagerService

private WindowManagerService(Context context, PowerManagerService pm,
            boolean haveInputMethods) {
    ......
    final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();

    ......
    mInputManager = new InputManager(context, this);

    ......
    mInputManager.start();
}

WindowManagerService.InputMonitor.interceptKeyBeforeQueueing

public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
                int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
    return mPolicy.interceptKeyBeforeQueueing(whenNanos, action, flags,
            keyCode, scanCode, policyFlags, isScreenOn);
}

InputManager.java

InputManager

// 包裹了C++层的InputManager并提供Callbacks回调
public class InputManager {
    ...... 
    private static native void nativeInit(Callbacks callbacks);
    private static native void nativeStart();
    private static native void nativeSetDisplaySize(int displayId, int width, int height);
    private static native void nativeSetDisplayOrientation(int displayId, int rotation);
    
    private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
            int scanCode);
    private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
            int keyCode);
    private static native int nativeGetSwitchState(int deviceId, int sourceMask,
            int sw);
    ......

    private class Callbacks {
       ...... 
    }
 

InputManager.Callbacks

private class Callbacks {
    ......

    @SuppressWarnings("unused")
    public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
            int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
        return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
                whenNanos, action, flags, keyCode, scanCode, policyFlags, isScreenOn);
    }
}

com_android_server_InputManager.cpp

NativeInputManager

class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface {
    ......
    
public:
    ......
    virtual status_t start();
    virtual status_t stop();

    virtual sp<InputReaderInterface> getReader();
    virtual sp<InputDispatcherInterface> getDispatcher();

private:
    sp<InputReaderInterface> mReader;
    sp<InputReaderThread> mReaderThread;

    sp<InputDispatcherInterface> mDispatcher;
    sp<InputDispatcherThread> mDispatcherThread;
}

NativeInputManager::NativeInputManager

NativeInputManager::NativeInputManager(jobject callbacksObj) :
    mFilterTouchEvents(-1), mFilterJumpyTouchEvents(-1), mVirtualKeyQuietTime(-1),
    mMaxEventsPerSecond(-1),
    mDisplayWidth(-1), mDisplayHeight(-1), mDisplayOrientation(ROTATION_0) {
    
    // 设置回调
    mCallbacksObj = env->NewGlobalRef(callbacksObj);
    // 初始化EventHub
    sp<EventHub> eventHub = new EventHub();
    // 初始化InputManager
    mInputManager = new InputManager(eventHub, this, this);
}

NativeInputManager::registerInputChannel

status_t NativeInputManager::registerInputChannel(JNIEnv* env,
        const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
    ......
    status = mInputManager->getDispatcher()->registerInputChannel(inputChannel, monitor);
    if (! status) {
        return OK;
    }
    ......
}

android_view_InputChannel.cpp

android_view_InputChannel_nativeOpenInputChannelPair

static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(JNIEnv* env,
        jclass clazz, jstring nameObj) {
    ......
    sp<InputChannel> serverChannel;
    sp<InputChannel> clientChannel;
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);

    ......
    // TODO more robust error checking
    jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
            new NativeInputChannel(serverChannel));
    jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
            new NativeInputChannel(clientChannel));
    ......
    return channelPair;
}

InputTransport.cpp

InputChannel::openInputChannelPair

status_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    ......
    int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
    if (serverAshmemFd < 0) {
        ......
    } else {
        result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
        if (result < 0) {
            ......
        } else {
            int clientAshmemFd;
            clientAshmemFd = dup(serverAshmemFd);
            if (clientAshmemFd < 0) {
                ......
            } else {
                int forward[2];
                if (pipe(forward)) {
                    ......
                } else {
                    int reverse[2];
                    if (pipe(reverse)) {
                        ......
                    } else {
                        String8 serverChannelName = name;
                        serverChannelName.append(" (server)");
                        outServerChannel = new InputChannel(serverChannelName,
                                serverAshmemFd, reverse[0], forward[1]);

                        String8 clientChannelName = name;
                        clientChannelName.append(" (client)");
                        outClientChannel = new InputChannel(clientChannelName,
                                clientAshmemFd, forward[0], reverse[1]);
                        return OK;
                    }
                    ::close(forward[0]);
                    ::close(forward[1]);
                }
                ::close(clientAshmemFd);
            }
        }
        ::close(serverAshmemFd);
    }
    
    ......
    return result;
}

android_view_InputQueue.cpp

status_t NativeInputQueue::registerInputChannel(JNIEnv* env, jobject inputChannelObj,
        jobject inputHandlerObj, jobject messageQueueObj) {
    sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
            inputChannelObj);
    ......

    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);

    { // acquire lock
        AutoMutex _l(mLock);

        ......
        sp<Connection> connection = new Connection(connectionId, inputChannel, looper);
        status_t result = connection->inputConsumer.initialize();
        ......

        connection->inputHandlerObjGlobal = env->NewGlobalRef(inputHandlerObj);
        
        .....
        looper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock
    
    ......
    return OK;
}

NativeInputQueue::handleReceiveCallback

int NativeInputQueue::handleReceiveCallback(int receiveFd, int events, void* data) {
    ......
    { // acquire lock
        AutoMutex _l(q->mLock);

        ssize_t connectionIndex = q->mConnectionsByReceiveFd.indexOfKey(receiveFd);
        ......

        connection = q->mConnectionsByReceiveFd.valueAt(connectionIndex);
        ......

        status_t status = connection->inputConsumer.receiveDispatchSignal();
        ......

        status = connection->inputConsumer.consume(& connection->inputEventFactory, & inputEvent);
        ......

        finishedToken = generateFinishedToken(receiveFd, connection->id, connection->messageSeqNum);
        ......

        inputHandlerObjLocal = env->NewLocalRef(connection->inputHandlerObjGlobal);
    } // release lock

    ......
    switch (inputEventType) {
    case AINPUT_EVENT_TYPE_KEY:
        inputEventObj = android_view_KeyEvent_fromNative(env,
                static_cast<KeyEvent*>(inputEvent));
        // 调用java层的dispatchKeyEvent方法
        dispatchMethodId = gInputQueueClassInfo.dispatchKeyEvent;
        break;

    case AINPUT_EVENT_TYPE_MOTION:
        inputEventObj = android_view_MotionEvent_fromNative(env,
                static_cast<MotionEvent*>(inputEvent));
        // 调用java层的dispatchMotionEvent方法
        dispatchMethodId = gInputQueueClassInfo.dispatchMotionEvent;
        break;

    default:
        assert(false); // InputConsumer should prevent this from ever happening
        inputEventObj = NULL;
    }

    ......
    env->CallStaticVoidMethod(gInputQueueClassInfo.clazz,
            dispatchMethodId, inputHandlerObjLocal, inputEventObj,
            jlong(finishedToken));

    ......
    return 1;
}

InputManager.cpp

InputManager::InputManager

InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

InputManager::start

status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    ......
    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    ......

    return OK;
}

InputManager::stop

status_t InputManager::stop() {
    status_t result = mReaderThread->requestExitAndWait();
    ......
    result = mDispatcherThread->requestExitAndWait();
    ......

    return OK;
}

InputReader.h

InputReader

class InputReader : public InputReaderInterface, protected InputReaderContext {
public:
    InputReader(const sp<EventHubInterface>& eventHub,
            const sp<InputReaderPolicyInterface>& policy,
            const sp<InputDispatcherInterface>& dispatcher);
            
    ......
    virtual void loopOnce();
    
private:
    sp<EventHubInterface> mEventHub;
    sp<InputReaderPolicyInterface> mPolicy;
    sp<InputDispatcherInterface> mDispatcher;
    ......
}

InputReader.cpp

InputReader::loopOnce

void InputReader::loopOnce() {
    RawEvent rawEvent;
    mEventHub->getEvent(& rawEvent);

#if DEBUG_RAW_EVENTS
    LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
            rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
            rawEvent.value);
#endif

    process(& rawEvent);
}

InputReader::process

void InputReader::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EventHubInterface::DEVICE_ADDED:
        addDevice(rawEvent->deviceId);
        break;

    case EventHubInterface::DEVICE_REMOVED:
        removeDevice(rawEvent->deviceId);
        break;

    case EventHubInterface::FINISHED_DEVICE_SCAN:
        handleConfigurationChanged(rawEvent->when);
        break;

    default:
        consumeEvent(rawEvent);
        break;
    }
}

InputReader::consumeEvent

void InputReader::consumeEvent(const RawEvent* rawEvent) {
    int32_t deviceId = rawEvent->deviceId;
    { // acquire device registry reader lock
        RWLock::AutoRLock _rl(mDeviceRegistryLock);

        ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
        if (deviceIndex < 0) {
            return;
        }

        InputDevice* device = mDevices.valueAt(deviceIndex);
        if (device->isIgnored()) {
            return;
        }

        device->process(rawEvent);
    } // release device registry reader lock
}

InputDevice::process

void InputDevice::process(const RawEvent* rawEvent) {
    size_t numMappers = mMappers.size();
    for (size_t i = 0; i < numMappers; i++) {
        InputMapper* mapper = mMappers[i];
        mapper->process(rawEvent);
    }
}

KeyboardInputMapper.cpp

KeyboardInputMapper::processKey

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {
    int32_t newMetaState;
    nsecs_t downTime;
    bool metaStateChanged = false;

    { // acquire lock
        AutoMutex _l(mLock);

        if (down) {
            // Rotate key codes according to orientation if needed.
            // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
            ......
            if (! getPolicy()->getDisplayInfo(mAssociatedDisplayId, NULL, NULL, & orientation)) {
                return;
            }

            // Add key down.KeyboardInputMapper::processKey
            ssize_t keyDownIndex = findKeyDownLocked(scanCode);
            if (keyDownIndex >= 0) {
                // key repeat, be sure to use same keycode as before in case of rotation
                keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
            } else {
                // key down
                ......
            }
        } else {
            // Remove key down.
        }
        
        ......
    } // release lock

    // 通过InputDispatcher分发事件
    getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
}

InputDispatcher.cpp

InputDispatcher::registerInputChannel

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
    { // acquire lock
        AutoMutex _l(mLock);

        sp<Connection> connection = new Connection(inputChannel);
        status_t status = connection->initialize();
        ......

        int32_t receiveFd = inputChannel->getReceivePipeFd();
        mConnectionsByReceiveFd.add(receiveFd, connection);

        if (monitor) {
            mMonitoringChannels.push(inputChannel);
        }

        mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);

        runCommandsLockedInterruptible();
    } // release lock
    return OK;
}

InputDispatcher::notifyKey

void InputDispatcher::notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
        uint32_t policyFlags, int32_t action, int32_t flags,
        int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime) {
    // 检验Key是否合法
    if (! validateKeyEvent(action)) {
        return;
    }

    // 系统预处理
    policyFlags |= POLICY_FLAG_TRUSTED;
    mPolicy->interceptKeyBeforeQueueing(eventTime, deviceId, action, /*byref*/ flags,
            keyCode, scanCode, /*byref*/ policyFlags);

    // 加入事件队列
    bool needWake;
    { // acquire lock
        AutoMutex _l(mLock);

        int32_t repeatCount = 0;
        KeyEntry* newEntry = mAllocator.obtainKeyEntry(eventTime,
                deviceId, source, policyFlags, action, flags, keyCode, scanCode,
                metaState, repeatCount, downTime);

        needWake = enqueueInboundEventLocked(newEntry);
    } // release lock

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

InputTransport.cpp

InputChannel::openInputChannelPair

status_t InputChannel::openInputChannelPair(const String8& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
    status_t result;

    int serverAshmemFd = ashmem_create_region(name.string(), DEFAULT_MESSAGE_BUFFER_SIZE);
    if (serverAshmemFd < 0) {
        result = -errno;
    } else {
        result = ashmem_set_prot_region(serverAshmemFd, PROT_READ | PROT_WRITE);
        if (result < 0) {
            ......
        } else {
            // Dup the file descriptor because the server and client input channel objects that
            // are returned may have different lifetimes but they share the same shared memory region.
            int clientAshmemFd;
            clientAshmemFd = dup(serverAshmemFd);
            if (clientAshmemFd < 0) {
                result = -errno;
            } else {
                int forward[2];
                if (pipe(forward)) {
                    result = -errno;
                } else {
                    int reverse[2];
                    if (pipe(reverse)) {
                        result = -errno;
                    } else {
                        String8 serverChannelName = name;
                        serverChannelName.append(" (server)");
                        outServerChannel = new InputChannel(serverChannelName,
                                serverAshmemFd, reverse[0], forward[1]);

                        String8 clientChannelName = name;
                        clientChannelName.append(" (client)");
                        outClientChannel = new InputChannel(clientChannelName,
                                clientAshmemFd, forward[0], reverse[1]);
                        return OK;
                    }
                    ::close(forward[0]);
                    ::close(forward[1]);
                }
                ::close(clientAshmemFd);
            }
        }
        ::close(serverAshmemFd);
    }

    outServerChannel.clear();
    outClientChannel.clear();
    return result;
}

PhoneWindowManager.java

updateSettings

public void updateSettings() {
    if (mPointerLocationInputChannel == null) {
        try {
            mPointerLocationInputChannel =
                mWindowManager.monitorInput("PointerLocationView");
            InputQueue.registerInputChannel(mPointerLocationInputChannel,
                    mPointerLocationInputHandler, mHandler.getLooper().getQueue());
        } catch (RemoteException ex) {
        }
    }
}

interceptKeyBeforeQueueing

public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
            int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
    ......
    // If screen is off then we treat the case where the keyguard is open but hidden
    // the same as if it were open and in front.
    // This will prevent any keys other than the power button from waking the screen
    // when the keyguard is hidden by another activity.
    final boolean keyguardActive = (isScreenOn ?
                                    mKeyguardMediator.isShowingAndNotHidden() :
                                    mKeyguardMediator.isShowing());

    ......
    if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
        performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
    }

    // Basic policy based on screen state and keyguard.
    // FIXME: This policy isn't quite correct.  We shouldn't care whether the screen
    //        is on or off, really.  We should care about whether the device is in an
    //        interactive state or is in suspend pretending to be "off".
    //        The primary screen might be turned off due to proximity sensor or
    //        because we are presenting media on an auxiliary screen or remotely controlling
    //        the device some other way (which is why we have an exemption here for injected
    //        events).
    int result;
    if (isScreenOn || isInjected) {
        // When the screen is on or if the key is injected pass the key to the application.
        ......
    } else {
        // When the screen is off and the key is not injected, determine whether
        // to wake the device but don't pass the key to the application.
        ......
    }

    // Handle special keys.
    switch (keyCode) {
        case KeyEvent.KEYCODE_VOLUME_DOWN:
        case KeyEvent.KEYCODE_VOLUME_UP: {
            ......
            break;
        }

        case KeyEvent.KEYCODE_ENDCALL: {
            ......
            break;
        }

        case KeyEvent.KEYCODE_POWER: {
            ......
            break;
        }

        case KeyEvent.KEYCODE_HEADSETHOOK:
        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
        case KeyEvent.KEYCODE_MEDIA_STOP:
        case KeyEvent.KEYCODE_MEDIA_NEXT:
        case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
        case KeyEvent.KEYCODE_MEDIA_REWIND:
        case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
            ......
            break;
        }

        case KeyEvent.KEYCODE_CALL: {
            ......
            break;
        }
    }
    return result;
}

Looper.h

Looper

class Looper : public ALooper, public RefBase {
    ......
    void wake();
    int addFd(int fd, int ident, int events, ALooper_callbackFunc callback, void* data);
    int removeFd(int fd);

private:
    struct Request {
        int fd;
        int ident;
        ALooper_callbackFunc callback;
        void* data;
    };

    struct Response {
        int events;
        Request request;
    };
    
    ......
}

Looper.cpp

Looper::Looper

Looper::Looper(bool allowNonCallbacks) :
        mAllowNonCallbacks(allowNonCallbacks),
        mResponseIndex(0) {
    int wakeFds[2];
    int result = pipe(wakeFds);

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];
    ......
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    ......
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);

#ifdef LOOPER_USES_EPOLL
    // Allocate the epoll instance and register the wake pipe.
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);

    struct epoll_event eventItem;
    memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union
    eventItem.events = EPOLLIN;
    eventItem.data.fd = mWakeReadPipeFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem);
#else
    ......
#endif
}

Looper::pollOnce

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        ......
        result = pollInner(timeoutMillis);
    }
}

Looper::pollInner

int Looper::pollInner(int timeoutMillis) {
    ......
    // epoll模式监听事件
#ifdef LOOPER_USES_EPOLL
    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
    bool acquiredLock = false;
#else
    ......
#endif

    if (eventCount < 0) {
        if (errno == EINTR) {
            goto Done;
        }

        result = ALOOPER_POLL_ERROR;
        goto Done;
    }

    if (eventCount == 0) {
        result = ALOOPER_POLL_TIMEOUT;
        goto Done;
    }

    // push相应的应答对象
#ifdef LOOPER_USES_EPOLL
    for (int i = 0; i < eventCount; i++) {
        int fd = eventItems[i].data.fd;
        uint32_t epollEvents = eventItems[i].events;
        if (fd == mWakeReadPipeFd) {
            if (epollEvents & EPOLLIN) {
                awoken();
            } else {
            }
        } else {
            if (! acquiredLock) {
                mLock.lock();
                acquiredLock = true;
            }

            ssize_t requestIndex = mRequests.indexOfKey(fd);
            if (requestIndex >= 0) {
                int events = 0;
                if (epollEvents & EPOLLIN) events |= ALOOPER_EVENT_INPUT;
                if (epollEvents & EPOLLOUT) events |= ALOOPER_EVENT_OUTPUT;
                if (epollEvents & EPOLLERR) events |= ALOOPER_EVENT_ERROR;
                if (epollEvents & EPOLLHUP) events |= ALOOPER_EVENT_HANGUP;
                pushResponse(events, mRequests.valueAt(requestIndex));
            } else {
            }
        }
    }
    if (acquiredLock) {
        mLock.unlock();
    }
Done: ;
#else
    ......
#endif
    ......
    // 循环调用注册的callback方法
    for (size_t i = 0; i < mResponses.size(); i++) {
        const Response& response = mResponses.itemAt(i);
        if (response.request.callback) {
            int callbackResult = response.request.callback(
                    response.request.fd, response.events, response.request.data);
            if (callbackResult == 0) {
                removeFd(response.request.fd);
            }

            result = ALOOPER_POLL_CALLBACK;
        }
    }
    return result;
}