应用程序请求注册对Input事件的监听

来源:互联网 发布:java方法签名 异常 编辑:程序博客网 时间:2024/06/01 09:19

一、应用程序在绘制View时注册监听事件

[/frameworks/base/core/java/android/view/ViewRootImpl.java]public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {    synchronized (this) {        if (mView == null) {            mView = view;            ...            requestLayout();            //创建InputChannel实例,创建后的InputChannel是未初始化的,可以通过从Parcel对象中读取信息初始化            //或者调用transferTo(InputChannel outParameter)从另一个InputChannel实例中获取初始化信息。            if ((mWindowAttributes.inputFeatures &                       WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {                mInputChannel = new InputChannel();            }            try {                ...                //addToDisplay()方法会调用WindowManagerService的addWindow()方法。                res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(),mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,mAttachInfo.mOutsets, mInputChannel);            } catch (RemoteException e) {                ...                mView = null;                mInputChannel = null;                ...                throw new RuntimeException("Adding window failed", e);            } finally {                ...            }            if (mInputChannel != null) {                if (mInputQueueCallback != null) {                    mInputQueue = new InputQueue();                    mInputQueueCallback.onInputQueueCreated(mInputQueue);                }                //创建WindowInputEventReceiver实例,使用前面创建好的InputChannel实例作参数。                mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,                        Looper.myLooper());            }        }    }}

Session类的addToDisplay()方法会调用WindowManagerService的addWindow()方法,这个方法非常重要。

[/frameworks/base/services/java/com/android/server/wm/WindowManagerService.java]public int addWindow(Session session, IWindow client, int seq,        WindowManager.LayoutParams attrs, int viewVisibility, int displayId,        Rect outContentInsets, Rect outStableInsets, Rect outOutsets,        InputChannel outInputChannel) {    ...    synchronized(mWindowMap) {        ...        if (outInputChannel != null && (attrs.inputFeatures                & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {            String name = win.makeInputChannelName();            //创建名为name的socketpair实例,将socket[0](服务端)注册到InputManagerService中,            //将socket[1](客户端)传递给应用进程。            InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);            win.setInputChannel(inputChannels[0]);            inputChannels[1].transferTo(outInputChannel);            mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);        }    }//synchronized    return res;}

二、InputManagerService对socketpair服务端的处理

2.1 InputManagerService的初始化和启动

public InputManagerService(Context context) {    this.mContext = context;    //InputManagerService的Handler使用的是DisplayThread的Looper。    this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());    mUseDevInputEventForAudioJack =            context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);    //在native层完成初始化, nativeInit()返回的是JNI层创建的NativeInputManager对象的指针。Java层保存Native的对象指针,这个是Android中非常常见的用法。    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());    LocalServices.addService(InputManagerInternal.class, new LocalService());}

[com_android_server_input_InputManagerService.cpp]
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, “MessageQueue is not initialized.”);
return 0;
}

//new一个NativeInputManager实例,NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());im->incStrong(0);return reinterpret_cast<jlong>(im);

}

NativeInputManager类

NativeInputManager类的设计

class NativeInputManager : public virtual RefBase,    public virtual InputReaderPolicyInterface,    public virtual InputDispatcherPolicyInterface,    public virtual PointerControllerPolicyInterface {protected:    virtual ~NativeInputManager();public:    NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper);    inline sp<InputManager> getInputManager() const { return mInputManager; }    status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,            const sp<InputWindowHandle>& inputWindowHandle, bool monitor);    status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);    ...private:    sp<InputManager> mInputManager;    jobject mContextObj;    jobject mServiceObj;    sp<Looper> mLooper;}

NativeInputManager的构造函数

NativeInputManager::NativeInputManager(jobject contextObj,    jobject serviceObj, const sp<Looper>& looper) :    mLooper(looper), mInteractive(true) {    JNIEnv* env = jniEnv();    mContextObj = env->NewGlobalRef(contextObj);    mServiceObj = env->NewGlobalRef(serviceObj);    {        AutoMutex _l(mLock);        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;        mLocked.pointerSpeed = 0;        mLocked.pointerGesturesEnabled = true;        mLocked.showTouches = false;    }    mInteractive = true;    sp<EventHub> eventHub = new EventHub();    mInputManager = new InputManager(eventHub, this, this);}

“`

“`####InputManagerService的启动####
主要的工作是把Native层的InputReaderThread和InputDispatcherThread两个线程启动起来。

public void start() {    //在native层启动    nativeStart(mPtr);    // Add ourself to the Watchdog monitors.    Watchdog.getInstance().addMonitor(this);    registerPointerSpeedSettingObserver();    registerShowTouchesSettingObserver();    mContext.registerReceiver(new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            updatePointerSpeedFromSettings();            updateShowTouchesFromSettings();        }    }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);    updatePointerSpeedFromSettings();    updateShowTouchesFromSettings();}

com_android_server_input_InputManagerService.cpp

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);    status_t result = im->getInputManager()->start();    if (result) {        jniThrowRuntimeException(env, "Input manager could not be started.");    }}

InputManager的设计

接口:

class InputManagerInterface : public virtual RefBase {protected:    InputManagerInterface() { }    virtual ~InputManagerInterface() { }public:    /* Starts the input manager threads. */    virtual status_t start() = 0;    /* Stops the input manager threads and waits for them to exit. */    virtual status_t stop() = 0;    /* Gets the input reader. */    virtual sp<InputReaderInterface> getReader() = 0;    /* Gets the input dispatcher. */    virtual sp<InputDispatcherInterface> getDispatcher() = 0;};

具体类:

class InputManager : public InputManagerInterface {protected:    virtual ~InputManager();public:    InputManager(            const sp<EventHubInterface>& eventHub,            const sp<InputReaderPolicyInterface>& readerPolicy,            const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);    // (used for testing purposes)    InputManager(            const sp<InputReaderInterface>& reader,            const sp<InputDispatcherInterface>& dispatcher);    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;    void initialize();};

socketpair服务端的注册

最终调用的是InputDispatcher的registerInputChannel()函数。

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,         const sp<InputWindowHandle>& inputWindowHandle, bool monitor);
  1. 以socketFd作为索引,将Connection实例添加到:KeyedVector

InputDispatcher的分发线程

分发流程:
1. 轮询mCommandQueue;
2. 轮询mLooper。
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();

        //如果队列mCommandQueue不为空,则调用dispatchOnceInnerLocked()函数进行分发。        if (!haveCommandsLocked()) {            dispatchOnceInnerLocked(&nextWakeupTime);        }        if (runCommandsLockedInterruptible()) {            nextWakeupTime = LONG_LONG_MIN;        }    } // release lock    nsecs_t currentTime = now();    int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);    mLooper->pollOnce(timeoutMillis);}bool InputDispatcher::runCommandsLockedInterruptible() {    //如果队列mCommandQueue为空,直接返回flase。    if (mCommandQueue.isEmpty()) {        return false;    }    do {        //依次从队列mCommandQueue中出列一个元素,调用command()函数,直到队列为空为止,返回true。        CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();        Command command = commandEntry->command;        (this->*command)(commandEntry);        commandEntry->connection.clear();        delete commandEntry;    } while (! mCommandQueue.isEmpty());    return true;}

三、应用程序对SocketPair客户端事件的处理

3.1 Native层的InputEventReceiver的设计

    [/frameworks/base/core/jni/android_view_InputEventReceiver.cpp]    class NativeInputEventReceiver : public LooperCallback {    public:        NativeInputEventReceiver(JNIEnv* env,                jobject receiverWeak, const sp<InputChannel>& inputChannel,                const sp<MessageQueue>& messageQueue);        status_t initialize();        void dispose();        status_t finishInputEvent(uint32_t seq, bool handled);        status_t consumeEvents(JNIEnv* env, bool consumeBatches, nsecs_t frameTime,                bool* outConsumedBatch);    protected:        virtual ~NativeInputEventReceiver();    private:        struct Finish {            uint32_t seq;            bool handled;        };        jobject mReceiverWeakGlobal;        InputConsumer mInputConsumer;        sp<MessageQueue> mMessageQueue;        PreallocatedInputEventFactory mInputEventFactory;        bool mBatchedInputEventPending;        int mFdEvents;        Vector<Finish> mFinishQueue;        void setFdEvents(int events);        const char* getInputChannelName() {            return mInputConsumer.getChannel()->getName().string();        }        virtual int handleEvent(int receiveFd, int events, void* data);    };status_t NativeInputEventReceiver::initialize() {        //监听类型为ALOOPER_EVENT_INPUT        setFdEvents(ALOOPER_EVENT_INPUT);        return OK;    }    //NativeInputEventReceiver继承自LooperCallback,有事件发生时会回调handleEvent()函数。    void NativeInputEventReceiver::setFdEvents(int events) {        if (mFdEvents != events) {            mFdEvents = events;            int fd = mInputConsumer.getChannel()->getFd();            if (events) {                mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);            } else {                mMessageQueue->getLooper()->removeFd(fd);            }        }    }    int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {        if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {            return 0; // remove the callback        }        if (events & ALOOPER_EVENT_INPUT) {            JNIEnv* env = AndroidRuntime::getJNIEnv();            status_t status = consumeEvents(env, false /*consumeBatches*/, -1, NULL);            mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");            return status == OK || status == NO_MEMORY ? 1 : 0;        }        if (events & ALOOPER_EVENT_OUTPUT) {            for (size_t i = 0; i < mFinishQueue.size(); i++) {                const Finish& finish = mFinishQueue.itemAt(i);                status_t status = mInputConsumer.sendFinishedSignal(finish.seq, finish.handled);                if (status) {                    mFinishQueue.removeItemsAt(0, i);                    if (status == WOULD_BLOCK) {                        return 1; // keep the callback, try again later                    }                    ALOGW("Failed to send finished signal on channel '%s'.  status=%d",                            getInputChannelName(), status);                    if (status != DEAD_OBJECT) {                        JNIEnv* env = AndroidRuntime::getJNIEnv();                        String8 message;                        message.appendFormat("Failed to finish input event.  status=%d", status);                        jniThrowRuntimeException(env, message.string());                        mMessageQueue->raiseAndClearException(env, "finishInputEvent");                    }                    return 0; // remove the callback                }            }            mFinishQueue.clear();            setFdEvents(ALOOPER_EVENT_INPUT);            return 1;        }        return 1;    }    status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,            bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {        if (consumeBatches) {            mBatchedInputEventPending = false;        }        if (outConsumedBatch) {            *outConsumedBatch = false;        }        ScopedLocalRef<jobject> receiverObj(env, NULL);        bool skipCallbacks = false;        for (;;) {            uint32_t seq;            InputEvent* inputEvent;            status_t status = mInputConsumer.consume(&mInputEventFactory,                    consumeBatches, frameTime, &seq, &inputEvent);            if (status) {                if (status == WOULD_BLOCK) {                    ...                }                ALOGE("channel '%s' ~ Failed to consume input event.  status=%d",                        getInputChannelName(), status);                return status;            }            assert(inputEvent);            if (!skipCallbacks) {                ...                jobject inputEventObj;                switch (inputEvent->getType()) {                case AINPUT_EVENT_TYPE_KEY:                    inputEventObj = android_view_KeyEvent_fromNative(env,                            static_cast<KeyEvent*>(inputEvent));                    break;                case AINPUT_EVENT_TYPE_MOTION: {                    MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);                    if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {                        *outConsumedBatch = true;                    }                    inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);                    break;                }                default:                    assert(false); // InputConsumer should prevent this from ever happening                    inputEventObj = NULL;                }                if (inputEventObj) {                    //调用Java层的dispatchInputEvent()方法。                    env->CallVoidMethod(receiverObj.get(),                            gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);                    if (env->ExceptionCheck()) {                        ALOGE("Exception dispatching input event.");                        skipCallbacks = true;                    }                    env->DeleteLocalRef(inputEventObj);                } else {                    ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());                    skipCallbacks = true;                }            }            /* 前面执行成功时,skipCallbacks为false, 最终会调用sendFinishedSignal()函数,               它会构建InputMessage,格式:                 InputMessage msg;                 msg.header.type = InputMessage::TYPE_FINISHED;                 msg.body.finished.seq = seq;                 msg.body.finished.handled = handled;                 mChannel->sendMessage(&msg);               socketpair的服务端会收到该消息后,就知道该消息已经成功分发了。            */            if (skipCallbacks) {                mInputConsumer.sendFinishedSignal(seq, false);            }        }    }

四、InputDispatcher事件发送成功后的处理

int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {        InputDispatcher* d = static_cast<InputDispatcher*>(data);        { // acquire lock            AutoMutex _l(d->mLock);            ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);            if (connectionIndex < 0) {                ALOGE("Received spurious receive callback for unknown input channel.  "                        "fd=%d, events=0x%x", fd, events);                return 0; // remove the callback            }            bool notify;            sp<Connection> connection = d->mConnectionsByFd.valueAt(connectionIndex);            if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {                if (!(events & ALOOPER_EVENT_INPUT)) {                    ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event.  "                            "events=0x%x", connection->getInputChannelName(), events);                    return 1;                }                nsecs_t currentTime = now();                bool gotOne = false;                status_t status;                for (;;) {                    uint32_t seq;                    bool handled;                    status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);                    if (status) {                        break;                    }                    d->finishDispatchCycleLocked(currentTime, connection, seq, handled);                    gotOne = true;                }                if (gotOne) {                    d->runCommandsLockedInterruptible();                    if (status == WOULD_BLOCK) {                        return 1;                    }                }                notify = status != DEAD_OBJECT || !connection->monitor;                if (notify) {                    ALOGE("channel '%s' ~ Failed to receive finished signal.  status=%d",                            connection->getInputChannelName(), status);                }            } else {                // Monitor channels are never explicitly unregistered.                // We do it automatically when the remote endpoint is closed so don't warn                // about them.                notify = !connection->monitor;                if (notify) {                    ALOGW("channel '%s' ~ Consumer closed input channel or an error occurred.  "                            "events=0x%x", connection->getInputChannelName(), events);                }            }            // Unregister the channel.            d->unregisterInputChannelLocked(connection->inputChannel, notify);            return 0; // remove the callback        } // release lock    }    status_t InputDispatcher::unregisterInputChannelLocked(const sp<InputChannel>& inputChannel,            bool notify) {        ssize_t connectionIndex = getConnectionIndexLocked(inputChannel);        if (connectionIndex < 0) {            ALOGW("Attempted to unregister already unregistered input channel '%s'",                    inputChannel->getName().string());            return BAD_VALUE;        }        //移除mConnectionsByFd中与connIndex对应的键值对。        sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);        mConnectionsByFd.removeItemsAt(connectionIndex);        if (connection->monitor) {            removeMonitorChannelLocked(inputChannel);        }        //移除该InputChannel包含的socketFd。        mLooper->removeFd(inputChannel->getFd());        nsecs_t currentTime = now();        abortBrokenDispatchCycleLocked(currentTime, connection, notify);        connection->status = Connection::STATUS_ZOMBIE;        return OK;    }
0 0
原创粉丝点击