第九章:底层输入系统与焦点管理

124 阅读3分钟

9.1 Android输入系统架构

输入系统整体架构

deepseek_mermaid_20250712_4bf9ef.png

核心组件解析

组件功能源码位置
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 焦点窗口管理机制

窗口焦点状态机

deepseek_mermaid_20250712_c3d64e.png

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 焦点视图查找机制

跨进程焦点查找

deepseek_mermaid_20250712_dfa645.png

性能优化:焦点缓存

// 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();
}

焦点状态同步流程

deepseek_mermaid_20250712_ab27c7.png

9.8 性能优化与调优

焦点查找优化策略

  1. 空间分区索引

    // 使用网格空间分区
    SpatialIndex spatialIndex = new GridSpatialIndex(100, 100);
    for (View view : focusableViews) {
        spatialIndex.add(view, view.getLocationOnScreen());
    }
    
    // 按区域查询候选视图
    List<View> candidates = spatialIndex.query(focusedRect, direction);
    
  2. 预测性焦点预加载

    // 预测下一个可能的焦点视图
    void preloadFocusCandidates(int direction) {
        Rect predictionArea = predictNextFocusArea(direction);
        List<View> candidates = findViewsInArea(predictionArea);
        
        // 预加载视图状态
        for (View view : candidates) {
            view.measureIfNeeded();
        }
    }
    
  3. 异步焦点查找

    // 在后台线程执行焦点查找
    CompletableFuture<View> findFocusAsync(View focused, int direction) {
        return CompletableFuture.supplyAsync(() -> {
            return FocusFinder.getInstance().findNextFocus(
                focused.getRootView(), focused, direction);
        }, mFocusExecutor);
    }
    

本章小结

  1. 输入系统架构

    • EventHub监听设备输入
    • InputReader解析原始事件
    • InputDispatcher分发到应用
  2. 焦点窗口管理

    • WMS维护焦点窗口状态
    • 焦点窗口变更通知机制
    • 临时焦点丢失处理
  3. 事件分发流程

    • 按键事件优先分发到焦点窗口
    • 焦点视图处理事件机制
    • 系统级按键处理
  4. 无障碍焦点系统

    • 无障碍服务焦点同步
    • 双焦点系统实现
    • 焦点变更事件通知
  5. 安全机制

    • 焦点变更权限验证
    • 安全焦点转移
    • 焦点劫持防护
  6. 跨进程通信

    • Binder接口定义
    • 焦点状态同步流程
    • 窗口与应用焦点协调
  7. 性能优化

    • 空间分区索引
    • 预测性预加载
    • 异步焦点查找

关键源码位置

  • 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