Android之Input子系统事件分发流程
Android之Input子系统事件分发流程
Android创建窗口机制,请看如下转载:
http://blog.csdn.net/sfdev/article/details/9130527
一、Android4.2系统服务侧——与View关系
1.服务端channel注册过程
frameworks/base/core/java/android/view/ViewRootImpl.java
[cpp] view plain copy- publicvoidsetView(Viewview,WindowManager.LayoutParamsattrs,ViewpanelParentView){
- mInputChannel=newInputChannel();//创建InputChannel
- res=mWindowSession.addToDisplay(mWindow,mSeq,mWindowAttributes,
- getHostVisibility(),mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets,mInputChannel);//创建与上述InputChannel对应的通道至服务端
- /*
- mWindowSession=WindowManagerGlobal.getWindowSession(context.getMainLooper());
- frameworks/base/core/java/android/view/WindowManagerGlobal.java
- publicstaticIWindowSessiongetWindowSession(LoopermainLooper){
- IWindowManagerwindowManager=getWindowManagerService();
- sWindowSession=windowManager.openSession(
- imm.getClient(),imm.getInputContext());
- returnsWindowSession;
- }
- frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
- publicIWindowSessionopenSession(IInputMethodClientclient,
- IInputContextinputContext){
- if(client==null)thrownewIllegalArgumentException("nullclient");
- if(inputContext==null)thrownewIllegalArgumentException("nullinputContext");
- Sessionsession=newSession(this,client,inputContext);
- returnsession;
- }
- */
- mInputEventReceiver=newWindowInputEventReceiver(mInputChannel,
- Looper.myLooper());//将本通道注册进InputEventReceiver
- }
- publicintaddToDisplay(IWindowwindow,intseq,WindowManager.LayoutParamsattrs,
- intviewVisibility,intdisplayId,RectoutContentInsets,
- InputChanneloutInputChannel){
- returnmService.addWindow(this,window,seq,attrs,viewVisibility,displayId,
- outContentInsets,outInputChannel);
- }
- publicintaddWindow(Sessionsession,IWindowclient,intseq,
- WindowManager.LayoutParamsattrs,intviewVisibility,intdisplayId,
- RectoutContentInsets,InputChanneloutInputChannel){
- //以下包括了管道的创建(用于WMS与应用程序View通信)等
- Stringname=win.makeInputChannelName();
- InputChannel[]inputChannels=InputChannel.openInputChannelPair(name);
- win.setInputChannel(inputChannels[0]);
- inputChannels[1].transferTo(outInputChannel);
- //以下便是注册至server端过程
- //finalInputManagerServicemInputManager;
- mInputManager.registerInputChannel(win.mInputChannel,win.mInputWindowHandle);
- }
- publicvoidregisterInputChannel(InputChannelinputChannel,
- InputWindowHandleinputWindowHandle){
- nativeRegisterInputChannel(mPtr,inputChannel,inputWindowHandle,false);
- }
- privatestaticnativevoidnativeRegisterInputChannel(intptr,InputChannelinputChannel,
- InputWindowHandleinputWindowHandle,booleanmonitor);
- staticvoidnativeRegisterInputChannel(JNIEnv*env,jclassclazz,
- jintptr,jobjectinputChannelObj,jobjectinputWindowHandleObj,jbooleanmonitor){
- NativeInputManager*im=reinterpret_cast<NativeInputManager*>(ptr);
- status_tstatus=im->registerInputChannel(
- env,inputChannel,inputWindowHandle,monitor);
- }
- status_tNativeInputManager::registerInputChannel(JNIEnv*env,
- constsp<InputChannel>&inputChannel,
- constsp<InputWindowHandle>&inputWindowHandle,boolmonitor){
- returnmInputManager->getDispatcher()->registerInputChannel(
- inputChannel,inputWindowHandle,monitor);
- //mInputManager=newInputManager(eventHub,this,this);
- /*
- frameworks/base/services/input/InputManager.cpp
- sp<InputDispatcherInterface>InputManager::getDispatcher(){
- returnmDispatcher;
- }
- mDispatcher=newInputDispatcher(dispatcherPolicy);
- */
- }
frameworks/base/services/input/InputDispatcher.cpp
[cpp] view plain copy- status_tInputDispatcher::registerInputChannel(constsp<InputChannel>&inputChannel,
- constsp<InputWindowHandle>&inputWindowHandle,boolmonitor){
- intfd=inputChannel->getFd();
- mConnectionsByFd.add(fd,connection);
- //该fd监听对应的处理函数为handleReceiveCallback
- mLooper->addFd(fd,0,ALOOPER_EVENT_INPUT,handleReceiveCallback,this);
- }
2.1.InputReaderThread线程从驱动读取数据并处理,如实现鼠标右键上报back键即在此处完成、以下代码将会看到
frameworks/base/services/input/InputReader.cpp
[cpp] view plain copy- boolInputReaderThread::threadLoop(){
- mReader->loopOnce();
- returntrue;
- }
- voidInputReader::loopOnce(){
- size_tcount=mEventHub->getEvents(timeoutMillis,mEventBuffer,EVENT_BUFFER_SIZE);
- /*
- frameworks/base/services/input/EventHub.cpp
- size_tEventHub::getEvents(inttimeoutMillis,RawEvent*buffer,size_tbufferSize){
- int32_treadSize=read(device->fd,readBuffer,
- sizeof(structinput_event)*capacity);//从驱动读取事件
- }
- */
- processEventsLocked(mEventBuffer,count);
- }
- voidInputReader::processEventsLocked(constRawEvent*rawEvents,size_tcount){
- processEventsForDeviceLocked(deviceId,rawEvent,batchSize);
- }
- voidInputReader::processEventsForDeviceLocked(int32_tdeviceId,
- constRawEvent*rawEvents,size_tcount){
- device->process(rawEvents,count);
- }
- voidInputDevice::process(constRawEvent*rawEvents,size_tcount){
- //该设备的所有mapper进行处理;注意:这里使用了多态
- for(size_ti=0;i<numMappers;i++){
- InputMapper*mapper=mMappers[i];
- mapper->process(rawEvent);
- }
- }
- //以下就是各个mapper
- //CursorInput鼠标设备
- voidCursorInputMapper::process(constRawEvent*rawEvent){
- mCursorButtonAccumulator.process(rawEvent);
- mCursorMotionAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
- if(rawEvent->type==EV_SYN&&rawEvent->code==SYN_REPORT){
- sync(rawEvent->when);
- }
- }
- //CursorButtonAccumulator::process(constRawEvent*rawEvent)
- //CursorMotionAccumulator::process(constRawEvent*rawEvent)
- //CursorScrollAccumulator::process(constRawEvent*rawEvent)
- voidCursorInputMapper::sync(nsecs_twhen){
- int32_tcurrentButtonState=mCursorButtonAccumulator.getButtonState();
- /*
- uint32_tCursorButtonAccumulator::getButtonState()const{
- if(mBtnRight){
- //Changedbytankformouseleftbuttontoback
- result|=AMOTION_EVENT_BUTTON_BACK;
- //result|=AMOTION_EVENT_BUTTON_SECONDARY;
- }
- if(mBtnMiddle){
- //changebytank@tcl.comformousemiddlebuttontomenu
- result|=AMOTION_EVENT_BUTTON_MENU;
- //result|=AMOTION_EVENT_BUTTON_TERTIARY;
- }
- }
- */
- getListener()->notifyMotion(&args);
- synthesizeButtonKeys(getContext(),AKEY_EVENT_ACTION_UP,when,getDeviceId(),mSource,
- policyFlags,lastButtonState,currentButtonState);
- /*
- staticvoidsynthesizeButtonKeys(InputReaderContext*context,int32_taction,
- nsecs_twhen,int32_tdeviceId,uint32_tsource,
- uint32_tpolicyFlags,int32_tlastButtonState,int32_tcurrentButtonState){
- synthesizeButtonKey(context,action,when,deviceId,source,policyFlags,
- lastButtonState,currentButtonState,
- AMOTION_EVENT_BUTTON_BACK,AKEYCODE_BACK);
- synthesizeButtonKey(context,action,when,deviceId,source,policyFlags,
- lastButtonState,currentButtonState,
- AMOTION_EVENT_BUTTON_FORWARD,AKEYCODE_FORWARD);
- //addbytankmousekeyeventmiddle->menu.
- synthesizeButtonKey(context,action,when,deviceId,source,policyFlags,
- lastButtonState,currentButtonState,
- AMOTION_EVENT_BUTTON_MENU,AKEYCODE_MENU);
- //endtank
- }
- staticvoidsynthesizeButtonKey(InputReaderContext*context,int32_taction,
- nsecs_twhen,int32_tdeviceId,uint32_tsource,
- uint32_tpolicyFlags,int32_tlastButtonState,int32_tcurrentButtonState,
- int32_tbuttonState,int32_tkeyCode){
- if((action==AKEY_EVENT_ACTION_DOWN&&!(lastButtonState&buttonState)
- &&(currentButtonState&buttonState))
- ||(action==AKEY_EVENT_ACTION_UP
- &&(lastButtonState&buttonState)
- &&!(currentButtonState&buttonState))){
- context->getListener()->notifyKey(&args);
- }
- }
- */
- }
- //TouchInput触摸板设备
- voidSingleTouchInputMapper::process(constRawEvent*rawEvent)
- TouchInputMapper::process(rawEvent);
- mSingleTouchMotionAccumulator.process(rawEvent);
- }
- //SingleTouchMotionAccumulator::process(constRawEvent*rawEvent)
- voidMultiTouchInputMapper::process(constRawEvent*rawEvent){
- TouchInputMapper::process(rawEvent);
- mMultiTouchMotionAccumulator.process(rawEvent);
- }
- //MultiTouchMotionAccumulator::process(constRawEvent*rawEvent)
- voidTouchInputMapper::process(constRawEvent*rawEvent){
- mCursorButtonAccumulator.process(rawEvent);
- mCursorScrollAccumulator.process(rawEvent);
- mTouchButtonAccumulator.process(rawEvent);
- if(rawEvent->type==EV_SYN&&rawEvent->code==SYN_REPORT){
- sync(rawEvent->when);
- }
- }
- //TouchButtonAccumulator::process(constRawEvent*rawEvent)
- voidTouchInputMapper::sync(nsecs_twhen){
- dispatchTouches(when,policyFlags);
- }
- voidTouchInputMapper::dispatchTouches(nsecs_twhen,uint32_tpolicyFlags){
- dispatchMotion(when,policyFlags,mSource,
- AMOTION_EVENT_ACTION_MOVE,0,metaState,buttonState,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- mCurrentCookedPointerData.pointerProperties,
- mCurrentCookedPointerData.pointerCoords,
- mCurrentCookedPointerData.idToIndex,
- currentIdBits,-1,
- mOrientedXPrecision,mOrientedYPrecision,mDownTime);
- }
- voidTouchInputMapper::dispatchMotion(nsecs_twhen,uint32_tpolicyFlags,uint32_tsource,
- int32_taction,int32_tflags,int32_tmetaState,int32_tbuttonState,int32_tedgeFlags,
- constPointerProperties*properties,constPointerCoords*coords,
- constuint32_t*idToIndex,BitSet32idBits,
- int32_tchangedId,floatxPrecision,floatyPrecision,nsecs_tdownTime){
- getListener()->notifyMotion(&args);
- }
- //SwitchInput设备
- voidSwitchInputMapper::process(constRawEvent*rawEvent){
- sync(rawEvent->when);
- }
- voidSwitchInputMapper::sync(nsecs_twhen){
- getListener()->notifySwitch(&args);
- }
- //JoystickInput游戏手柄设备
- voidJoystickInputMapper::process(constRawEvent*rawEvent){
- sync(rawEvent->when,false/*force*/);
- }
- voidJoystickInputMapper::sync(nsecs_twhen,boolforce){
- getListener()->notifyMotion(&args);
- }
- //KeyboardInput按键设备
- voidKeyboardInputMapper::process(constRawEvent*rawEvent){
- processKey(rawEvent->when,rawEvent->value!=0,keyCode,scanCode,flags);
- }
- voidKeyboardInputMapper::processKey(nsecs_twhen,booldown,int32_tkeyCode,
- int32_tscanCode,uint32_tpolicyFlags){
- getListener()->notifyKey(&args);
- }
2.2.InputReaderThread线程对系统层按键做处理(比较重要的是POWER键,最终在PhoneWindowManager中的interceptKeyBeforeQueueing和interceptMotionBeforeQueueingWhenScreenOff)后分发给InputDispatcherThread线程,以下分析将看到之前一个鼠标操作过程中无法待机的问题解决
以下几种情况都会唤醒InputDispatcherThread线程,即调用mLooper->wake()唤醒正在awoken()中的InputReaderThread线程:
frameworks/base/services/input/InputDispatcher.cpp
[cpp] view plain copy- //有新输入设备注册等
- voidInputDispatcher::notifyConfigurationChanged(constNotifyConfigurationChangedArgs*args){
- ConfigurationChangedEntry*newEntry=newConfigurationChangedEntry(args->eventTime);
- needWake=enqueueInboundEventLocked(newEntry);
- if(needWake){
- mLooper->wake();
- }
- }
- //分发按键事件
- voidInputDispatcher::notifyKey(constNotifyKeyArgs*args){
- //说明:PhoneWindowManager.java中policyFlags位决定系统按键(如HOME等是否需要由系统处理)
- mPolicy->interceptKeyBeforeQueueing(&event,policyFlags);
- //以下分析将看到,该调用实际是在PhoneWindowManager.java中实现
- /*
- frameworks/base/services/input/InputManager.cpp
- InputManager::InputManager(
- constsp<EventHubInterface>&eventHub,
- constsp<InputReaderPolicyInterface>&readerPolicy,
- constsp<InputDispatcherPolicyInterface>&dispatcherPolicy){
- mDispatcher=newInputDispatcher(dispatcherPolicy);
- mReader=newInputReader(eventHub,readerPolicy,mDispatcher);
- }
- frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
- NativeInputManager::NativeInputManager(jobjectcontextObj,
- jobjectserviceObj,constsp<Looper>&looper):
- mLooper(looper){
- mInputManager=newInputManager(eventHub,this,this);
- }
- voidNativeInputManager::interceptKeyBeforeQueueing(constKeyEvent*keyEvent,
- uint32_t&policyFlags){
- wmActions=env->CallIntMethod(mServiceObj,
- gServiceClassInfo.interceptKeyBeforeQueueing,
- keyEventObj,policyFlags,isScreenOn);
- //如下函数中将有待机和开机的处理
- handleInterceptActions(wmActions,when,policyFlags);
- }
- frameworks/base/service/java/com/android/server/input/InputManagerService.java
- privateintinterceptKeyBeforeQueueing(KeyEventevent,intpolicyFlags,booleanisScreenOn){
- returnmWindowManagerCallbacks.interceptKeyBeforeQueueing(
- event,policyFlags,isScreenOn);
- }
- frameworks/base/service/java/com/android/server/SystemServer.java
- inputManager=newInputManagerService(context,wmHandler);
- wm=WindowManagerService.main(context,power,display,inputManager,
- uiHandler,wmHandler,
- factoryTest!=SystemServer.FACTORY_TEST_LOW_LEVEL,
- !firstBoot,onlyCore);
- inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
- frameworks/base/service/java/com/android/server/wm/WindowManagerService.java
- publicInputMonitorgetInputMonitor(){
- returnmInputMonitor;
- }
- frameworks/base/service/java/com/android/server/wm/InputMonitor.java
- publicintinterceptKeyBeforeQueueing(
- KeyEventevent,intpolicyFlags,booleanisScreenOn){
- returnmService.mPolicy.interceptKeyBeforeQueueing(event,policyFlags,isScreenOn);
- }
- publicInputMonitor(WindowManagerServiceservice){
- mService=service;
- }
- frameworks/base/service/java/com/android/server/wm/WindowManagerService.java
- finalWindowManagerPolicymPolicy=PolicyManager.makeNewWindowManager();
- frameworks/base/core/java/com/android/internal/policy/PolicyManager.java
- publicstaticWindowManagerPolicymakeNewWindowManager(){
- returnsPolicy.makeNewWindowManager();
- }
- privatestaticfinalStringPOLICY_IMPL_CLASS_NAME=
- "com.android.internal.policy.impl.Policy";
- ClasspolicyClass=Class.forName(POLICY_IMPL_CLASS_NAME);
- sPolicy=(IPolicy)policyClass.newInstance();
- frameworks/base/core/java/com/android/internal/policy/Policy.java
- packagecom.android.internal.policy.impl;
- publicclassPolicyimplementsIPolicy{
- publicWindowManagerPolicymakeNewWindowManager(){
- returnnewPhoneWindowManager();
- }
- }
- frameworks/base/core/java/com/android/internal/policy/PhoneWindowManager.java
- publicintinterceptKeyBeforeQueueing(KeyEventevent,intpolicyFlags,booleanisScreenOn){
- caseKeyEvent.KEYCODE_POWER:{
- result=(result&~ACTION_WAKE_UP)|ACTION_GO_TO_SLEEP;
- }
- }
- */
- KeyEntry*newEntry=newKeyEntry(args->eventTime,
- args->deviceId,args->source,policyFlags,
- args->action,flags,args->keyCode,args->scanCode,
- metaState,repeatCount,args->downTime);
- needWake=enqueueInboundEventLocked(newEntry);
- if(needWake){
- mLooper->wake();
- }
- }
- //分发Motion事件
- voidInputDispatcher::notifyMotion(constNotifyMotionArgs*args){
- mPolicy->interceptMotionBeforeQueueing(args->eventTime,/*byref*/policyFlags);
- /*
- 如上分析,不再累赘;该接口是:
- frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
- voidNativeInputManager::interceptMotionBeforeQueueing(nsecs_twhen,uint32_t&policyFlags){
- jintwmActions=env->CallIntMethod(mServiceObj,
- gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
- policyFlags);
- handleInterceptActions(wmActions,when,policyFlags);
- }
- 如上interceptMotionBeforeQueueingWhenScreenOff在PhoneWindowManager中实现;分析同上,不再累赘:
- frameworks/base/core/java/com/android/internal/policy/PhoneWindowManager.java
- publicintinterceptMotionBeforeQueueingWhenScreenOff(intpolicyFlags){
- //result|=ACTION_WAKE_UP;
- //addbytank
- result=result&(~ACTION_WAKE_UP);
- //endtank
- returnresult;
- }
- 看看handleInterceptActions函数:
- voidNativeInputManager::handleInterceptActions(jintwmActions,nsecs_twhen,
- uint32_t&policyFlags){
- //接上边PhoneWindowManager中interceptKeyBeforeQueueing对于power键的返回值可知,系统将待机
- if(wmActions&WM_ACTION_GO_TO_SLEEP){
- #ifDEBUG_INPUT_DISPATCHER_POLICY
- ALOGD("handleInterceptActions:Goingtosleep.");
- #endif
- android_server_PowerManagerService_goToSleep(when);
- }
- //以下说明PhoneWindowManager中interceptMotionBeforeQueueingWhenScreenOff返回值WM_ACTION_WAKE_UP将会导致唤醒
- //当然,是可是收到motion事件的前提下
- if(wmActions&WM_ACTION_WAKE_UP){
- #ifDEBUG_INPUT_DISPATCHER_POLICY
- ALOGD("handleInterceptActions:Wakingup.");
- #endif
- android_server_PowerManagerService_wakeUp(when);
- }
- //以下是可以上报给系统的
- if(wmActions&WM_ACTION_PASS_TO_USER){
- policyFlags|=POLICY_FLAG_PASS_TO_USER;
- }
- }
- */
- MotionEntry*newEntry=newMotionEntry(args->eventTime,
- args->deviceId,args->source,policyFlags,
- args->action,args->flags,args->metaState,args->buttonState,
- args->edgeFlags,args->xPrecision,args->yPrecision,args->downTime,
- args->displayId,
- args->pointerCount,args->pointerProperties,args->pointerCoords);
- needWake=enqueueInboundEventLocked(newEntry);
- if(needWake){
- mLooper->wake();
- }
- }
- //设备重置
- voidInputDispatcher::notifyDeviceReset(constNotifyDeviceResetArgs*args){
- DeviceResetEntry*newEntry=newDeviceResetEntry(args->eventTime,args->deviceId);
- needWake=enqueueInboundEventLocked(newEntry);
- if(needWake){
- mLooper->wake();
- }
- }
- //C层的按键注入接口
- int32_tInputDispatcher::injectInputEvent(constInputEvent*event,
- int32_tinjectorPid,int32_tinjectorUid,int32_tsyncMode,int32_ttimeoutMillis,
- uint32_tpolicyFlags){
- needWake|=enqueueInboundEventLocked(entry);
- if(needWake){
- mLooper->wake();
- }
- }
- //setInputWindows
- //setFocusedApplication
- //setInputDispatchMode
- //setInputFilterEnabled
- //transferTouchFocus
- //registerInputChannel
- //unregisterInputChannel
- //monitor
2.3.InputDispatcherThread线程处理,根据PhoneWindowManager中的interceptKeyBeforeDispatching决定是否丢弃按键
InputDispatcherThread线程被唤醒
[cpp] view plain copy- boolInputDispatcherThread::threadLoop(){
- mDispatcher->dispatchOnce();
- returntrue;
- }
- voidInputDispatcher::dispatchOnce(){
- dispatchOnceInnerLocked(&nextWakeupTime);
- mLooper->pollOnce(timeoutMillis);
- }
- voidInputDispatcher::dispatchOnceInnerLocked(nsecs_t*nextWakeupTime){
- if(!mPolicy->isKeyRepeatEnabled()){
- resetKeyRepeatLocked();
- }
- switch(mPendingEvent->type){
- caseEventEntry::TYPE_CONFIGURATION_CHANGED:{
- done=dispatchConfigurationChangedLocked(currentTime,typedEntry);
- }
- caseEventEntry::TYPE_DEVICE_RESET:{
- done=dispatchDeviceResetLocked(currentTime,typedEntry);
- }
- caseEventEntry::TYPE_KEY:{
- done=dispatchKeyLocked(currentTime,typedEntry,&dropReason,nextWakeupTime);
- }
- caseEventEntry::TYPE_MOTION:{
- done=dispatchMotionLocked(currentTime,typedEntry,
- &dropReason,nextWakeupTime);
- }
- }
- dropInboundEventLocked(mPendingEvent,dropReason);//丢弃的事件!!!!
- }
- boolInputDispatcher::dispatchKeyLocked(nsecs_tcurrentTime,KeyEntry*entry,
- DropReason*dropReason,nsecs_t*nextWakeupTime){
- CommandEntry*commandEntry=postCommandLocked(
- &InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
- /*
- voidInputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible(
- CommandEntry*commandEntry){
- //说明:PhoneWindowManager.java中可以截断事件而不上报,即返回-1、将被丢弃
- nsecs_tdelay=mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
- &event,entry->policyFlags);
- if(delay<0){
- entry->interceptKeyResult=KeyEntry::INTERCEPT_KEY_RESULT_SKIP;
- }elseif(!delay){
- entry->interceptKeyResult=KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
- }else{
- entry->interceptKeyResult=KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER;
- entry->interceptKeyWakeupTime=now()+delay;
- }
- }
- */
- elseif(entry->interceptKeyResult==KeyEntry::INTERCEPT_KEY_RESULT_SKIP){
- if(*dropReason==DROP_REASON_NOT_DROPPED){
- *dropReason=DROP_REASON_POLICY;//dropReason是因为策略丢弃
- }
- }
- if(*dropReason!=DROP_REASON_NOT_DROPPED){
- setInjectionResultLocked(entry,*dropReason==DROP_REASON_POLICY
- ?INPUT_EVENT_INJECTION_SUCCEEDED:INPUT_EVENT_INJECTION_FAILED);
- returntrue;
- }
- dispatchEventLocked(currentTime,entry,inputTargets);
- }
- boolInputDispatcher::dispatchMotionLocked(
- nsecs_tcurrentTime,MotionEntry*entry,DropReason*dropReason,nsecs_t*nextWakeupTime){
- dispatchEventLocked(currentTime,entry,inputTargets);
- }
2.4.InputDispatcherThread线程分发给应用程序进程
在这里解决了up事件上报两次的问题!!!!!!
frameworks/base/services/input/InputDispatcher.cpp
[cpp] view plain copy- voidInputDispatcher::dispatchEventLocked(nsecs_tcurrentTime,
- EventEntry*eventEntry,constVector<InputTarget>&inputTargets){
- pokeUserActivityLocked(eventEntry);//和Activity相关,后边三中有设备删除的分析;基本同下
- ssize_tconnectionIndex=getConnectionIndexLocked(inputTarget.inputChannel);
- sp<Connection>connection=mConnectionsByFd.valueAt(connectionIndex);
- prepareDispatchCycleLocked(currentTime,connection,eventEntry,&inputTarget);
- }
- voidInputDispatcher::prepareDispatchCycleLocked(nsecs_tcurrentTime,
- constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget){
- enqueueDispatchEntriesLocked(currentTime,connection,eventEntry,inputTarget);
- }
- voidInputDispatcher::enqueueDispatchEntriesLocked(nsecs_tcurrentTime,
- constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget){
- enqueueDispatchEntryLocked(connection,eventEntry,inputTarget,
- InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);//将按键注入队列
- /*
- voidInputDispatcher::enqueueDispatchEntryLocked(
- constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget,
- int32_tdispatchMode){
- DispatchEntry*dispatchEntry=newDispatchEntry(eventEntry,//incrementsref
- inputTargetFlags,inputTarget->xOffset,inputTarget->yOffset,
- inputTarget->scaleFactor);
- if(!connection->inputState.trackKey(keyEntry,
- dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags)||(dispatchEntry->resolvedFlags==0x28)){
- //addbytankai0x28
- deletedispatchEntry;
- return;
- }
- }
- */
- //dropInboundEventLocked
- //synthesizeCancelationEventsForAllConnectionsLocked->
- //synthesizeCancelationEventsForConnectionLocked->
- /*
- voidInputDispatcher::synthesizeCancelationEventsForConnectionLocked(
- constsp<Connection>&connection,constCancelationOptions&options){
- Vector<EventEntry*>cancelationEvents;
- connection->inputState.synthesizeCancelationEvents(currentTime,
- cancelationEvents,options);
- //关键在这里,mKeyMementos;在enqueueDispatchEntryLocked时调用trackKey由addKeyMemento注入!!!!!!
- if(!cancelationEvents.isEmpty()){
- enqueueDispatchEntryLocked(connection,cancelationEventEntry,//incrementsref
- &target,InputTarget::FLAG_DISPATCH_AS_IS);
- }
- }
- */
- //enqueueDispatchEntriesLocked,注入了0x28标志的按键
- startDispatchCycleLocked(currentTime,connection);
- }
- voidInputDispatcher::startDispatchCycleLocked(nsecs_tcurrentTime,
- constsp<Connection>&connection){
- switch(eventEntry->type){
- caseEventEntry::TYPE_KEY:{
- status=connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
- keyEntry->deviceId,keyEntry->source,
- dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags,
- keyEntry->keyCode,keyEntry->scanCode,
- keyEntry->metaState,keyEntry->repeatCount,keyEntry->downTime,
- keyEntry->eventTime);
- }
- caseEventEntry::TYPE_MOTION:{
- status=connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
- motionEntry->deviceId,motionEntry->source,
- dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags,
- motionEntry->edgeFlags,motionEntry->metaState,motionEntry->buttonState,
- xOffset,yOffset,
- motionEntry->xPrecision,motionEntry->yPrecision,
- motionEntry->downTime,motionEntry->eventTime,
- motionEntry->pointerCount,motionEntry->pointerProperties,
- usingCoords);
- }
- }
- }
[cpp] view plain copy
- status_tInputPublisher::publishKeyEvent(
- uint32_tseq,
- int32_tdeviceId,
- int32_tsource,
- int32_taction,
- int32_tflags,
- int32_tkeyCode,
- int32_tscanCode,
- int32_tmetaState,
- int32_trepeatCount,
- nsecs_tdownTime,
- nsecs_teventTime){
- returnmChannel->sendMessage(&msg);
- }
- status_tInputChannel::sendMessage(constInputMessage*msg){
- do{
- nWrite=::send(mFd,msg,msgLength,MSG_DONTWAIT|MSG_NOSIGNAL);
- }while(nWrite==-1&&errno==EINTR);
- }
二、Android4.2系统应用程序侧——与View关系
InputManagerService也就是InputDispatcher与应用程序通信是靠looper。
说明:
InputReader从设备文件中读取的是RawEvent,在交给InputDispatcher进行分发之前,它需要先把RawEvent进行转化分类,拆分成KeyEvent、MotionEvent、TrackEvent各种类型等。
InputDispatcher获得按键事件后,根据当前设备的状况来优先消化事件(该过程交由PhoneWindowManager.java来处理);最后,剩余事件分发给ViewRoot;ViewRoot再分发给IME输入法或View、Activity。
1.应用程序View中channel注册过程
frameworks/base/core/java/android/view/ViewRootImpl.java
[cpp] view plain copy- publicvoidsetView(Viewview,WindowManager.LayoutParamsattrs,ViewpanelParentView){
- mInputChannel=newInputChannel();//创建InputChannel
- res=mWindowSession.addToDisplay(mWindow,mSeq,mWindowAttributes,
- getHostVisibility(),mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets,mInputChannel);//创建与上述InputChannel对应的通道至服务端
- mInputEventReceiver=newWindowInputEventReceiver(mInputChannel,
- Looper.myLooper());//将本通道注册进InputEventReceiver
- }
- finalclassWindowInputEventReceiverextendsInputEventReceiver{
- publicWindowInputEventReceiver(InputChannelinputChannel,Looperlooper){
- super(inputChannel,looper);
- }
- @Override
- publicvoidonInputEvent(InputEventevent){
- enqueueInputEvent(event,this,0,true);
- }
- }
frameworks/base/core/java/android/view/InputEventReceiver.java
[cpp] view plain copy- publicInputEventReceiver(InputChannelinputChannel,Looperlooper){
- mReceiverPtr=nativeInit(this,inputChannel,mMessageQueue);
- }
- privatestaticnativeintnativeInit(InputEventReceiverreceiver,
- InputChannelinputChannel,MessageQueuemessageQueue);
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
[cpp] view plain copy- staticjintnativeInit(JNIEnv*env,jclassclazz,jobjectreceiverObj,
- jobjectinputChannelObj,jobjectmessageQueueObj){
- sp<NativeInputEventReceiver>receiver=newNativeInputEventReceiver(env,
- receiverObj,inputChannel,messageQueue);
- status_tstatus=receiver->initialize();
- }
- status_tNativeInputEventReceiver::initialize(){
- intreceiveFd=mInputConsumer.getChannel()->getFd();
- mMessageQueue->getLooper()->addFd(receiveFd,0,ALOOPER_EVENT_INPUT,this,NULL);
- returnOK;
- }
frameworks/native/libs/utils/Looper.cpp
[cpp] view plain copy- intLooper::addFd(intfd,intident,intevents,constsp<LooperCallback>&callback,void*data){
- request.callback=callback;
- }
2.应用程序View响应过程
frameworks/native/libs/utils/Looper.cpp
[cpp] view plain copy- intLooper::pollInner(inttimeoutMillis){
- awoken();//阻塞,等待
- intcallbackResult=response.request.callback->handleEvent(fd,events,data);
- }
frameworks/base/core/jni/android_view_InputEventReceiver.cpp
[cpp] view plain copy- intNativeInputEventReceiver::handleEvent(intreceiveFd,intevents,void*data){
- status_tstatus=consumeEvents(env,false/*consumeBatches*/,-1);
- }
- status_tNativeInputEventReceiver::consumeEvents(JNIEnv*env,
- boolconsumeBatches,nsecs_tframeTime){
- env->CallVoidMethod(mReceiverObjGlobal,
- gInputEventReceiverClassInfo.dispatchInputEvent,seq,inputEventObj);
- }
- privatevoiddispatchInputEvent(intseq,InputEventevent){
- mSeqMap.put(event.getSequenceNumber(),seq);
- onInputEvent(event);
- }
- finalclassWindowInputEventReceiverextendsInputEventReceiver{
- publicWindowInputEventReceiver(InputChannelinputChannel,Looperlooper){
- super(inputChannel,looper);
- }
- @Override
- publicvoidonInputEvent(InputEventevent){
- enqueueInputEvent(event,this,0,true);
- }
- }
- voidenqueueInputEvent(InputEventevent,
- InputEventReceiverreceiver,intflags,booleanprocessImmediately){
- scheduleProcessInputEvents();
- }
/////////////////////////////////////////////////////////////
有关handler机制请看下文:
http://blog.csdn.net/itachi85/article/details/8035333
- finalViewRootHandlermHandler=newViewRootHandler();
- privatevoidscheduleProcessInputEvents(){
- Messagemsg=mHandler.obtainMessage(MSG_PROCESS_INPUT_EVENTS);
- mHandler.sendMessage(msg);
- }
- publicvoidhandleMessage(Messagemsg){
- switch(msg.what){
- caseMSG_PROCESS_INPUT_EVENTS:
- doProcessInputEvents();
- }
- }
///////////////////////////////////////////////////////
[cpp] view plain copy- voiddoProcessInputEvents(){
- deliverInputEvent(q);
- }
- privatevoiddeliverInputEvent(QueuedInputEventq){
- deliverKeyEvent(q);
- deliverPointerEvent(q);
- deliverTrackballEvent(q);
- deliverGenericMotionEvent(q);
- }
- privatevoiddeliverKeyEvent(QueuedInputEventq){
- imm.dispatchKeyEvent(mView.getContext(),seq,event,mInputMethodCallback);//分发给输入法
- deliverKeyEventPostIme(q);//分发给View
- /*
- privatevoiddeliverKeyEventPostIme(QueuedInputEventq){
- mView.dispatchKeyEvent(event)
- }
- */
- }
- privatevoiddeliverPointerEvent(QueuedInputEventq){
- booleanhandled=mView.dispatchPointerEvent(event);//分发给View
- }
- privatevoiddeliverTrackballEvent(QueuedInputEventq){
- imm.dispatchTrackballEvent(mView.getContext(),seq,event,
- mInputMethodCallback);//分发给输入法
- deliverTrackballEventPostIme(q);//分发给View
- /*
- privatevoiddeliverTrackballEventPostIme(QueuedInputEventq){
- mView.dispatchTrackballEvent(event)
- }
- */
- }
- privatevoiddeliverGenericMotionEvent(QueuedInputEventq){
- imm.dispatchGenericMotionEvent(mView.getContext(),seq,event,
- mInputMethodCallback);//分发给输入法
- deliverGenericMotionEventPostIme(q);//分发给View
- /*
- privatevoiddeliverGenericMotionEventPostIme(QueuedInputEventq){
- updateJoystickDirection(event,false);//游戏手柄的摇杆就是在这处理
- mView.dispatchGenericMotionEvent(event)
- }
- */
- }
分发给应用程序Activity:
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
[java] view plain copy- privatefinalclassDecorViewextendsFrameLayoutimplementsRootViewSurfaceTaker{
- publicbooleandispatchKeyEvent(KeyEventevent){
- finalCallbackcb=getCallback();
- //cb为应用程序MainActivity
- finalbooleanhandled=cb!=null&&mFeatureId<0?cb.dispatchKeyEvent(event):super.dispatchKeyEvent(event);
- //给应用程序Activity的dispatchKeyEvent处理或交给View的dispatchKeyEvent
- }
- }
而上述应用程序中的dispatchKeyEvent一般会调用其父类的该方法,例如:
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
[java] view plain copy- publicbooleandispatchKeyEvent(KeyEventevent){
- returnsuper.dispatchKeyEvent(event);
- }
应用程序Activity在分发给与之关联的某个View,如果这个View没有处理、最终交给该Activity自己处理。
应用程序有关View的设置:
[java] view plain copy- privateDialogmMenuWin;
- mMenuWin=newDialog(aActivity,R.style.CameraDialog);
- mMenuWin.setContentView(mMenuLayout);
- mMenuWin.setOnClickListener();//鼠标单击
- mMenuWin.setOnLongClickListener();//
- mMenuWin.setOnTouchListener();//触摸板
- mMenuWin.setOnKeyListener(newOnKeyListener(){
- publicbooleanonKey();//按键
- publicvoidonClick(Viewv);//鼠标单击
- }
frameworks/base/core/java/android/app/Activity.java
[java] view plain copy- publicbooleandispatchKeyEvent(KeyEventevent){
- onUserInteraction();
- Windowwin=getWindow();
- if(win.superDispatchKeyEvent(event)){//首先由Window消化,即如果View消化了、则Activity将不在回调onKeyDown
- returntrue;
- }
- Viewdecor=mDecor;//如果没被消化,会调用Activity的onKeyDown
- if(decor==null)decor=win.getDecorView();
- returnevent.dispatch(this,decor!=null?decor.getKeyDispatcherState():null,this);
- }
- }
frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java
[java] view plain copy- publicclassPhoneWindowextendsWindowimplementsMenuBuilder.Callback{
- publicbooleansuperDispatchKeyEvent(KeyEventevent){
- returnmDecor.superDispatchKeyEvent(event);
- }
- }
- privatefinalclassDecorViewextendsFrameLayoutimplementsRootViewSurfaceTaker{
- publicbooleansuperDispatchKeyEvent(KeyEventevent){
- super.dispatchKeyEvent(event)
- }
- }
- publicbooleandispatchKeyEvent(KeyEventevent){
- mInputEventConsistencyVerifier.onKeyEvent(event,1);
- super.dispatchKeyEvent(event)
- }
frameworks/base/core/java/android/view/View.java
[java] view plain copy- publicbooleandispatchKeyEvent(KeyEventevent){
- li.mOnKeyListener.onKey(this,event.getKeyCode(),event);//回调应用程序View相应方法
- event.dispatch(this,mAttachInfo!=null?mAttachInfo.mKeyDispatchState:null,this)
- /*
- frameworks/base/core/java/android/view/KeyEvent.java
- publicfinalbooleandispatch(Callbackreceiver,DispatcherStatestate,
- Objecttarget){
- //按键响应
- booleanres=receiver.onKeyDown(mKeyCode,this);//应用程序回调函数
- }
- */
- }
- publicfinalbooleandispatchPointerEvent(MotionEventevent){
- if(event.isTouchEvent()){
- returndispatchTouchEvent(event);
- }else{
- returndispatchGenericMotionEvent(event);
- }
- }
- publicbooleandispatchTouchEvent(MotionEventevent){
- //触摸板响应
- li.mOnTouchListener.onTouch(this,event)//应用程序继承OnTouchListener,实现的回调接口
- //鼠标左键响应
- onTouchEvent(event)
- /*
- publicbooleanonTouchEvent(MotionEventevent){
- performClick();
- //该接口调用li.mOnClickListener.onClick(this);为应用程序继承OnClickListener的回调函数
- }
- */
- }
dispatchGenericMotionEvent
dispatchTrackballEvent
dispatchConfigurationChanged //添加或删除键盘设备Activity重启,见http://blog.csdn.net/tankai19880619/article/details/16805401
三、Input设备与Activity关系
1.InputReaderThread线程检测到设备插入删除
frameworks/base/service/input/InputReader.cpp
[cpp] view plain copy- voidInputReader::loopOnce(){
- size_tcount=mEventHub->getEvents(timeoutMillis,mEventBuffer,EVENT_BUFFER_SIZE);
- /*
- frameworks/base/services/input/EventHub.cpp
- size_tEventHub::getEvents(inttimeoutMillis,RawEvent*buffer,size_tbufferSize){
- int32_treadSize=read(device->fd,readBuffer,
- sizeof(structinput_event)*capacity);//从驱动读取事件
- }
- */
- processEventsLocked(mEventBuffer,count);
- }
- voidInputReader::processEventsLocked(constRawEvent*rawEvents,size_tcount){
- caseEventHubInterface::FINISHED_DEVICE_SCAN:
- handleConfigurationChangedLocked(rawEvent->when);
- }
- voidInputReader::handleConfigurationChangedLocked(nsecs_twhen){
- updateGlobalMetaStateLocked();
- //Enqueueconfigurationchanged.
- NotifyConfigurationChangedArgsargs(when);
- mQueuedListener->notifyConfigurationChanged(&args);
- }
说明:有的平台需要在接入硬件键盘时Activity不需要刷新;可以在上处做屏蔽:
[cpp] view plain copy- //addbytank
- //donotsendconfigurationchange
- //NotifyConfigurationChangedArgsargs(when);
- //mQueuedListener->notifyConfigurationChanged(&args);
- //endtank
2.InputReaderThread线程分发给InputDispatcherThread线程
frameworks/base/service/input/InputDispatcher.cpp
[cpp] view plain copy- voidInputDispatcher::notifyConfigurationChanged(constNotifyConfigurationChangedArgs*args){
- needWake=enqueueInboundEventLocked(newEntry);
- if(needWake){
- mLooper->wake();
- }
- }
frameworks/base/service/input/InputDispatcher.cpp
[cpp] view plain copy- boolInputDispatcherThread::threadLoop(){
- mDispatcher->dispatchOnce();
- returntrue;
- }
- voidInputDispatcher::dispatchOnce(){
- dispatchOnceInnerLocked(&nextWakeupTime);
- }
- voidInputDispatcher::dispatchOnceInnerLocked(nsecs_t*nextWakeupTime){
- caseEventEntry::TYPE_CONFIGURATION_CHANGED:{
- ConfigurationChangedEntry*typedEntry=
- static_cast<ConfigurationChangedEntry*>(mPendingEvent);
- done=dispatchConfigurationChangedLocked(currentTime,typedEntry);
- }
- }
- boolInputDispatcher::dispatchConfigurationChangedLocked(
- nsecs_tcurrentTime,ConfigurationChangedEntry*entry){
- CommandEntry*commandEntry=postCommandLocked(
- &InputDispatcher::doNotifyConfigurationChangedInterruptible);
- }
- voidInputDispatcher::doNotifyConfigurationChangedInterruptible(
- CommandEntry*commandEntry){
- mPolicy->notifyConfigurationChanged(commandEntry->eventTime);
- }
frameworks/base/services/jni/com_android_server_input_InputManagerService.cpp
[cpp] view plain copy- voidNativeInputManager::notifyConfigurationChanged(nsecs_twhen){
- env->CallVoidMethod(mServiceObj,gServiceClassInfo.notifyConfigurationChanged,when);
- }
- privatevoidnotifyConfigurationChanged(longwhenNanos){
- mWindowManagerCallbacks.notifyConfigurationChanged();
- }
frameworks/base/service/java/com/android/server/wm/InputMonitor.java
[cpp] view plain copy- publicvoidnotifyConfigurationChanged(){
- mService.sendNewConfiguration();
- }
- voidsendNewConfiguration(){
- mActivityManager.updateConfiguration(null);
- /*
- mActivityManager=ActivityManagerNative.getDefault();
- frameworks/base/core/java/android/app/ActivityManagerNative.java
- staticpublicIActivityManagergetDefault(){
- returngDefault.get();
- }
- privatestaticfinalSingleton<IActivityManager>gDefault=newSingleton<IActivityManager>(){
- IBinderb=ServiceManager.getService("activity");
- IActivityManageram=asInterface(b);
- returnam;
- }
- frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
- publicstaticvoidsetSystemProcess(){
- ActivityManagerServicem=mSelf;
- ServiceManager.addService("activity",m,true);
- }
- */
- }
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
[cpp] view plain copy- publicvoidupdateConfiguration(Configurationvalues){
- updateConfigurationLocked(values,null,false,false);
- }
- booleanupdateConfigurationLocked(Configurationvalues,
- ActivityRecordstarting,booleanpersistent,booleaninitLocale){
- kept=mMainStack.ensureActivityConfigurationLocked(starting,changes);
- publicvoidsetWindowManager(WindowManagerServicewm){
- mWindowManager=wm;
- }
- }
- finalbooleanensureActivityConfigurationLocked(ActivityRecordr,
- intglobalChanges){
- //一般会重启Activity
- if((changes&(~r.info.getRealConfigChanged()))!=0||r.forceNewConfig){
- relaunchActivityLocked(r,r.configChangeFlags,false);
- returnfalse;
- }
- //应用程序AndroidMenifest中写标记将不会重启
- r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
- }
- publicvoidscheduleActivityConfigurationChanged(IBindertoken){
- queueOrSendMessage(H.ACTIVITY_CONFIGURATION_CHANGED,token);
- }
- //消息循环同上,不再分析
- publicvoidhandleMessage(Messagemsg){
- caseACTIVITY_CONFIGURATION_CHANGED:
- handleActivityConfigurationChanged((IBinder)msg.obj);
- }
- finalvoidhandleActivityConfigurationChanged(IBindertoken){
- performConfigurationChanged(r.activity,mCompatConfiguration);
- }
- privatestaticvoidperformConfigurationChanged(ComponentCallbacks2cb,Configurationconfig){
- cb.onConfigurationChanged(config);//回调Activity类的onConfigurationChanged方法
- }
四、项目问题
1.resumeTopActivity时的Activity重启。
http://blog.csdn.net/jivin_shen/article/details/6839175
操作逻辑:打开Launcher界面下的一个应用(比如播放器),完后接入USB键盘;之后退出该应用,也就是resumeTopActivity到Launcher时也引发了config配置更新导致的Activity重启。
原理以及解决部分:
frameworks/base/services/java/com/android/server/am/ActivityStack.java
- finalbooleanresumeTopActivityLocked(ActivityRecordprev){
- returnresumeTopActivityLocked(prev,null);
- }
- finalbooleanresumeTopActivityLocked(ActivityRecordprev,Bundleoptions){
- Configurationconfig=mService.mWindowManager.updateOrientationFromAppTokens(
- mService.mConfiguration,
- next.mayFreezeScreenLocked(next.app)?next.appToken:null);
- }
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
[cpp] view plain copy- publicConfigurationupdateOrientationFromAppTokens(
- ConfigurationcurrentConfig,IBinderfreezeThisOneIfNeeded){
- config=updateOrientationFromAppTokensLocked(currentConfig,
- freezeThisOneIfNeeded);
- }
- privateConfigurationupdateOrientationFromAppTokensLocked(
- ConfigurationcurrentConfig,IBinderfreezeThisOneIfNeeded){
- computeScreenConfigurationLocked(mTempConfiguration)
- }
- booleancomputeScreenConfigurationLocked(Configurationconfig){
- if((sources&InputDevice.SOURCE_TOUCHSCREEN)==InputDevice.SOURCE_TOUCHSCREEN){
- //changebytank
- config.touchscreen=Configuration.TOUCHSCREEN_NOTOUCH;
- //config.touchscreen=Configuration.TOUCHSCREEN_FINGER;
- //endtank
- }
- elseif((sources&InputDevice.SOURCE_DPAD)==InputDevice.SOURCE_DPAD
- &&config.navigation==Configuration.NAVIGATION_NONAV){
- //changebytank
- //config.navigation=Configuration.NAVIGATION_DPAD;
- //navigationPresence|=presenceFlag;
- //endtank
- }
- if(device.getKeyboardType()==InputDevice.KEYBOARD_TYPE_ALPHABETIC){
- //changebytank
- //config.keyboard=Configuration.KEYBOARD_QWERTY;
- //keyboardPresence|=presenceFlag;
- //endtank
- }
- }
2.面板设备与虚拟驱动导致的up上报两次:
drop类按键
down或up:
dispatchOnceInnerLocked>
dropInboundEventLocked>synthesizeCancelationEventsForAllConnectionsLocked-synthesizeCancelationEventsForConnectionLocked>inputState.synthesizeCancelationEvents->mKeyMementos.itemAt(i),最后上报系统(synthesizeCancelationEventsForConnectionLocked调用enqueueDispatchEntryLocked)
非drop类按键
down:
dispatchOnceInnerLocked->
dispatchKeyLocked->dispatchEventLocked->prepareDispatchCycleLocked->enqueueDispatchEntriesLocked->enqueueDispatchEntryLocked->InputState::trackKey->addKeyMemento //只在down时保存对up的处理
问题:
面板down->drop
虚拟down->非drop,保存up
面板down->drop,将虚拟保存的up送上去
虚拟up->非drop,直接上报
结果——两个虚拟的up
修改方法:
frameworks/base/service/input/InputDispatcher.cpp
[cpp] view plain copy- voidInputDispatcher::enqueueDispatchEntryLocked(
- constsp<Connection>&connection,EventEntry*eventEntry,constInputTarget*inputTarget,
- int32_tdispatchMode)
- {
- if(!connection->inputState.trackKey(keyEntry,
- dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags)/*addbytank@tcl.comend*/||(dispatchEntry->resolvedFlags==0x28))
- {
- #ifDEBUG_DISPATCH_CYCLE
- ALOGD("channel'%s'~enqueueDispatchEntryLocked:skippinginconsistentkeyevent",
- connection->getInputChannelName());
- #endif
- deletedispatchEntry;
- return;//skiptheinconsistentevent
- }
- /*
- //addbytankai
- if(dispatchEntry->resolvedFlags==0x28&&keyEntry->deviceId==3){
- ALOGD("TK--------->>>deletesimKeyMementosup\n");
- deletedispatchEntry;
- return;//skiptheinconsistentevent
- }
- //endtankai
- */
- }
3.焦点request错误导致不能响应按键
正确调用:setFocusable(true)和requestFocus()重新获取焦点
错误调用:setFocusable(false)和requestFocus()
系统侧为该应用tv.huan.deezer强制修改:
frameworks/base/core/java/android/view/View.java
[java] view plain copy
- publicfinalbooleanrequestFocus(){
- Log.d("TKTK","TK---->>>View.java>>>>requestFocus()");//addbytank
- if(SystemProperties.get("sys.user.camera",null).equals("tv.huan.deezer"))
- {
- setFocusable(true);
- }
- //endtank
- returnrequestFocus(View.FOCUS_DOWN);
- }
更多相关文章
- Google Android 应用程序结构
- android应用程序跳转到系统的各个设置页面
- 如何以编程方式退出android应用程序
- Android Application Fundamentals——Android应用程序基础知识
- Android 应用程序只运行一个实例
- android4.2上获取应用程序大小的变更点
- android按键灯流程分析
- Android 拦截 HOME 按键
- Android 之应用程序重启