Android应用程序键盘(Keyboard)消息处理机制分析(10)

Step 2. ViewRoot.requestLayout
这个函数定义在frameworks/base/core/java/android/view/ViewRoot.java文件中:
  1. public final class ViewRoot extends Handler implements ViewParent,  
  2.         View.AttachInfo.Callbacks {  
  3.     ......  
  4.   
  5.     public void requestLayout() {  
  6.         ......  
  7.         mLayoutRequested = true;  
  8.         scheduleTraversals();  
  9.     }  
  10.   
  11.     ......  
  12. }  
         这个函数调用了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 文件中:
  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     private final class Session extends IWindowSession.Stub  
  6.             implements IBinder.DeathRecipient {  
  7.         ......  
  8.   
  9.         public int relayout(IWindow window, WindowManager.LayoutParams attrs,  
  10.                 int requestedWidth, int requestedHeight, int viewFlags,  
  11.                 boolean insetsPending, Rect outFrame, Rect outContentInsets,  
  12.                 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {  
  13.             //Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());  
  14.             int res = relayoutWindow(this, window, attrs,  
  15.                     requestedWidth, requestedHeight, viewFlags, insetsPending,  
  16.                     outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);  
  17.             //Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());  
  18.             return res;  
  19.         }  
  20.   
  21.         ......  
  22.     }  
  23.   
  24.     ......  
  25. }  

 

        这个函数只是简单地调用WindowManagerService的成员函数relayoutWIndow来进一步处理。
        Step 4. WindowManagerService.relayoutWIndow
        这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java 文件中:
  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     public int relayoutWindow(Session session, IWindow client,  
  6.             WindowManager.LayoutParams attrs, int requestedWidth,  
  7.             int requestedHeight, int viewVisibility, boolean insetsPending,  
  8.             Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,  
  9.             Configuration outConfig, Surface outSurface) {  
  10.         ......  
  11.   
  12.         synchronized(mWindowMap) {  
  13.             ......  
  14.   
  15.             mInputMonitor.updateInputWindowsLw();  
  16.         }  
  17.   
  18.         ......  
  19.     }  
  20.   
  21.     ......  
  22. }  
         这个函数又会继续调用mInputMonitor的updateInputWindowsLw成员函数来更新当前的输入窗口,mInputMonitor是WindowManagerService的成员变量,它的类型为InputMonitor。
 
         Step 5. InputMonitor.updateInputWindowsLw
         这个函数定义在frameworks/base/services/java/com/android/server/WindowManagerService.java 文件中:
  1. public class WindowManagerService extends IWindowManager.Stub  
  2.         implements Watchdog.Monitor {  
  3.     ......  
  4.   
  5.     final class InputMonitor {  
  6.         ......  
  7.   
  8.         /* Updates the cached window information provided to the input dispatcher. */  
  9.         public void updateInputWindowsLw() {  
  10.             // Populate the input window list with information about all of the windows that  
  11.             // could potentially receive input.  
  12.             // As an optimization, we could try to prune the list of windows but this turns  
  13.             // out to be difficult because only the native code knows for sure which window  
  14.             // currently has touch focus.  
  15.             final ArrayList<WindowState> windows = mWindows;  
  16.             final int N = windows.size();  
  17.             for (int i = N - 1; i >= 0; i--) {  
  18.                 final WindowState child = windows.get(i);  
  19.                 if (child.mInputChannel == null || child.mRemoved) {  
  20.                     // Skip this window because it cannot possibly receive input.  
  21.                     continue;  
  22.                 }  
  23.   
  24.                 ......  
  25.   
  26.                 // Add a window to our list of input windows.  
  27.                 final InputWindow inputWindow = mTempInputWindows.add();  
  28.   
  29.                 ......  
  30.             }  
  31.   
  32.             // Send windows to native code.  
  33.             mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());  
  34.   
  35.             ......  
  36.         }  
  37.   
  38.         ......  
  39.     }  
  40.   
  41.     ......  
  42. }  
        这个函数将当前系统中带有InputChannel的Activity窗口都设置为InputManager的输入窗口,但是后面我们会看到,只有当前激活的窗口才会响应键盘消息。
 
        Step 6. InputManager.setInputWindows
        这个函数定义在frameworks/base/services/java/com/android/server/InputManager.java文件中:
  1. public class InputManager {  
  2.     ......  
  3.   
  4.     public void setInputWindows(InputWindow[] windows) {  
  5.         nativeSetInputWindows(windows);  
  6.     }  
  7.   
  8.     ......  
  9. }  
        这个函数调用了本地方法nativeSetInputWindows来进一步执行操作。
        Step 7. InputManager.nativeSetInputWindows
 
        这个函数定义在frameworks/base/services/jni/com_android_server_InputManager.cpp 文件中:
  1. static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,  
  2.         jobjectArray windowObjArray) {  
  3.     if (checkInputManagerUnitialized(env)) {  
  4.         return;  
  5.     }  
  6.   
  7.     gNativeInputManager->setInputWindows(env, windowObjArray);  
  8. }  
        这里的gNativeInputManager我们前面分析InputManager的启动过程时已经见过了,这是一个本地InputManager对象,通过它进一步设置当前系统的输入窗口。

 

你可能感兴趣的:(android,keyboard,消息处理机制分析)