Step 2. ViewRoot.requestLayout
這個函數定義在frameworks/base/core/java/android/view/ViewRoot.java檔案中:
public final class ViewRoot extends Handler implements ViewParent,
View.AttachInfo.Callbacks {
......
public void requestLayout() {
......
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 檔案中:
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
private final class Session extends IWindowSession.Stub
implements IBinder.DeathRecipient {
public int relayout(IWindow window, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
boolean insetsPending, Rect outFrame, Rect outContentInsets,
Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
//Log.d(TAG, ">>>>>> ENTERED relayout from " + Binder.getCallingPid());
int res = relayoutWindow(this, window, attrs,
requestedWidth, requestedHeight, viewFlags, insetsPending,
outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
//Log.d(TAG, "<<<<<< EXITING relayout to " + Binder.getCallingPid());
return res;
}
這個函數隻是簡單地調用WindowManagerService的成員函數relayoutWIndow來進一步處理。
Step 4. WindowManagerService.relayoutWIndow
public int relayoutWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, boolean insetsPending,
Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Configuration outConfig, Surface outSurface) {
synchronized(mWindowMap) {
......
mInputMonitor.updateInputWindowsLw();
這個函數又會繼續調用mInputMonitor的updateInputWindowsLw成員函數來更新目前的輸入視窗,mInputMonitor是WindowManagerService的成員變量,它的類型為InputMonitor。
Step 5. InputMonitor.updateInputWindowsLw
這個函數定義在frameworks/base/services/java/com/android/server/WindowManagerService.java 檔案中:
final class InputMonitor {
/* Updates the cached window information provided to the input dispatcher. */
public void updateInputWindowsLw() {
// Populate the input window list with information about all of the windows that
// could potentially receive input.
// As an optimization, we could try to prune the list of windows but this turns
// out to be difficult because only the native code knows for sure which window
// currently has touch focus.
final ArrayList<WindowState> windows = mWindows;
final int N = windows.size();
for (int i = N - 1; i >= 0; i--) {
final WindowState child = windows.get(i);
if (child.mInputChannel == null || child.mRemoved) {
// Skip this window because it cannot possibly receive input.
continue;
}
......
// Add a window to our list of input windows.
final InputWindow inputWindow = mTempInputWindows.add();
}
// Send windows to native code.
mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
這個函數将目前系統中帶有InputChannel的Activity視窗都設定為InputManager的輸入視窗,但是後面我們會看到,隻有目前激活的視窗才會響應鍵盤消息。
Step 6. InputManager.setInputWindows
這個函數定義在frameworks/base/services/java/com/android/server/InputManager.java檔案中:
public class InputManager {
public void setInputWindows(InputWindow[] windows) {
nativeSetInputWindows(windows);
這個函數調用了本地方法nativeSetInputWindows來進一步執行操作。
Step 7. InputManager.nativeSetInputWindows
這個函數定義在frameworks/base/services/jni/com_android_server_InputManager.cpp 檔案中:
static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
jobjectArray windowObjArray) {
if (checkInputManagerUnitialized(env)) {
return;
gNativeInputManager->setInputWindows(env, windowObjArray);
這裡的gNativeInputManager我們前面分析InputManager的啟動過程時已經見過了,這是一個本地InputManager對象,通過它進一步設定目前系統的輸入視窗。
本文轉自 Luoshengyang 51CTO部落格,原文連結:xxxxxxx,如需轉載請自行聯系原作者