豐都網(wǎng)站建設(shè)信息流推廣
在 Android 中,輸入事件(例如觸摸、按鍵)從硬件傳遞到應用程序并最終由應用層消費。整個過程涉及多個系統(tǒng)層次,包括硬件層、Linux 內(nèi)核、Native 層、Framework 層和應用層。我們將深入解析這一流程,并結(jié)合代碼逐步了解輸入事件的傳遞。
1. 輸入事件的產(chǎn)生與傳遞
輸入事件的產(chǎn)生是從硬件觸摸屏開始的。觸摸屏等輸入設(shè)備檢測到用戶的操作(如觸摸、滑動),然后將這些事件傳遞給 Linux 內(nèi)核。
- 硬件層(觸摸屏等):將物理觸摸或按鍵操作轉(zhuǎn)化為信號。
- 內(nèi)核層:Linux 內(nèi)核中的 Input 子系統(tǒng)負責接收這些輸入信號并生成相應的事件。
在 Android 系統(tǒng)中,輸入事件從硬件傳遞到應用層的大致流程如下:
觸摸屏(硬件層) → Linux 內(nèi)核(Input子系統(tǒng)) → Native Input System(輸入事件解析與分發(fā))
→ Framework(事件管理) → 應用層(事件消費)
2. Linux 內(nèi)核:輸入事件的生成與處理
內(nèi)核的 Input 子系統(tǒng)接收到輸入事件后,將其轉(zhuǎn)化為 input_event
結(jié)構(gòu)。每個輸入事件包括三部分:
- type:事件的類型,例如 EV_ABS 表示絕對坐標事件。
- code:事件的具體代碼,例如 ABS_X 表示 X 軸坐標。
- value:事件的值,例如坐標值。
代碼示例
在 Linux 內(nèi)核中,輸入事件使用以下結(jié)構(gòu)定義:
struct input_event {struct timeval time; // 事件發(fā)生時間__u16 type; // 事件類型__u16 code; // 事件代碼__s32 value; // 事件值
};
當觸摸屏收到用戶的操作時,會產(chǎn)生一系列 input_event
事件,傳遞到 Linux Input 子系統(tǒng)。然后,內(nèi)核會將這些事件通過 /dev/input/eventX
文件接口暴露給用戶態(tài)。
3. Native 層:InputReader 和 InputDispatcher
Android 使用 InputReader
和 InputDispatcher
這兩個關(guān)鍵組件來處理輸入事件。
- InputReader:從 Linux /dev/input/eventX 接口讀取事件,并解析為 Android 系統(tǒng)可以理解的 MotionEvent 或 KeyEvent。
- InputDispatcher:將 InputReader 解析后的事件分發(fā)給應用程序的 Window。
在 Android 系統(tǒng)中,InputManagerService
是輸入系統(tǒng)的核心服務,它在系統(tǒng)啟動時被創(chuàng)建,并負責管理整個輸入事件的讀取和分發(fā)。
InputReader 代碼流程
在 InputReader
中,EventHub
類負責打開 /dev/input/eventX
設(shè)備文件并讀取事件。
void EventHub::openDevice(const char* deviceName) {// 打開設(shè)備文件int fd = open(deviceName, O_RDWR);// 將設(shè)備文件添加到輸入設(shè)備列表中mDevices.push_back(fd);
}
InputReader::loopOnce
是 InputReader
的核心處理函數(shù),它不斷從事件隊列中讀取事件并處理。
void InputReader::loopOnce() {// 讀取事件processEvents();// 處理事件dispatchEvent();
}
InputDispatcher 代碼流程
InputDispatcher
使用 dispatchEvent
方法將事件分發(fā)到合適的 Window
或 Activity
。
void InputDispatcher::dispatchEvent(const Event& event) {// 獲取目標 Windowsp targetWindow = getTargetWindow(event);// 將事件發(fā)送給目標 WindowtargetWindow->sendEvent(event);
}
4. Framework 層:事件分發(fā)(WindowManagerService)
在 Framework 層,InputManagerService
將事件傳遞給 WindowManagerService
,WindowManagerService
負責管理所有窗口的輸入焦點,并將事件轉(zhuǎn)發(fā)給有焦點的窗口。
代碼流程
WindowManagerService
中的 dispatchPointerEvent
方法會根據(jù)窗口焦點來分發(fā)事件。
public void dispatchPointerEvent(MotionEvent event) {// 獲取焦點窗口WindowState focusedWindow = getFocusedWindow();if (focusedWindow != null) {// 將事件發(fā)送到焦點窗口focusedWindow.sendInputEvent(event);}
}
5. 應用層:事件消費(View 和 Activity)
最終,事件到達應用層。對于觸摸事件,Android 使用 onTouchEvent
方法處理,而對于按鍵事件,則使用 onKeyDown
、onKeyUp
等方法處理。
示例代碼
在 Activity
或 View
中,可以通過重寫 onTouchEvent
來消費事件。
@Override
public boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 處理按下事件break;case MotionEvent.ACTION_MOVE:// 處理移動事件break;case MotionEvent.ACTION_UP:// 處理抬起事件break;}return super.onTouchEvent(event);
}
總結(jié)
- 硬件層:產(chǎn)生輸入事件并傳遞到內(nèi)核。
- Linux 內(nèi)核:接收輸入信號并轉(zhuǎn)化為 input_event。
- Native 層:InputReader 和 InputDispatcher 解析和分發(fā)事件。
- Framework 層:WindowManagerService 負責將事件傳遞給對應的窗口。
- 應用層:Activity 和 View 接收并消費事件。
這一整套流程保證了從物理輸入到應用響應的鏈路完整性和效率。
參考
Android Input Framework Architecture