Android输入输出系统之TouchEvent流程
一个是InputReader,一个是InputDispatcher。方法是dispatchTouch。
入口点是InputReader 的loopOnce方法.
InputReader里面有个线程叫做InputReaderThread,threadLoop
[code="java"]InputReaderThread::InputReaderThread(const sp& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
InputReaderThread::~InputReaderThread() {
}
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
- voidInputDispatcher::dispatchOnce(){
- nsecs_tkeyRepeatTimeout=mPolicy->getKeyRepeatTimeout();
- nsecs_tkeyRepeatDelay=mPolicy->getKeyRepeatDelay();
- nsecs_tnextWakeupTime=LONG_LONG_MAX;
- {//acquirelock
- AutoMutex_l(mLock);
- dispatchOnceInnerLocked(keyRepeatTimeout,keyRepeatDelay,&nextWakeupTime);
- if(runCommandsLockedInterruptible()){
- nextWakeupTime=LONG_LONG_MIN;//forcenextpolltowakeupimmediately
- }
- }//releaselock
- //Waitforcallbackortimeoutorwake.(makesureweroundup,notdown)
- nsecs_tcurrentTime=now();
- int32_ttimeoutMillis;
- if(nextWakeupTime>currentTime){
- uint64_ttimeout=uint64_t(nextWakeupTime-currentTime);
- timeout=(timeout+999999LL)/1000000LL;
- timeoutMillis=timeout>INT_MAX?-1:int32_t(timeout);
- }else{
- timeoutMillis=0;
- }
- mLooper->pollOnce(timeoutMillis);
- }
Java代码
- caseEventEntry::TYPE_MOTION:{
- MotionEntry*typedEntry=static_cast<MotionEntry*>(mPendingEvent);
- if(dropReason==DROP_REASON_NOT_DROPPED&&isAppSwitchDue){
- dropReason=DROP_REASON_APP_SWITCH;
- }
- done=dispatchMotionLocked(currentTime,typedEntry,
- &dropReason,nextWakeupTime);
- break;
Java代码
- boolInputDispatcher::dispatchMotionLocked(
- nsecs_tcurrentTime,MotionEntry*entry,DropReason*dropReason,nsecs_t*nextWakeupTime){
- //Preprocessing.
- if(!entry->dispatchInProgress){
- entry->dispatchInProgress=true;
- resetTargetsLocked();
- logOutboundMotionDetailsLocked("dispatchMotion-",entry);
- }
- //Cleanupifdroppingtheevent.
- if(*dropReason!=DROP_REASON_NOT_DROPPED){
- resetTargetsLocked();
- setInjectionResultLocked(entry,*dropReason==DROP_REASON_POLICY
- ?INPUT_EVENT_INJECTION_SUCCEEDED:INPUT_EVENT_INJECTION_FAILED);
- returntrue;
- }
- boolisPointerEvent=entry->source&AINPUT_SOURCE_CLASS_POINTER;
- //Identifytargets.
- if(!mCurrentInputTargetsValid){
- int32_tinjectionResult;
- if(isPointerEvent){
- //Pointerevent.(eg.touchscreen)
- injectionResult=findTouchedWindowTargetsLocked(currentTime,
- entry,nextWakeupTime);
- }else{
- //Nontouchevent.(eg.trackball)
- injectionResult=findFocusedWindowTargetsLocked(currentTime,
- entry,nextWakeupTime);
- }
- if(injectionResult==INPUT_EVENT_INJECTION_PENDING){
- returnfalse;
- }
- setInjectionResultLocked(entry,injectionResult);
- if(injectionResult!=INPUT_EVENT_INJECTION_SUCCEEDED){
- returntrue;
- }
- addMonitoringTargetsLocked();
- commitTargetsLocked();
- }
- //Dispatchthemotion.
- dispatchEventToCurrentInputTargetsLocked(currentTime,entry,false);
- returntrue;
- }
Java代码
- startDispatchCycleLocked中的方法
- status=connection->inputPublisher.publishMotionEvent(motionEntry->deviceId,
- motionEntry->source,action,flags,motionEntry->edgeFlags,motionEntry->metaState,
- xOffset,yOffset,
- motionEntry->xPrecision,motionEntry->yPrecision,
- motionEntry->downTime,firstMotionSample->eventTime,
- motionEntry->pointerCount,motionEntry->pointerIds,
- firstMotionSample->pointerCoords);
Java代码
- ViewRoot有个InputHandler
Java代码
- privatefinalInputHandlermInputHandler=newInputHandler(){
- publicvoidhandleKey(KeyEventevent,RunnablefinishedCallback){
- startInputEvent(finishedCallback);
- dispatchKey(event,true);
- }
- publicvoidhandleMotion(MotionEventevent,RunnablefinishedCallback){
- startInputEvent(finishedCallback);
- dispatchMotion(event,true);
- }
- };
InputHandler注册给了系统
Java代码- InputQueue.registerInputChannel(mInputChannel,mInputHandler,
- Looper.myQueue());
Java代码
- dispatchMotion(event,true);方法如下
- rivatevoiddispatchMotion(MotionEventevent,booleansendDone){
- intsource=event.getSource();
- if((source&InputDevice.SOURCE_CLASS_POINTER)!=0){
- dispatchPointer(event,sendDone);
- }elseif((source&InputDevice.SOURCE_CLASS_TRACKBALL)!=0){
- dispatchTrackball(event,sendDone);
- }else{
- //TODO
- Log.v(TAG,"Droppingunsupportedmotionevent(unimplemented):"+event);
- if(sendDone){
- finishInputEvent();
- }
- }
- }
调用了dispatchPointer
ViewRoot本身就是Handler直接sendMessageAtTime
然后就进入了View的焦点系统。
下面就说一下Activity的焦点是怎么回事。
Java代码- InputDisapatcher.cpp中调用了如下方法
- dispatchEventToCurrentInputTargetsLocked(currentTime,motionEntry,
- true/*resumeWithAppendedMotionSample*/);
然后
Java代码- dispatchEventToCurrentInputTargetsLocked
调用了如下方法
Java代码- int32_tInputDispatcher::findFocusedWindowTargetsLocked(nsecs_tcurrentTime,
- constEventEntry*entry,nsecs_t*nextWakeupTime){
- mCurrentInputTargets.clear();
- int32_tinjectionResult;
- //Ifthereisnocurrentlyfocusedwindowandnofocusedapplication
- //thendroptheevent.
- if(!mFocusedWindow){
- if(mFocusedApplication){
- #ifDEBUG_FOCUS
- LOGD("Waitingbecausethereisnofocusedwindowbutthereisa"
- "focusedapplicationthatmayeventuallyaddawindow:%s.",
- getApplicationWindowLabelLocked(mFocusedApplication,NULL).string());
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- mFocusedApplication,NULL,nextWakeupTime);
- gotoUnresponsive;
- }
- LOGI("Droppingeventbecausethereisnofocusedwindoworfocusedapplication.");
- injectionResult=INPUT_EVENT_INJECTION_FAILED;
- gotoFailed;
- }
- //Checkpermissions.
- if(!checkInjectionPermission(mFocusedWindow,entry->injectionState)){
- injectionResult=INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- gotoFailed;
- }
- //Ifthecurrentlyfocusedwindowispausedthenkeepwaiting.
- if(mFocusedWindow->paused){
- #ifDEBUG_FOCUS
- LOGD("Waitingbecausefocusedwindowispaused.");
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- mFocusedApplication,mFocusedWindow,nextWakeupTime);
- gotoUnresponsive;
- }
- //Ifthecurrentlyfocusedwindowisstillworkingonpreviouseventsthenkeepwaiting.
- if(!isWindowFinishedWithPreviousInputLocked(mFocusedWindow)){
- #ifDEBUG_FOCUS
- LOGD("Waitingbecausefocusedwindowstillprocessingpreviousinput.");
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- mFocusedApplication,mFocusedWindow,nextWakeupTime);
- gotoUnresponsive;
- }
- //Success!Outputtargets.
- injectionResult=INPUT_EVENT_INJECTION_SUCCEEDED;
- addWindowTargetLocked(mFocusedWindow,InputTarget::FLAG_FOREGROUND,BitSet32(0));
- //Done.
- Failed:
- Unresponsive:
- nsecs_ttimeSpentWaitingForApplication=getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime,entry,
- injectionResult,timeSpentWaitingForApplication);
- #ifDEBUG_FOCUS
- LOGD("findFocusedWindowfinished:injectionResult=%d,"
- "timeSpendWaitingForApplication=%0.1fms",
- injectionResult,timeSpentWaitingForApplication/1000000.0);
- #endif
- returninjectionResult;
- }
move事件的处理和Down事件的处理很不相同。
新建立的Window在处理焦点的时候,按下事件没有起来之前,保持了原来的焦点窗口。除非ACTION_UP事件收到以后
Java代码- /*Updatesthecachedwindowinformationprovidedtotheinputdispatcher.*/
- publicvoidupdateInputWindowsLw(){
- //Populatetheinputwindowlistwithinformationaboutallofthewindowsthat
- //couldpotentiallyreceiveinput.
- //Asanoptimization,wecouldtrytoprunethelistofwindowsbutthisturns
- //outtobedifficultbecauseonlythenativecodeknowsforsurewhichwindow
- //currentlyhastouchfocus.
- finalArrayList<WindowState>windows=mWindows;
- finalintN=windows.size();
- for(inti=N-1;i>=0;i--){
- finalWindowStatechild=windows.get(i);
- if(child.mInputChannel==null||child.mRemoved){
- //Skipthiswindowbecauseitcannotpossiblyreceiveinput.
- continue;
- }
- finalintflags=child.mAttrs.flags;
- finalinttype=child.mAttrs.type;
- finalbooleanhasFocus=(child==mInputFocus);
- finalbooleanisVisible=child.isVisibleLw();
- finalbooleanhasWallpaper=(child==mWallpaperTarget)
- &&(type!=WindowManager.LayoutParams.TYPE_KEYGUARD);
- //Addawindowtoourlistofinputwindows.
- finalInputWindowinputWindow=mTempInputWindows.add();
- inputWindow.inputChannel=child.mInputChannel;
- inputWindow.name=child.toString();
- inputWindow.layoutParamsFlags=flags;
- inputWindow.layoutParamsType=type;
- inputWindow.dispatchingTimeoutNanos=child.getInputDispatchingTimeoutNanos();
- inputWindow.visible=isVisible;
- inputWindow.canReceiveKeys=child.canReceiveKeys();
- inputWindow.hasFocus=hasFocus;
- inputWindow.hasWallpaper=hasWallpaper;
- inputWindow.paused=child.mAppToken!=null?child.mAppToken.paused:false;
- inputWindow.layer=child.mLayer;
- inputWindow.ownerPid=child.mSession.mPid;
- inputWindow.ownerUid=child.mSession.mUid;
- finalRectframe=child.mFrame;
- inputWindow.frameLeft=frame.left;
- inputWindow.frameTop=frame.top;
- inputWindow.frameRight=frame.right;
- inputWindow.frameBottom=frame.bottom;
- finalRectvisibleFrame=child.mVisibleFrame;
- inputWindow.visibleFrameLeft=visibleFrame.left;
- inputWindow.visibleFrameTop=visibleFrame.top;
- inputWindow.visibleFrameRight=visibleFrame.right;
- inputWindow.visibleFrameBottom=visibleFrame.bottom;
- switch(child.mTouchableInsets){
- default:
- caseViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
- inputWindow.touchableAreaLeft=frame.left;
- inputWindow.touchableAreaTop=frame.top;
- inputWindow.touchableAreaRight=frame.right;
- inputWindow.touchableAreaBottom=frame.bottom;
- break;
- caseViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:{
- Rectinset=child.mGivenContentInsets;
- inputWindow.touchableAreaLeft=frame.left+inset.left;
- inputWindow.touchableAreaTop=frame.top+inset.top;
- inputWindow.touchableAreaRight=frame.right-inset.right;
- inputWindow.touchableAreaBottom=frame.bottom-inset.bottom;
- break;
- }
- caseViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:{
- Rectinset=child.mGivenVisibleInsets;
- inputWindow.touchableAreaLeft=frame.left+inset.left;
- inputWindow.touchableAreaTop=frame.top+inset.top;
- inputWindow.touchableAreaRight=frame.right-inset.right;
- inputWindow.touchableAreaBottom=frame.bottom-inset.bottom;
- break;
- }
- }
- }
- //Sendwindowstonativecode.
- mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
- //Clearthelistinpreparationforthenextround.
- //AlsoavoidskeepingInputChannelobjectsreferencedunnecessarily.
- mTempInputWindows.clear();
- }
真正的Input的控制是通过以下方式
/**
* Z-ordered (bottom-most first) list of all Window objects.
*/
final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
- /**
- *Z-ordered(bottom-mostfirst)listofallWindowobjects.
- */
- finalArrayList<WindowState>mWindows=newArrayList<WindowState>();
另外的touch的target并不是通过input focus 获得的。而是通过visible来获得
Java代码- int32_tInputDispatcher::findTouchedWindowTargetsLocked(nsecs_tcurrentTime,
- constMotionEntry*entry,nsecs_t*nextWakeupTime){
- enumInjectionPermission{
- INJECTION_PERMISSION_UNKNOWN,
- INJECTION_PERMISSION_GRANTED,
- INJECTION_PERMISSION_DENIED
- };
- mCurrentInputTargets.clear();
- nsecs_tstartTime=now();
- //Forsecurityreasons,wedeferupdatingthetouchstateuntilwearesurethat
- //eventinjectionwillbeallowed.
- //
- //FIXMEIntheoriginalcode,screenWasOffcouldneverbesettotrue.
- //ThereasonisthatthePOLICY_FLAG_WOKE_HERE
- //andPOLICY_FLAG_BRIGHT_HEREflagsweresetonlywhenpreprocessingraw
- //EV_KEY,EV_RELandEV_ABSevents.Asithappens,thetoucheventwas
- //actuallyenqueuedusingthepolicyFlagsthatappearedinthefinalEV_SYN
- //eventsuponwhichnopreprocessingtookplace.SopolicyFlagswasalways0.
- //Inthenewnativeinputdispatcherwe'reabitmorecarefulaboutevent
- //preprocessingsothetoucheswereceivecanactuallyhavenon-zeropolicyFlags.
- //Unfortunatelyweobtainundesirablebehavior.
- //
- //Here'swhathappens:
- //
- //Whenthedevicedimsinanticipationofgoingtosleep,touches
- //inwindowswhichhaveFLAG_TOUCHABLE_WHEN_WAKINGcause
- //thedevicetobrightenandresettheuseractivitytimer.
- //Touchesonotherwindows(suchasthelauncherwindow)
- //aredropped.Thenafteramoment,thedevicegoestosleep.Oops.
- //
- //AlsonoticehowscreenWasOffwasbeinginitializedusingPOLICY_FLAG_BRIGHT_HERE
- //insteadofPOLICY_FLAG_WOKE_HERE...
- //
- boolscreenWasOff=false;//originalpolicy:policyFlags&POLICY_FLAG_BRIGHT_HERE;
- int32_taction=entry->action;
- int32_tmaskedAction=action&AMOTION_EVENT_ACTION_MASK;
- //Updatethetouchstateasneededbasedonthepropertiesofthetouchevent.
- int32_tinjectionResult=INPUT_EVENT_INJECTION_PENDING;
- InjectionPermissioninjectionPermission=INJECTION_PERMISSION_UNKNOWN;
- if(maskedAction==AMOTION_EVENT_ACTION_DOWN){
- mTempTouchState.reset();
- mTempTouchState.down=true;
- }else{
- mTempTouchState.copyFrom(mTouchState);
- }
- boolisSplit=mTempTouchState.split&&mTempTouchState.down;
- if(maskedAction==AMOTION_EVENT_ACTION_DOWN
- ||(isSplit&&maskedAction==AMOTION_EVENT_ACTION_POINTER_DOWN)){
- /*Case1:Newsplittablepointergoingdown.*/
- int32_tpointerIndex=getMotionEventActionPointerIndex(action);
- int32_tx=int32_t(entry->firstSample.pointerCoords[pointerIndex].x);
- int32_ty=int32_t(entry->firstSample.pointerCoords[pointerIndex].y);
- constInputWindow*newTouchedWindow=NULL;
- constInputWindow*topErrorWindow=NULL;
- //Traversewindowsfromfronttobacktofindtouchedwindowandoutsidetargets.
- size_tnumWindows=mWindows.size();
- for(size_ti=0;i<numWindows;i++){
- constInputWindow*window=&mWindows.editItemAt(i);
- int32_tflags=window->layoutParamsFlags;
- if(flags&InputWindow::FLAG_SYSTEM_ERROR){
- if(!topErrorWindow){
- topErrorWindow=window;
- }
- }
- if(window->visible){
- if(!(flags&InputWindow::FLAG_NOT_TOUCHABLE)){
- boolisTouchModal=(flags&(InputWindow::FLAG_NOT_FOCUSABLE
- |InputWindow::FLAG_NOT_TOUCH_MODAL))==0;
- if(isTouchModal||window->touchableAreaContainsPoint(x,y)){
- if(!screenWasOff||flags&InputWindow::FLAG_TOUCHABLE_WHEN_WAKING){
- newTouchedWindow=window;
- }
- break;//foundtouchedwindow,exitwindowloop
- }
- }
- if(maskedAction==AMOTION_EVENT_ACTION_DOWN
- &&(flags&InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)){
- int32_toutsideTargetFlags=InputTarget::FLAG_OUTSIDE;
- if(isWindowObscuredAtPointLocked(window,x,y)){
- outsideTargetFlags|=InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
- mTempTouchState.addOrUpdateWindow(window,outsideTargetFlags,BitSet32(0));
- }
- }
- }
- //Ifthereisanerrorwindowbutitisnottakingfocus(typicallybecause
- //itisinvisible)thenwaitforit.Anyotherfocusedwindowmayin
- //factbeinANRstate.
- if(topErrorWindow&&newTouchedWindow!=topErrorWindow){
- #ifDEBUG_FOCUS
- LOGD("Waitingbecausesystemerrorwindowispending.");
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- NULL,NULL,nextWakeupTime);
- injectionPermission=INJECTION_PERMISSION_UNKNOWN;
- gotoUnresponsive;
- }
- //Figureoutwhethersplittingwillbeallowedforthiswindow.
- if(newTouchedWindow
- &&(newTouchedWindow->layoutParamsFlags&InputWindow::FLAG_SPLIT_TOUCH)){
- //Newwindowsupportssplitting.
- isSplit=true;
- }elseif(isSplit){
- //Newwindowdoesnotsupportsplittingbutwehavealreadysplitevents.
- //Assignthepointertothefirstforegroundwindowwefind.
- //(MaybeNULLwhichiswhyweputthiscodeblockbeforethenextcheck.)
- newTouchedWindow=mTempTouchState.getFirstForegroundWindow();
- }
- //Ifwedidnotfindatouchedwindowthenfail.
- if(!newTouchedWindow){
- if(mFocusedApplication){
- #ifDEBUG_FOCUS
- LOGD("Waitingbecausethereisnotouchedwindowbutthereisa"
- "focusedapplicationthatmayeventuallyaddanewwindow:%s.",
- getApplicationWindowLabelLocked(mFocusedApplication,NULL).string());
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- mFocusedApplication,NULL,nextWakeupTime);
- gotoUnresponsive;
- }
- LOGI("Droppingeventbecausethereisnotouchedwindoworfocusedapplication.");
- injectionResult=INPUT_EVENT_INJECTION_FAILED;
- gotoFailed;
- }
- //Settargetflags.
- int32_ttargetFlags=InputTarget::FLAG_FOREGROUND;
- if(isSplit){
- targetFlags|=InputTarget::FLAG_SPLIT;
- }
- if(isWindowObscuredAtPointLocked(newTouchedWindow,x,y)){
- targetFlags|=InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
- //Updatethetemporarytouchstate.
- BitSet32pointerIds;
- if(isSplit){
- uint32_tpointerId=entry->pointerIds[pointerIndex];
- pointerIds.markBit(pointerId);
- }
- mTempTouchState.addOrUpdateWindow(newTouchedWindow,targetFlags,pointerIds);
- }else{
- /*Case2:Pointermove,up,cancelornon-splittablepointerdown.*/
- //Ifthepointerisnotcurrentlydown,thenignoretheevent.
- if(!mTempTouchState.down){
- LOGI("Droppingeventbecausethepointerisnotdown.");
- injectionResult=INPUT_EVENT_INJECTION_FAILED;
- gotoFailed;
- }
- }
- //Checkpermissiontoinjectintoalltouchedforegroundwindowsandensurethere
- //isatleastonetouchedforegroundwindow.
- {
- boolhaveForegroundWindow=false;
- for(size_ti=0;i<mTempTouchState.windows.size();i++){
- constTouchedWindow&touchedWindow=mTempTouchState.windows[i];
- if(touchedWindow.targetFlags&InputTarget::FLAG_FOREGROUND){
- haveForegroundWindow=true;
- if(!checkInjectionPermission(touchedWindow.window,entry->injectionState)){
- injectionResult=INPUT_EVENT_INJECTION_PERMISSION_DENIED;
- injectionPermission=INJECTION_PERMISSION_DENIED;
- gotoFailed;
- }
- }
- }
- if(!haveForegroundWindow){
- #ifDEBUG_INPUT_DISPATCHER_POLICY
- LOGD("Droppingeventbecausethereisnotouchedforegroundwindowtoreceiveit.");
- #endif
- injectionResult=INPUT_EVENT_INJECTION_FAILED;
- gotoFailed;
- }
- //Permissiongrantedtoinjectionintoalltouchedforegroundwindows.
- injectionPermission=INJECTION_PERMISSION_GRANTED;
- }
- //Ensurealltouchedforegroundwindowsarereadyfornewinput.
- for(size_ti=0;i<mTempTouchState.windows.size();i++){
- constTouchedWindow&touchedWindow=mTempTouchState.windows[i];
- if(touchedWindow.targetFlags&InputTarget::FLAG_FOREGROUND){
- //Ifthetouchedwindowispausedthenkeepwaiting.
- if(touchedWindow.window->paused){
- #ifDEBUG_INPUT_DISPATCHER_POLICY
- LOGD("Waitingbecausetouchedwindowispaused.");
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- NULL,touchedWindow.window,nextWakeupTime);
- gotoUnresponsive;
- }
- //Ifthetouchedwindowisstillworkingonpreviouseventsthenkeepwaiting.
- if(!isWindowFinishedWithPreviousInputLocked(touchedWindow.window)){
- #ifDEBUG_FOCUS
- LOGD("Waitingbecausetouchedwindowstillprocessingpreviousinput.");
- #endif
- injectionResult=handleTargetsNotReadyLocked(currentTime,entry,
- NULL,touchedWindow.window,nextWakeupTime);
- gotoUnresponsive;
- }
- }
- }
- //Ifthisisthefirstpointergoingdownandthetouchedwindowhasawallpaper
- //thenalsoaddthetouchedwallpaperwindowssotheyarelockedinfortheduration
- //ofthetouchgesture.
- if(maskedAction==AMOTION_EVENT_ACTION_DOWN){
- constInputWindow*foregroundWindow=mTempTouchState.getFirstForegroundWindow();
- if(foregroundWindow->hasWallpaper){
- for(size_ti=0;i<mWindows.size();i++){
- constInputWindow*window=&mWindows[i];
- if(window->layoutParamsType==InputWindow::TYPE_WALLPAPER){
- mTempTouchState.addOrUpdateWindow(window,
- InputTarget::FLAG_WINDOW_IS_OBSCURED,BitSet32(0));
- }
- }
- }
- }
- //Success!Outputtargets.
- injectionResult=INPUT_EVENT_INJECTION_SUCCEEDED;
- for(size_ti=0;i<mTempTouchState.windows.size();i++){
- constTouchedWindow&touchedWindow=mTempTouchState.windows.itemAt(i);
- addWindowTargetLocked(touchedWindow.window,touchedWindow.targetFlags,
- touchedWindow.pointerIds);
- }
- //Droptheoutsidetouchwindowsincewewillnotcareabouttheminthenextiteration.
- mTempTouchState.removeOutsideTouchWindows();
- Failed:
- //Checkinjectionpermissiononceandforall.
- if(injectionPermission==INJECTION_PERMISSION_UNKNOWN){
- if(checkInjectionPermission(NULL,entry->injectionState)){
- injectionPermission=INJECTION_PERMISSION_GRANTED;
- }else{
- injectionPermission=INJECTION_PERMISSION_DENIED;
- }
- }
- //Updatefinalpiecesoftouchstateiftheinjectorhadpermission.
- if(injectionPermission==INJECTION_PERMISSION_GRANTED){
- if(maskedAction==AMOTION_EVENT_ACTION_UP
- ||maskedAction==AMOTION_EVENT_ACTION_CANCEL){
- //Allpointersuporcanceled.
- mTempTouchState.reset();
- }elseif(maskedAction==AMOTION_EVENT_ACTION_DOWN){
- //Firstpointerwentdown.
- if(mTouchState.down){
- #ifDEBUG_FOCUS
- LOGD("Pointerdownreceivedwhilealreadydown.");
- #endif
- }
- }elseif(maskedAction==AMOTION_EVENT_ACTION_POINTER_UP){
- //Onepointerwentup.
- if(isSplit){
- int32_tpointerIndex=getMotionEventActionPointerIndex(action);
- uint32_tpointerId=entry->pointerIds[pointerIndex];
- for(size_ti=0;i<mTempTouchState.windows.size();){
- TouchedWindow&touchedWindow=mTempTouchState.windows.editItemAt(i);
- if(touchedWindow.targetFlags&InputTarget::FLAG_SPLIT){
- touchedWindow.pointerIds.clearBit(pointerId);
- if(touchedWindow.pointerIds.isEmpty()){
- mTempTouchState.windows.removeAt(i);
- continue;
- }
- }
- i+=1;
- }
- }
- }
- //Savechangestotouchstate.
- mTouchState.copyFrom(mTempTouchState);
- }else{
- #ifDEBUG_FOCUS
- LOGD("Notupdatingtouchfocusbecauseinjectionwasdenied.");
- #endif
- }
- Unresponsive:
- //Resettemporarytouchstatetoensurewereleaseunnecessaryreferencestoinputchannels.
- mTempTouchState.reset();
- nsecs_ttimeSpentWaitingForApplication=getTimeSpentWaitingForApplicationLocked(currentTime);
- updateDispatchStatisticsLocked(currentTime,entry,
- injectionResult,timeSpentWaitingForApplication);
- #ifDEBUG_FOCUS
- LOGD("findTouchedWindowfinished:injectionResult=%d,injectionPermission=%d,"
- "timeSpentWaitingForApplication=%0.1fms",
- injectionResult,injectionPermission,timeSpentWaitingForApplication/1000000.0);
- #endif
- returninjectionResult;
- }
最关键的几行代码,说明了Windows是如何找到触屏的输入焦点的:
Cpp代码- if(window->visible){
- if(!(flags&InputWindow::FLAG_NOT_TOUCHABLE)){
- boolisTouchModal=(flags&(InputWindow::FLAG_NOT_FOCUSABLE
- |InputWindow::FLAG_NOT_TOUCH_MODAL))==0;
- if(isTouchModal||window->touchableAreaContainsPoint(x,y)){
- if(!screenWasOff||flags&InputWindow::FLAG_TOUCHABLE_WHEN_WAKING){
- newTouchedWindow=window;
- }
- break;//foundtouchedwindow,exitwindowloop
- }
- }
- if(maskedAction==AMOTION_EVENT_ACTION_DOWN
- &&(flags&InputWindow::FLAG_WATCH_OUTSIDE_TOUCH)){
- int32_toutsideTargetFlags=InputTarget::FLAG_OUTSIDE;
- if(isWindowObscuredAtPointLocked(window,x,y)){
- outsideTargetFlags|=InputTarget::FLAG_WINDOW_IS_OBSCURED;
- }
- mTempTouchState.addOrUpdateWindow(window,outsideTargetFlags,BitSet32(0));
- }
- }
Java代码
- //Focustrackingfortouch.
- structTouchedWindow{
- constInputWindow*window;
- int32_ttargetFlags;
- BitSet32pointerIds;
- sp<InputChannel>channel;
- };
- structTouchState{
- booldown;
- boolsplit;
- Vector<TouchedWindow>windows;
- TouchState();
- ~TouchState();
- voidreset();
- voidcopyFrom(constTouchState&other);
- voidaddOrUpdateWindow(constInputWindow*window,int32_ttargetFlags,BitSet32pointerIds);
- voidremoveOutsideTouchWindows();
- constInputWindow*getFirstForegroundWindow();
- };
- 另外如何定义按键和其他触屏焦点的:
- /*Updatesthecachedwindowinformationprovidedtotheinputdispatcher.*/
- publicvoidupdateInputWindowsLw(){
- //Populatetheinputwindowlistwithinformationaboutallofthewindowsthat
- //couldpotentiallyreceiveinput.
- //Asanoptimization,wecouldtrytoprunethelistofwindowsbutthisturns
- //outtobedifficultbecauseonlythenativecodeknowsforsurewhichwindow
- //currentlyhastouchfocus.
- finalArrayList<WindowState>windows=mWindows;
- finalintN=windows.size();
- for(inti=N-1;i>=0;i--){
- finalWindowStatechild=windows.get(i);
- if(child.mInputChannel==null||child.mRemoved){
- //Skipthiswindowbecauseitcannotpossiblyreceiveinput.
- continue;
- }
- finalintflags=child.mAttrs.flags;
- finalinttype=child.mAttrs.type;
- <spanstyle="color:#ff6600;">finalbooleanhasFocus=(child==mInputFocus);</span>
- //本行代码确定,一次性的focusWindow只有一个。
- finalbooleanisVisible=child.isVisibleLw();
- finalbooleanhasWallpaper=(child==mWallpaperTarget)
- &&(type!=WindowManager.LayoutParams.TYPE_KEYGUARD);
更多相关文章
- Android(安卓)特殊用法--来自中国移动开发社区
- 菜鸟学Android开发系列之:发送短信拨打电话
- 〖Android〗/system/etc/event-log-tags
- Android(安卓)progressBar代码设置进度条颜色、背景颜色以及圆角
- 求 在独立service 中 调用contentprovider的方法
- Android实现系统打印功能
- Android(安卓)中的BroadCastReceiver
- Android(安卓)- Handler is abstract, cannot be instantiated.
- 查询存储空间的代码