Step 8.NativeInputManager.setInputWindows 这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp文件中:
  1. voidNativeInputManager::setInputWindows(JNIEnv*env,jobjectArraywindowObjArray){
  2. Vector<InputWindow>windows;
  3. jsizelength=env->GetArrayLength(windowObjArray);
  4. for(jsizei=0;i<length;i++){
  5. jobjectinputTargetObj=env->GetObjectArrayElement(windowObjArray,i);
  6. if(!inputTargetObj){
  7. break;//foundnullelementindicatingendofusedportionofthearray
  8. }
  9. windows.push();
  10. InputWindow&window=windows.editTop();
  11. boolvalid=populateWindow(env,inputTargetObj,window);
  12. if(!valid){
  13. windows.pop();
  14. }
  15. env->DeleteLocalRef(inputTargetObj);
  16. }
  17. mInputManager->getDispatcher()->setInputWindows(windows);
  18. }
这个函数首先将Java层的Window转换成C++层的InputWindow,然后放在windows向量中,最后将这些输入窗口设置到InputDispatcher中去。 Step 9. InputDispatcher.setInputWindows 这个函数定义在frameworks/base/libs/ui/InputDispatcher.cpp文件中:
  1. voidInputDispatcher::setInputWindows(constVector<InputWindow>&inputWindows){
  2. ......
  3. {//acquirelock
  4. AutoMutex_l(mLock);
  5. //Clearoldwindowpointers.
  6. sp<InputChannel>oldFocusedWindowChannel;
  7. if(mFocusedWindow){
  8. oldFocusedWindowChannel=mFocusedWindow->inputChannel;
  9. mFocusedWindow=NULL;
  10. }
  11. mWindows.clear();
  12. //Loopovernewwindowsandrebuildthenecessarywindowpointersfor
  13. //trackingfocusandtouch.
  14. mWindows.appendVector(inputWindows);
  15. size_tnumWindows=mWindows.size();
  16. for(size_ti=0;i<numWindows;i++){
  17. constInputWindow*window=&mWindows.itemAt(i);
  18. if(window->hasFocus){
  19. mFocusedWindow=window;
  20. break;
  21. }
  22. }
  23. ......
  24. }//releaselock
  25. ......
  26. }
这里InputDispatcher的成员变量mFocusedWindow就代表当前激活的窗口的。这个函数首先清空mFocusedWindow,然后再通过一个for循环检查当前的输入窗口中的哪一个窗口是获得焦点的,获得焦点的输入窗口即为当前激活的窗口。 这样,InputManager就把当前激活的Activity窗口保存在InputDispatcher中了,后面就可以把键盘消息分发给它来处理。 回到Step 1中的ViewRoot.setView函数中,接下来就调用下面语句来注册键盘消息接收通道的一端到InputManager中去:
  1. mInputChannel=newInputChannel();
  2. try{
  3. res=sWindowSession.add(mWindow,mWindowAttributes,
  4. getHostVisibility(),mAttachInfo.mContentInsets,
  5. mInputChannel);
  6. }catch(RemoteExceptione){
  7. ......
  8. }finally{
  9. ......
  10. }
前面说过,这里的sWindowSession是WindowManagerService内部类Session的一个远程接口,通过它可以进入到WindowManagerService中去。 Step 10.WindowManagerService.Session.add 这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:
  1. publicclassWindowManagerServiceextendsIWindowManager.Stub
  2. implementsWatchdog.Monitor{
  3. ......
  4. privatefinalclassSessionextendsIWindowSession.Stub
  5. implementsIBinder.DeathRecipient{
  6. ......
  7. publicintadd(IWindowwindow,WindowManager.LayoutParamsattrs,
  8. intviewVisibility,RectoutContentInsets,InputChanneloutInputChannel){
  9. returnaddWindow(this,window,attrs,viewVisibility,outContentInsets,
  10. outInputChannel);
  11. }
  12. ......
  13. }
  14. ......
  15. }
这里调用WindowManagerService类的addWindow函数来进一步执行操作。 Step 11.WindowManagerService.addWindow 这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java文件中:
  1. publicclassWindowManagerServiceextendsIWindowManager.Stub
  2. implementsWatchdog.Monitor{
  3. ......
  4. publicintaddWindow(Sessionsession,IWindowclient,
  5. WindowManager.LayoutParamsattrs,intviewVisibility,
  6. RectoutContentInsets,InputChanneloutInputChannel){
  7. ......
  8. WindowStatewin=null;
  9. synchronized(mWindowMap){
  10. ......
  11. win=newWindowState(session,client,token,
  12. attachedWindow,attrs,viewVisibility);
  13. ......
  14. if(outInputChannel!=null){
  15. Stringname=win.makeInputChannelName();
  16. InputChannel[]inputChannels=InputChannel.openInputChannelPair(name);
  17. win.mInputChannel=inputChannels[0];
  18. inputChannels[1].transferToBinderOutParameter(outInputChannel);
  19. mInputManager.registerInputChannel(win.mInputChannel);
  20. }
  21. ......
  22. }
  23. ......
  24. }
  25. ......
  26. }

这里的outInputChannel即为前面在Step 1中创建的InputChannel,它不为NULL,因此,这里会通过InputChannel.openInputChannelPair函数来创建一对输入通道,其中一个位于WindowManagerService中,另外一个通过outInputChannel参数返回到应用程序中:

  1. inputChannels[1].transferToBinderOutParameter(outInputChannel);

创建输入通道之前,WindowManagerService会为当前Activity窗口创建一个WindowState对象win,用来记录这个Activity窗口的状态信息。当创建这对输入管道成功以后,也会把其中的一个管道保存在这个WindowState对象win的成员变量mInputChannel中,后面要注销这个管道的时候,就是从这个WindownState对象中取回这个管道的:

  1. win.mInputChannel=inputChannels[0];

接下来我们就看一下InputChannel.openInputChannelPair函数的实现。

更多相关文章

  1. 输入法与窗口交互
  2. Android图形显示之本地窗口
  3. Android 抽象回调函数以及接口回调更新UI
  4. Android Render(一)Activity窗口构成和绘制解析
  5. Android 依赖注入函数库Roboguice(一)
  6. WindowManager实现悬浮窗口&可自由移动的悬浮窗口
  7. Android 的窗口管理系统 (View, Canvas, WindowManager)

随机推荐

  1. android:configChanges="orientation|key
  2. Android唯一标识
  3. 据9成手机操作系统份额的iOS和Android遇
  4. Android使用WebView浏览有声音或者视频的
  5. android 学习总结
  6. 挖掘更合适的MVP模式的架构设计
  7. Android上实现仿IOS弹性ListView
  8. android给listview的item设定高度
  9. Android 'showAsAction' in package 'and
  10. android图片特效处理之光晕效果