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

一、应用程序在绘制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(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);
    inline sp getInputManager() const { return mInputManager; }
    status_t registerInputChannel(JNIEnv* env, const sp& inputChannel,
            const sp& inputWindowHandle, bool monitor);
    status_t unregisterInputChannel(JNIEnv* env, const sp& inputChannel);
    ...
private:
    sp mInputManager;

    jobject mContextObj;
    jobject mServiceObj;
    sp mLooper;
}

NativeInputManager的构造函数

NativeInputManager::NativeInputManager(jobject contextObj,
    jobject serviceObj, const sp& 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 = 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(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 getReader() = 0;

    /* Gets the input dispatcher. */
    virtual sp getDispatcher() = 0;
};

具体类:

class InputManager : public InputManagerInterface {
protected:
    virtual ~InputManager();

public:
    InputManager(
            const sp& eventHub,
            const sp& readerPolicy,
            const sp& dispatcherPolicy);

    // (used for testing purposes)
    InputManager(
            const sp& reader,
            const sp& dispatcher);

    virtual status_t start();
    virtual status_t stop();

    virtual sp getReader();
    virtual sp getDispatcher();

private:
    sp mReader;
    sp mReaderThread;

    sp mDispatcher;
    sp mDispatcherThread;

    void initialize();
};

socketpair服务端的注册

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

status_t InputDispatcher::registerInputChannel(const sp& inputChannel, 
        const sp& 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,
                const sp& 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 mMessageQueue;
        PreallocatedInputEventFactory mInputEventFactory;
        bool mBatchedInputEventPending;
        int mFdEvents;
        Vector 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 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(inputEvent));
                    break;

                case AINPUT_EVENT_TYPE_MOTION: {
                    MotionEvent* motionEvent = static_cast(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;
    }

你可能感兴趣的:(Android应用)