// frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
// 进入RootWindowContainer中
boolean changed = mRoot.updateFocusedWindowLocked(mode, updateInputWindows);
return changed;
}
其中,第一个参数表示更新焦点窗口时所处的阶段,共有五个参数:
// 表示正常更新
static final int UPDATE_FOCUS_NORMAL = 0;
// 表示此次更新焦点窗口发生在window layer分配之前
static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
// 表示此次更新焦点窗口发生在进行放置Surface过程中,在performSurfacePlacement()时
static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
// 表示此次更新焦点窗口发生在进行放置Surface之前
static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
// 表示此次更新焦点窗口发生在焦点窗口移除后
static final int UPDATE_FOCUS_REMOVING_FOCUS = 4;
如在Window添加过程的WMS#addWindow()
方法中,更新焦点窗口发生在分配窗口layer流程之前,因此使用UPDATE_FOCUS_WILL_ASSIGN_LAYERS
作为第一个参数,表示此次更新时,还没有分配layer。 针对不同阶段,会有不同的操作。
第二个参数表示是否同步更新InputWindow。
1.2.RWC#updateFocusedWindowLocked()
WMS中发起更新焦点窗口后,由RootWindowContainer中处理:
// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
// 存储了当前焦点窗口的Pid和ActivityRecord的Map映射
mTopFocusedAppByProcess.clear();
boolean changed = false;
int topFocusedDisplayId = INVALID_DISPLAY;
// 遍历DisplayContent
for (int i = mChildren.size() - 1; i >= 0; --i) {
final DisplayContent dc = mChildren.get(i);
// 针对每个DisplayContent,进行焦点窗口更新
changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId);
// 更新全局焦点窗口
final WindowState newFocus = dc.mCurrentFocus;
if (newFocus != null) {
final int pidOfNewFocus = newFocus.mSession.mPid;
if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) {
mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord);
}
} else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) {
topFocusedDisplayId = dc.getDisplayId();
}
}
// 更新mTopFocusedDisplayId,表示焦点屏幕
if (mTopFocusedDisplayId != topFocusedDisplayId) {
mTopFocusedDisplayId = topFocusedDisplayId;
mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
}
return changed;
}
这里会遍历DisplayContent,并在每个DisplayContent中进行更新,然后将更新的结果返回给DisplayContent#mCurrentFocus变量,该变量表示全局的焦点窗口。同时更新mTopFocusedDisplayId变量,表示当前焦点屏(即焦点窗口所在的屏)。
1.3.DisplayContent#updateFocusedWindowLocked()
该方法如下:
// frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows,
int topFocusedDisplayId) {
// 寻找焦点窗口
WindowState newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId);
// 焦点窗口没有变化时,返回false
if (mCurrentFocus == newFocus) {
return false;
}
boolean imWindowChanged = false;
final WindowState imWindow = mInputMethodWindow;
// 更新IM