9.1 Android输入系统架构
输入系统整体架构
核心组件解析
| 组件 | 功能 | 源码位置 |
|---|---|---|
| EventHub | 监听设备输入事件 | /frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp |
| InputReader | 解析原始输入事件 | /frameworks/base/services/core/jni/com_android_server_input_InputReader.cpp |
| InputDispatcher | 分发输入事件到应用 | /frameworks/base/services/core/jni/com_android_server_input_InputDispatcher.cpp |
| WindowManagerService | 管理窗口焦点 | /frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java |
9.2 焦点窗口管理机制
窗口焦点状态机
WMS焦点管理源码
// WindowManagerService.java
public void setFocusedApp(IBinder token) {
synchronized(mWindowMap) {
// 更新焦点应用
mFocusedApp = token;
// 通知输入系统
InputManagerService.setFocusedApplication(token);
// 更新所有窗口焦点状态
for (WindowState window : mWindows) {
boolean hasFocus = token != null && token.equals(window.mToken);
window.setFocused(hasFocus);
}
}
}
// 焦点窗口变更处理
void updateFocusedWindowLocked() {
WindowState newFocus = computeFocusedWindow();
if (mFocusedWindow != newFocus) {
// 通知原焦点窗口失去焦点
if (mFocusedWindow != null) {
mFocusedWindow.onFocusChanged(false);
}
// 更新焦点窗口
mFocusedWindow = newFocus;
// 通知新焦点窗口获得焦点
if (mFocusedWindow != null) {
mFocusedWindow.onFocusChanged(true);
// 通知输入系统
InputManagerService.setFocusedWindow(mFocusedWindow.mClient);
}
}
}
9.3 输入事件分发与焦点
按键事件分发流程
// InputDispatcher.cpp
void InputDispatcher::dispatchKeyEvent() {
// 1. 查找焦点窗口
sp<InputWindowHandle> focusedWindow = findFocusedWindow();
// 2. 准备事件分发
KeyEvent event;
initializeKeyEvent(&event);
// 3. 分发到焦点窗口
if (focusedWindow != nullptr) {
focusedWindow->dispatchKeyEvent(&event);
}
}
// ViewRootImpl.java
public void dispatchKeyEvent(KeyEvent event) {
// 查找当前焦点视图
View focused = mView.findFocus();
if (focused != null) {
// 分发到焦点视图
if (focused.dispatchKeyEvent(event)) {
return; // 事件已处理
}
}
// 系统级按键处理
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_BACK:
handleBackKey();
break;
}
}
}
9.4 焦点视图查找机制
跨进程焦点查找
性能优化:焦点缓存
// ViewRootImpl.java
private View mCachedFocusView;
public View findFocus() {
// 使用缓存提高性能
if (mCachedFocusView != null && mCachedFocusView.isFocused()) {
return mCachedFocusView;
}
// 重新查找焦点视图
mCachedFocusView = mView.findFocus();
return mCachedFocusView;
}
// 焦点变更时更新缓存
void updateFocusCache(View newFocus) {
if (mCachedFocusView != newFocus) {
mCachedFocusView = newFocus;
// 通知输入系统焦点变更
InputManagerService.reportFocusChange(newFocus);
}
}
9.5 无障碍服务与焦点
无障碍焦点同步机制
// AccessibilityManagerService.java
void onFocusChanged(View focused) {
// 通知所有启用的无障碍服务
for (AccessibilityService service : mEnabledServices) {
service.onAccessibilityEvent(
AccessibilityEvent.obtainWindowsChangedEvent(focused)
);
}
}
// View.java
public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
// ...
// 通知无障碍服务
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
}
双焦点系统实现
// AccessibilityNodeInfo.java
public void setAccessibilityFocused(boolean focused) {
// 更新无障碍焦点状态
mAccessibilityFocused = focused;
// 通知视图系统
if (mSource != null) {
mSource.setAccessibilityFocused(focused);
}
}
// View.java
public void setAccessibilityFocused(boolean focused) {
// 更新无障碍焦点状态
if (mAccessibilityFocused != focused) {
mAccessibilityFocused = focused;
refreshDrawableState();
// 通知监听器
if (mOnAccessibilityStateChangeListener != null) {
mOnAccessibilityStateChangeListener.onAccessibilityStateChanged(this);
}
}
}
9.6 焦点安全机制
焦点劫持防护
// InputDispatcher.cpp
bool InputDispatcher::validateFocusChange() {
// 验证焦点变更请求来源
if (mFocusedWindowHandle->getToken() != request.sourceToken) {
// 记录安全事件
ALOGE("Focus change request from unauthorized source");
return false;
}
return true;
}
// WindowManagerService.java
void enforceFocusChangePermission(IBinder token) {
// 验证调用方权限
if (checkCallingPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED) {
throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
}
}
安全焦点转移
// ViewRootImpl.java
public boolean transferFocusTo(View view) {
// 验证视图在同一个窗口
if (view.getRootView() != mView) {
throw new SecurityException("Cannot transfer focus to view in different window");
}
// 执行焦点转移
return view.requestFocus();
}
9.7 跨进程焦点通信
Binder接口定义
// IInputManager.aidl
interface IInputManager {
void setFocusedWindow(IBinder token);
IBinder getFocusedWindow();
void reportFocusChange(IBinder token, View view);
}
// IWindowManager.aidl
interface IWindowManager {
void setFocusedApp(IBinder token);
IBinder getFocusedApp();
}
焦点状态同步流程
9.8 性能优化与调优
焦点查找优化策略
-
空间分区索引:
// 使用网格空间分区 SpatialIndex spatialIndex = new GridSpatialIndex(100, 100); for (View view : focusableViews) { spatialIndex.add(view, view.getLocationOnScreen()); } // 按区域查询候选视图 List<View> candidates = spatialIndex.query(focusedRect, direction); -
预测性焦点预加载:
// 预测下一个可能的焦点视图 void preloadFocusCandidates(int direction) { Rect predictionArea = predictNextFocusArea(direction); List<View> candidates = findViewsInArea(predictionArea); // 预加载视图状态 for (View view : candidates) { view.measureIfNeeded(); } } -
异步焦点查找:
// 在后台线程执行焦点查找 CompletableFuture<View> findFocusAsync(View focused, int direction) { return CompletableFuture.supplyAsync(() -> { return FocusFinder.getInstance().findNextFocus( focused.getRootView(), focused, direction); }, mFocusExecutor); }
本章小结
-
输入系统架构:
- EventHub监听设备输入
- InputReader解析原始事件
- InputDispatcher分发到应用
-
焦点窗口管理:
- WMS维护焦点窗口状态
- 焦点窗口变更通知机制
- 临时焦点丢失处理
-
事件分发流程:
- 按键事件优先分发到焦点窗口
- 焦点视图处理事件机制
- 系统级按键处理
-
无障碍焦点系统:
- 无障碍服务焦点同步
- 双焦点系统实现
- 焦点变更事件通知
-
安全机制:
- 焦点变更权限验证
- 安全焦点转移
- 焦点劫持防护
-
跨进程通信:
- Binder接口定义
- 焦点状态同步流程
- 窗口与应用焦点协调
-
性能优化:
- 空间分区索引
- 预测性预加载
- 异步焦点查找
关键源码位置:
- InputManagerService:
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java- WindowManagerService:
/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java- ViewRootImpl:
/frameworks/base/core/java/android/view/ViewRootImpl.java- InputDispatcher:
/frameworks/base/services/core/jni/com_android_server_input_InputDispatcher.cpp