droid应用程序键盘(Keyboard)消息处理机制分析(10)
Step 2.ViewRoot.requestLayout 这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中: publicfinalclassViewRootextendsHandlerimplementsViewParent, View.AttachInfo.Callbacks{ ...... publicvoidrequestLayout(){ ...... mLayoutRequested=true; scheduleTraversals(); } ...... } 这个函数调用了scheduleTraversals函数来进一步执行操作,由于篇幅关系,我们就不详细描述scheduleTraversals函数了,简单来说,在scheduleTraversals函数中,会通过sendEmptyMessage(DO_TRAVERSAL)发送一个消息到应用程序的消息队列中,这个消息最终由ViewRoot的handleMessage函数处理,而ViewRoot的handleMessage函数把这个消息交给ViewRoot类的performTraversals来处理,在performTraversals函数中,又会调用ViewRoot类的relayoutWindow函数来进一步执行操作,最后在relayoutWindow函数中,就会通过WindowManagerService内部类Session的远程接口sWindowSession的relayout函数来进入到WindowManagerService中。 Step 3.WindowManagerService.Session.relayout 这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中: publicclassWindowManagerServiceextendsIWindowManager.Stub implementsWatchdog.Monitor{ ...... privatefinalclassSessionextendsIWindowSession.Stub implementsIBinder.DeathRecipient{ ...... publicintrelayout(IWindowwindow,WindowManager.LayoutParamsattrs, intrequestedWidth,intrequestedHeight,intviewFlags, booleaninsetsPending,RectoutFrame,RectoutContentInsets, RectoutVisibleInsets,ConfigurationoutConfig,SurfaceoutSurface){ //Log.d(TAG,">>>>>>ENTEREDrelayoutfrom"+Binder.getCallingPid()); intres=relayoutWindow(this,window,attrs, requestedWidth,requestedHeight,viewFlags,insetsPending, outFrame,outContentInsets,outVisibleInsets,outConfig,outSurface); //Log.d(TAG,"<<<<<<EXITINGrelayoutto"+Binder.getCallingPid()); returnres; } ...... } ...... } 这个函数只是简单地调用WindowManagerService的成员函数relayoutWIndow来进一步处理。 Step 4.WindowManagerService.relayoutWIndow 这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中: publicclassWindowManagerServiceextendsIWindowManager.Stub implementsWatchdog.Monitor{ ...... publicintrelayoutWindow(Sessionsession,IWindowclient, WindowManager.LayoutParamsattrs,intrequestedWidth, intrequestedHeight,intviewVisibility,booleaninsetsPending, RectoutFrame,RectoutContentInsets,RectoutVisibleInsets, ConfigurationoutConfig,SurfaceoutSurface){ ...... synchronized(mWindowMap){ ...... mInputMonitor.updateInputWindowsLw(); } ...... } ...... } 这个函数又会继续调用mInputMonitor的updateInputWindowsLw成员函数来更新当前的输入窗口,mInputMonitor是WindowManagerService的成员变量,它的类型为InputMonitor。 Step 5.InputMonitor.updateInputWindowsLw 这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中: publicclassWindowManagerServiceextendsIWindowManager.Stub implementsWatchdog.Monitor{ ...... finalclassInputMonitor{ ...... /*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; } ...... //Addawindowtoourlistofinputwindows. finalInputWindowinputWindow=mTempInputWindows.add(); ...... } //Sendwindowstonativecode. mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray()); ...... } ...... } ...... } 这个函数将当前系统中带有InputChannel的Activity窗口都设置为InputManager的输入窗口,但是后面我们会看到,只有当前激活的窗口才会响应键盘消息。 Step 6.InputManager.setInputWindows 这个函数定义在frameworks/base/services/java/com/android/server/InputManager.java文件中: publicclassInputManager{ ...... publicvoidsetInputWindows(InputWindow[]windows){ nativeSetInputWindows(windows); } ...... } 这个函数调用了本地方法nativeSetInputWindows来进一步执行操作。 Step 7.InputManager.nativeSetInputWindows 这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp文件中: staticvoidandroid_server_InputManager_nativeSetInputWindows(JNIEnv*env,jclassclazz, jobjectArraywindowObjArray){ if(checkInputManagerUnitialized(env)){ return; } gNativeInputManager->setInputWindows(env,windowObjArray); } 这里的gNativeInputManager我们前面分析InputManager的启动过程时已经见过了,这是一个本地InputManager对象,通过它进一步设置当前系统的输入窗口。 本文转自 Luoshengyang 51CTO博客,原文链接:xxxxxxx,如需转载请自行联系原作者