Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android事件處理教程

android事件處理教程

編輯:關於Android編程

nit-----------zygote---------system-server-------------------windosmanager ------------------------------------------------------------ UEventObserver
------------------------------------------------------------ InputDeviceRead
-------------------------------------------------------------InputDispatcher
-------------------------------------------------------------DisplayEventThr
-------------------------------------------------------------ActivityManager

EventHub:
而事件的傳入是從EventHub開始的,EventHub是事件的抽象結構,維護著系統設備的運行情況,設備類型包括Keyboard、 TouchScreen、TraceBall。它在系統啟動的時候會通過open_device方法將系統提供的輸入設備都增加到這個抽象結構中,並維護一個所有輸入設備的文件描述符,如果輸入設備是鍵盤的話還會讀取/system/usr/keylayout/目錄下對應鍵盤設備的映射文件,另外 getEvent方法是對EventHub中的設備文件描述符使用poll操作等侍驅動層事件的發生,如果發生的事件是鍵盤事件,則調用Map函數按照映射文件轉換成相應的鍵值並將掃描碼和鍵碼返回給KeyInputQueue。
KeyLayoutMap主要是讀取鍵盤映射文件並將鍵盤掃描碼和鍵碼進行轉換

frameworks\base\core\jni\server\ com_android_server_KeyInputQueue.cpp
EventHub和KeyinputQueue的JNI接口層


KeyinputQueue:
在線程InputDeviceReader中會根據事件的類型以及事件值進行判斷處理,從而確定這個事件對應的設備狀態是否發生了改變並相應的改變對這個設備的描述結構InputDevice。
getEvent:在給定時間段時看是否有事件發生,如果有的話返回true否則false。

Windowmanager:
(frameworks/base/services/java/com/android/server/windowmanagerservice.java)
進程Windowmanager會創建一個線程(InputDispatcherThread),在這個線程裡從事件隊列中讀取發生的事件(QueuedEvent ev = mQueue.getEvent()),並根據讀取到事件類型的不同分成三類(KEYBOARD、TOUCHSCREEN、TRACKBALL),分別進行處理,例如鍵盤事件會調用dispatchKey((KeyEvent)ev.event, 0, 0)以將事件通過Binder發送給具有焦點的窗口應用程序,然後調用 mQueue.recycleEvent(ev)繼續等侍鍵盤事件的發生;如果是觸摸屏事件則調用dispatchPointer(ev, (MotionEvent)ev.event, 0, 0),這裡會根據事件的種類(UP、DOWN、MOVE、OUT_SIDE等)進行判斷並處理,比如Cancel或將事件發送到具有權限的指定的窗口中去;

Android 輸入事件流程

EventHub

EventHub對輸入設備進行了封裝。輸入設備驅動程序對用戶空間應用程序提供一些設備文件,這些設備文件放在/dev/input裡面。

EventHub掃描/dev/input下所有設備文件,並打開它們。


C代碼
bool EventHub::openPlatformInput(void)
{
...
mFDCount = 1;
mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
mFDs[0].events = POLLIN;
mDevices[0] = NULL;

res = scan_dir(device_path);
...
return true;
}
bool EventHub::openPlatformInput(void)
{
...
mFDCount = 1;
mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));
mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));
mFDs[0].events = POLLIN;
mDevices[0] = NULL;

res = scan_dir(device_path);
...
return true;
}

EventHub對外提供了一個函數用於從輸入設備文件中讀取數據。


C代碼
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
int32_t* outValue, nsecs_t* outWhen)
{
...
while(1) {

// First, report any devices that had last been added/removed.
if (mClosingDevices != NULL) {
device_t* device = mClosingDevices;
LOGV("Reporting device closed: id=0x%x, name=%s\n",
device->id, device->path.string());
mClosingDevices = device->next;
*outDeviceId = device->id;
if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
*outType = DEVICE_REMOVED;
delete device;
return true;
}
if (mOpeningDevices != NULL) {
device_t* device = mOpeningDevices;
LOGV("Reporting device opened: id=0x%x, name=%s\n",
device->id, device->path.string());
mOpeningDevices = device->next;
*outDeviceId = device->id;
if (*outDeviceId == mFirstKeyboardId) *outDeviceId = 0;
*outType = DEVICE_ADDED;
return true;
}

release_wake_lock(WAKE_LOCK_ID);

pollres = poll(mFDs, mFDCount, -1);

acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);

if (pollres <= 0) {
if (errno != EINTR) {
LOGW("select failed (errno=%d)\n", errno);
usleep(100000);
}
continue;
}

for(i = 1; i < mFDCount; i++) {
if(mFDs[i].revents) {
LOGV("revents for %d = 0x%08x", i, mFDs[i].revents);
if(mFDs[i].revents & POLLIN) {
res = read(mFDs[i].fd, &iev, sizeof(iev));
if (res == sizeof(iev)) {
LOGV("%s got: t0=%d, t1=%d, type=%d, code=%d, v=%d",
mDevices[i]->path.string(),

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved