应用程序请求注册对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);
- 以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; }
- 应用程序请求注册对Input事件的监听
- 监听input框输入的监听事件
- ServletRequestListener请求的监听事件
- input 标签的监听事件总结
- 对input的值实时监听
- cocos2dx的注册时间监听事件
- 对监听静态注册配置的理解
- input事件监听输入法事件
- input设置键盘监听事件
- input元素添加监听事件
- el-input监听事件失效
- 对抽屉菜单监听事件的优化
- 对css3动画事件的监听
- java中对按钮的事件监听
- 对同一监听事件的不同响应
- jq监听input值改变时的事件
- jquery监听由脚本改变input值的事件
- 事件句柄 注册 监听 概念
- 520. Detect Capital 的OJ代码笔记
- ubuntu16.04下安装Scrapy
- 数塔(HDU-2804)
- Cassandra issue
- Cassandra issue
- 应用程序请求注册对Input事件的监听
- C++11 并发指南一(C++11 多线程初探)
- windows下面安装postgreSQL
- Ubuntu16.04+Cuda8.0+Caffe+ Opencv3.2+Matlab2015b的配置、安装与编译(一)
- java实现排序算法
- HDU1870 愚人节的礼物【堆栈+输入输出】
- 逆波兰表达式 递归
- 使用Calendar类获取某个时间指定的时间
- clearsiver cgi获取到的post数据为空问题