Android 4.2 Input Event事件处理流程<一>---inputManager启动
2014-07-29 22:05
471 查看
Android中的事件处理流程比较复杂,我们分析下Android事件是怎么传给应用的,这里先看下nputManager启动的启动,流程图如下:
不知道从那个版本开始,Android加入了InputManagerService,InputManagerService由SystemServer创建,构造函数如下:
NativeInputManager又创建了EventHub和InputManager,我们先看EventHub
notify机制参考:http://blog.csdn.net/new_abc/article/details/38276057
把三个句柄添加到mEpollFd
回到NativeInputManager初始化,创建InputManager
主要是一些初始化,创建了一个Looper
创建一个QueuedInputListener,用于下面和JNI层往Java的消息传递调用等,再看initialize
到这里InputManagerService就已经初始化完成了,回到SystemServer,与inputManager相关的有一下几行
nativeStart比较简单,继续调用C++层的InputManager的start
启动了线程之后,就可以开始监听消息了。
不知道从那个版本开始,Android加入了InputManagerService,InputManagerService由SystemServer创建,构造函数如下:
public InputManagerService(Context context, Handler handler) { this.mContext = context; this.mHandler = new InputManagerHandler(handler.getLooper()); mUseDevInputEventForAudioJack = context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack=" + mUseDevInputEventForAudioJack); mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());创建了一个InputManagerHandler并调用nativeInit进行初始化,看一下nativeInit
static jint nativeInit(JNIEnv* env, jclass clazz, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); im->incStrong(serviceObj); return reinterpret_cast<jint>(im); }这里又创建一个NativeInputManager
NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper) { 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; } sp<EventHub> eventHub = new EventHub(); mInputManager = new InputManager(eventHub, this, this); }
NativeInputManager又创建了EventHub和InputManager,我们先看EventHub
EventHub::EventHub(void) : mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mOpeningDevices(0), mClosingDevices(0), mNeedToSendFinishedDeviceScan(false), mNeedToReopenDevices(false), mNeedToScanDevices(true), mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); mEpollFd = epoll_create(EPOLL_SIZE_HINT); LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); mINotifyFd = inotify_init(); int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE); LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s. errno=%d", DEVICE_PATH, errno); struct epoll_event eventItem; memset(&eventItem, 0, sizeof(eventItem)); eventItem.events = EPOLLIN; eventItem.data.u32 = EPOLL_ID_INOTIFY; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance. errno=%d", errno); int wakeFds[2]; result = pipe(wakeFds); LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); mWakeReadPipeFd = wakeFds[0]; mWakeWritePipeFd = wakeFds[1]; result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", errno); result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", errno); eventItem.data.u32 = EPOLL_ID_WAKE; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", errno); }
notify机制参考:http://blog.csdn.net/new_abc/article/details/38276057
把三个句柄添加到mEpollFd
回到NativeInputManager初始化,创建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(); }新建了InputDispatcher,InputReader,并调用初始化函数initialize,先看InputDispatcher
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) : mPolicy(policy), mPendingEvent(NULL), mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX), mNextUnblockedEvent(NULL), mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false), mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) { mLooper = new Looper(false); mKeyRepeatState.lastKeyEntry = NULL; policy->getDispatcherConfiguration(&mConfig); }
主要是一些初始化,创建了一个Looper
// --- InputReader --- InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) : mContext(this), mEventHub(eventHub), mPolicy(policy), mGlobalMetaState(0), mGeneration(1), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX), mConfigurationChangesToRefresh(0) { mQueuedListener = new QueuedInputListener(listener); { // acquire lock AutoMutex _l(mLock); mKeySynced = true; mKeyInMouseMode =false; mKeySynced = true; mDistance = 10; mKeyDeviceId = 0; mVirtualMouseCreated = false; mMouseDeviceId = 0x0fff0fff; mTouchDeviceId = 0x0fff0ffe; mVirtualTouchCreated = false; for(int i= 0;i < MAX_MOUSE_SIZE;i++) { mRealMouseDeviceId[i] = -1; } mRealTouchDeviceId = -1; mLeft = 0; mRight = 0; mTop = 0; mBottom = 0; refreshConfigurationLocked(0); updateGlobalMetaStateLocked(); } // release lock }
创建一个QueuedInputListener,用于下面和JNI层往Java的消息传递调用等,再看initialize
void InputManager::initialize() { mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher); }创建了两个线程,看一下他们的threadLoop
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true; }
bool InputDispatcherThread::threadLoop() { mDispatcher->dispatchOnce(); return true; }
到这里InputManagerService就已经初始化完成了,回到SystemServer,与inputManager相关的有一下几行
inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); display.setWindowManager(wm); display.setInputManager(inputManager);首先设置了inputmanager的WindowManagerCallbacks接口,然后调用inputManager的start,最后display设置inputManager,我们主要看下inputManager的start
public void start() { Slog.i(TAG, "Starting input manager"); nativeStart(mPtr);//native层的start // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this);//添加到WatchDogs 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(); }
nativeStart比较简单,继续调用C++层的InputManager的start
static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); status_t result = im->getInputManager()->start(); if (result) { jniThrowRuntimeException(env, "Input manager could not be started."); } }InputManager比较简单,主要是启动前面创建的两个线程
status_t InputManager::start() { status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY); if (result) { ALOGE("Could not start InputDispatcher thread due to error %d.", result); return result; } result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY); if (result) { ALOGE("Could not start InputReader thread due to error %d.", result); mDispatcherThread->requestExit(); return result; } return OK; }
启动了线程之后,就可以开始监听消息了。
相关文章推荐
- Android 4.2 Input Event事件处理流程<一>事情派发
- Android 4.2 Input Event事件处理流程<一>---应用注册
- 从零开始学android<android事件的处理方式.二十四.>
- <Android>长按事件的连续处理
- <4>Android4.2 G-Sensor工作流程
- <WEB>平板_手机开发_13 个处理触摸事件和多点触摸的JS 库
- Android开发工具——ADB(Android Debug Bridge) <一>概览
- linux启动流程导读(arm为例)&lt;一&gt;
- android Fragment实现<一>
- linux启动流程导读(arm为例)&lt;一&gt;
- Android开发收集<一>
- < Unity 3D专栏 >添加控件检测事件,函数处理
- linux启动流程导读(arm为例)<一>
- Android拨号界面输入*#*#<code>#*#*转入自定义Activity流程
- windows游戏编程<一>了解消息事件模型
- cocos2d-x基础<一> Android环境配置和HelloWorld的运行
- Android学习笔记:<一>Android 四大组件
- Android 新API 之 MediaCodec使用笔记 <一>
- EasyUI的datagrid中<a>标签需要点两次才能触发事件的处理方法
- android 数据存储<一>----android短信发送器之文件的读写(手机+SD卡)