iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0

InputManagerService (IMS)

intro

在 Android 系統中,使用者與設備互動的最直接方式就是輸入事件 (Input Event),包含觸控 (TouchEvent)、按鍵 (KeyEvent)、以及其他輸入裝置(滑鼠、手寫筆、遊戲控制器等)。
而這些輸入事件的核心控制者,就是 InputManagerService (IMS)。
如果說 AMS 管理應用程式的生命週期,WMS 管理視窗的呈現,那麼 IMS 就是 "負責將使用者的操作轉換成系統可以理解並分發給應用的事件" 。

Input 系統整體架構

在 Android 中,輸入事件的處理流程可以分為 四個層次:

  • 硬體層 (Hardware)
    • 包含觸控螢幕、鍵盤、滑鼠、感測器等輸入裝置
    • 事件會先送到 Linux Kernel Input Subsystem
  • 核心層 (Kernel)
    • 使用 evdev 驅動 將硬體事件封裝為 input_event 結構
    • 事件會被寫入 /dev/input/* 節點
  • Native Layer
    • Android 提供 InputReader 與 InputDispatcher
    • 這部分由 native C++ 層的 InputManager 實作
    • 負責事件的讀取、封裝、分發
  • 系統服務層 (System Server)
    • InputManagerService (IMS) 作為 Java 層代理
    • 與 WMS / AMS 協作,決定事件最終應該交給哪個視窗或 Activity

輸入架構示意圖:

[User Touch/Key]
     │
     ▼
[Hardware Device] → [Linux Kernel Input Subsystem] → [/dev/input/*]
     │
     ▼
[InputReader (Native)] → [InputDispatcher (Native)]
     │
     ▼
[InputManagerService (Java)]
     │
     ▼
[WMS / AMS] → [應用程式 View / Activity]

InputManagerService 的啟動與角色

  1. 啟動過程
    IMS 與其他系統服務一樣,由 SystemServer 在開機時初始化:
inputManager = new InputManagerService(context);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);

在此過程中:

  • 初始化 Native InputManager → 建立 InputReader 與 InputDispatcher
  • 啟動輸入線程 → 開始監聽 /dev/input/*
  • 註冊到 ServiceManager → 讓其他服務(例如 WMS)可以與之交互
  1. IMS 的角色
    IMS 主要扮演兩個角色:
  • 事件橋樑:把 Kernel Input Event 轉換成 Android 的 KeyEvent / MotionEvent
  • 分發協調者:根據 WMS 提供的窗口焦點資訊,決定事件應該送往哪個應用

輸入事件的流轉路徑

下面我們分別以 觸控事件 (TouchEvent) 和 按鍵事件 (KeyEvent) 來解析。

  1. TouchEvent 流程
    步驟 1:硬體輸入
  • 使用者手指觸碰螢幕,觸控控制器將訊號轉換為電壓變化
    步驟 2:Kernel 層處理
  • 驅動程式透過 evdev,將事件上報到 /dev/input/eventX
    步驟 3:InputReader 讀取事件
  • Native InputReader 從 /dev/input/* 讀取 raw event
  • 將其轉換為 MotionEvent
    步驟 4:InputDispatcher 分發事件
  • InputDispatcher 查詢 焦點視窗 (Focus Window)
  • 將事件投遞給對應的 Window
    步驟 5:IMS 與 WMS 協作
  • IMS 透過 Binder 請求 WMS,確認哪個視窗有焦點
  • 一旦確定,事件會送到應用程序對應的 InputChannel
    步驟 6:應用層處理
  • ViewRootImpl 透過 InputChannel 接收事件
  • 分發至 DecorView → ViewGroup → View 的事件分發機制

TouchEvent 流程示意圖:

Touch → /dev/input/eventX → InputReader
   → MotionEvent → InputDispatcher
   → IMS → 查詢 WMS 確定焦點視窗
   → InputChannel → ViewRootImpl
   → Activity → View 分發 (dispatchTouchEvent)
  1. KeyEvent 流程
    KeyEvent 的處理流程與 TouchEvent 類似,差別在於事件類型:
    步驟 1:硬體輸入
  • 使用者按下實體鍵盤或虛擬按鍵
    步驟 2:Kernel 層處理
  • 驅動程式上報 key code 與按鍵狀態 (down / up)
    步驟 3:InputReader 封裝事件
  • 封裝為 KeyEvent
    步驟 4:InputDispatcher 分發
  • 查詢 WMS 確認當前焦點視窗
  • 投遞給應用
    步驟 5:應用層處理
  • Activity.dispatchKeyEvent() → View.dispatchKeyEvent()
  • 最終傳遞到 onKeyDown / onKeyUp

KeyEvent 流程示意圖:

Key → /dev/input/eventX → InputReader
   → KeyEvent → InputDispatcher
   → IMS → WMS 確認焦點視窗
   → InputChannel → Activity
   → dispatchKeyEvent → onKeyDown/onKeyUp

IMS 與 WMS 的協作

輸入事件的分發,離不開 WindowManagerService (WMS) 的協助。

  1. 為何需要 WMS?
    因為輸入事件必須交給「正確的視窗」。
  • 若使用者觸控 A 應用 → 事件應交給 A 的視窗
  • 若 A 被 B 覆蓋(Dialog 或浮動視窗)→ 事件應交給 B
  1. IMS 與 WMS 協作流程
  • InputDispatcher 準備分發事件
  • 向 WMS 查詢目前焦點視窗
  • WMS 回覆「哪個 Window 有 Input Focus」
  • IMS 將事件投遞給該 Window 對應的 InputChannel
IMS(InputDispatcher) → 查詢 → WMS
                      ← 回覆焦點視窗
IMS → 投遞事件至 InputChannel

questions

  1. TouchEvent 流程從硬體到 View.onTouchEvent()?
硬體輸入 → Kernel /dev/input → InputReader → MotionEvent

InputDispatcher → IMS → 查詢 WMS → 投遞 InputChannel

ViewRootImpl → DecorView → ViewGroup → View.dispatchTouchEvent → onTouchEvent
  1. KeyEvent 是如何傳遞到 Activity 的?
硬體事件 → Kernel → InputReader → KeyEvent

InputDispatcher → IMS → WMS → InputChannel

ViewRootImpl → Activity.dispatchKeyEvent → onKeyDown/onKeyUp
  1. 多點觸控 (Multi-Touch) 如何處理?
  • InputReader 會把多個 pointer 的座標包裝在同一個 MotionEvent
  • View 層可透過 MotionEvent.getPointerCount()、getX(i)、getY(i) 取得多點資訊
  1. 為什麼某些情況下事件會丟失?
  • 應用未處於 foreground,WMS 判斷無焦點
  • InputDispatcher 分發超時 (ANR)
  • InputChannel 被關閉

summary

  • InputManagerService (IMS) 是 Android 輸入系統的核心服務,扮演著事件「橋樑」與「分發協調者」的角色。
  • 它與 InputReader / InputDispatcher 負責從 Kernel 讀取並分發事件
  • 與 WMS 協作,決定事件應該送往哪個視窗
  • 事件會抵達應用程式的 View 層,由開發者透過 dispatchTouchEvent / onTouchEvent / dispatchKeyEvent 來處理

上一篇
#09
下一篇
#11
系列文
安豬複習12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言