




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Android遙控器事件集成及用戶輸入系統(tǒng)分析一、用戶輸入系統(tǒng)結(jié)構(gòu)Android中,用戶輸入系統(tǒng)的結(jié)構(gòu)相對簡單,主要的輸入硬件設(shè)備是鍵盤、觸摸屏、軌跡球等。在Android的上層中,可以通過獲得這些設(shè)備產(chǎn)生的事件,并對設(shè)備的事件做出響應(yīng)。在Java框架和應(yīng)用程序?qū)?,通常使用運動事件獲得觸摸屏、軌跡球等設(shè)備的信息,用按鍵事件獲得各種鍵盤的信息。Android用戶輸入系統(tǒng)的基本層次結(jié)構(gòu)如圖1所示。圖1 Android用戶輸入系統(tǒng)的基本層次結(jié)構(gòu)具體而言,Android用戶輸入系統(tǒng)自下而上包含了驅(qū)動程序、本地庫處理部分、Java類對輸入事件的處理、對Java程序的接口。Android用戶輸入系統(tǒng)的結(jié)構(gòu)
2、如圖2所示:圖2 用戶輸入系統(tǒng)的結(jié)構(gòu)如圖2所示,自下而上,Android的用戶輸入系統(tǒng)分成幾個部分:驅(qū)動程序:在/dev/input目錄中,通常是Event類型的驅(qū)動程序;EventHub:本地框架層的EventHub是libui中的一部分,它實現(xiàn)了對驅(qū)動程序的控制,并從中獲得信息;KeyLayout(按鍵布局)和KeyCharacterMap(按鍵字符映射)文件。同時,libui中有相應(yīng)的代碼對其操作。定義按鍵布局和按鍵字符映射需要運行時配置文件的支持,它們的后綴名分別為kl和kcm;Java框架層的處理:在Java框架層具有KeyInputDevice等類用于處理由EventHub傳送上來
3、的信息,通常信息由數(shù)據(jù)結(jié)構(gòu)RawInputEvent和KeyEvent來表示。通常情況下,對于按鍵事件,則直接使用KeyEvent來傳送給應(yīng)用程序?qū)?,對于觸摸屏和軌跡球等事件,則由RawInputEvent經(jīng)過轉(zhuǎn)換后,形成MotionEvent時間傳送給應(yīng)用程序?qū)?;在Android的應(yīng)用程序?qū)又?,通過重新實現(xiàn)onTouchEvent和onTrackballEvent等函數(shù)來接收運動事件(MotionEvent),通過重新實現(xiàn)onKeyDown和onKeyUp等函數(shù)來接收按鍵事件(KeyEvent)。這些類包含在android.view包中。二、Hi3716C中遙控器事件的傳遞流程Hi3716C
4、中輸入事件的流程如圖3所示:圖3 Hi3716C中輸入事件的基本流程圖下面按照事件傳遞流程依次對遙控器按鍵事件傳遞各個環(huán)節(jié)進行講述:1、 輸入設(shè)備的打開EventHub類對輸入設(shè)備進行了封裝。輸入設(shè)備驅(qū)動程序?qū)τ脩艨臻g應(yīng)用程序提供一些設(shè)備文件,這些設(shè)備文件放在/dev/input里面。在系統(tǒng)啟動后,android 會使用 EventHub.cpp中以下函數(shù):static const char *device_path = "/dev/input" bool EventHub:openPlatformInput(void)res = scan_
5、dir(device_path); 通過調(diào)用scan_dir()搜索/dev/input下所有Input驅(qū)動的設(shè)備節(jié)點,最終調(diào)用下面的函數(shù)打開搜索到的所有輸入設(shè)備:int EventHub:open_device(const char *deviceName) . fd = open(deviceName, O_RDWR); . &
6、#160; mFDsmFDCount.fd = fd; mFDsmFDCount.events = POLLIN; . ioctl(mFDsmFDCount.fd, EVIOCGNAME(sizeof(devname)-1),devname); .
7、 const char* root = getenv("ANDROID_ROOT"); snprintf(keylayoutFilename, sizeof(keylayoutFilename), "%s/usr/
8、keylayout/%s.kl", root, tmpfn); . device->layoutMap->load(keylayoutFilename); . 打開設(shè)備的時候,如果 device->classes&CLASS_KEYBOARD 不等于 0 表明是鍵盤。 在此過程中,通過device->layoutMap->l
9、oad(keylayoutFilename),KeyLayoutMap類device->layoutMap會嘗試載入并解析按鍵映射文件/system/usr/keylayout/ Hi3716_keypad.kl (若不存在則載入默認的/system/usr/keylayout/ qwerty.kl)。Hi3716_keypad.kl文件的片斷如下所示:key 8 7key 9 8key 10 9key 11 0key 158 BACK WAKE_DROPPEDkey 230 SOFT_RIGHT WAKEkey 107 ENDCALL WAKE_DROPPEDkey 61 C
10、ALL WAKE_DROPPEDkey 232 DPAD_CENTER WAKE_DROPPEDkey 108 DPAD_DOWN WAKE_DROPPEDkey 103 DPAD_UP WAKE_DROPPEDkey 102 HOME WAKEkey 105 DPAD_LEFT WAKE_DROPPEDkey 106 DPAD_RIGHT WAKE_DROPPEDkey 115 VOLUME_UPkey 114 VOLUME_DOWNkey 16 Qkey 17 Wkey 18 Ekey 19 Rkey 20 T文件第1列為按鍵的整數(shù)掃描碼(ScanCode),第2列為按鍵的字符串標簽(Ke
11、ycodeLabel),第3列表示按鍵的Flag,帶有WAKE字符,表示這個按鍵可以喚醒系統(tǒng)。在KeyLayoutMap:load()中解析kl 文件時,會首先使用第1列掃描碼所對應(yīng)的按鍵標簽,在KeycodeLabels.h (froyoframeworksbaseincludeui)中的KeycodeLabel KEYCODES中查找同名字符串標簽,并將找到的標簽對應(yīng)的鍵值(KeycodeLabels.value)存入Key. Keycode。同樣地,kl文件第3列Flag字符串與KeycodeLabels.h中KeycodeLabel FLAGS的同名字符串所對應(yīng)的整數(shù)值(Ke
12、ycodeLabels.value),也會被存入Key.flags。最終,把按鍵的映射關(guān)系保存在 KeyedVector<int32_t,Key> m_keys中,int32_t即為kl文件中的掃描碼。需要指出的是,KeycodeLabel KEYCODES中的KeycodeLabels.value與android.view. KeyEvent.java中定義的鍵值是完全一致的,因此m_keys中的Key. Keycode值是可以被Android識別的。2、 驅(qū)動程序捕捉并上報按鍵事件目錄patch_froyodevicehisihi3716cdriversdkmspandroid
13、_driver hi_keypad下Ir_keyboad.c和Ir_keyboad.h是Hi3716C遙控器的驅(qū)動程序。它是Hi3716C的設(shè)備1(/dev/input/event0)的驅(qū)動程序,設(shè)備名稱為Hi3716_keypad。在IR_Keypad_Events_Probe()中此設(shè)備節(jié)點的中斷響應(yīng)函數(shù)被設(shè)置為IR_Keypad_IntIsr()。當(dāng)遙控器按鍵按下時,更底層的中斷響應(yīng)代碼會獲取按鍵的遙控器編碼(Ir_keyboad.h中ScanCode)并傳遞給IR_Keypad_IntIsr(),IR_Keypad_IntIsr將遙控器編碼轉(zhuǎn)換為掃描碼,通過input_key上報按鍵事
14、件。如下所示:if(IR_KEY_DOWN = keyval) /*key down*/ input_event(edev->input, EV_KEY, KEY_DOWN, KPC_EV_KEY_PRESS); input_event(edev->input, EV_KEY, KEY_DOWN, KPC_EV_KEY_RELEASE); printk("+ key down pressn");3、 InputDeviceReader線程讀取按鍵事件EventHub對外提供了一個函數(shù)用于從輸入設(shè)備文件中讀取數(shù)據(jù):bool EventHub:getEvent(in
15、t32_t* outDeviceId, int32_t* outType, int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags, int32_t* outValue, nsecs_t* outWhen). while(1) . release_wake_lock(WAKE_LOCK_ID); pollres = poll(mFDs, mFDCount, -1); acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID); for(i = 1; i < mFDCount; i
16、+) if(mFDsi.revents) if(mFDsi.revents & POLLIN) res = read(mFDsi.fd, &iev, sizeof(iev); if (res = sizeof(iev) if (iev.type = EV_KEY) err = mDevicesi->layoutMap->map(iev.code, outKeycode, outFlags); else *outKeycode = iev.code; return true; .函數(shù)使用阻塞函數(shù)poll()等侍驅(qū)動層事件的發(fā)生,然后通過read()讀取Input設(shè)備的
17、數(shù)據(jù),調(diào)用mDevicesi->layoutMap->map進行映射。KeyLayoutMap:map ()會使用KeyLayoutMap:load()所生成的KeyedVector<int32_t,Key> m_keys,將按鍵的掃描碼轉(zhuǎn)換為Android可以識別的鍵值。通過前面對KeyLayoutMap:load()的分析可知,KeyLayoutMap:map ()過程中,實際進行了2次按鍵信息轉(zhuǎn)換:按鍵的掃描碼首先被轉(zhuǎn)換為了kl文件中相應(yīng)的字符串標簽KeycodeLabel,接著字符串標簽又根據(jù)KeycodeLabels.h中的KeycodeLabel KEYCO
18、DES被轉(zhuǎn)換為了與android.view. KeyEvent.java鍵值相一致的整數(shù)鍵值。frameworks/base/services/jni/com_android_server_KeyInputQueue.cpp中,向JAVA提供了jni函數(shù)android_server_KeyInputQueue_readEvent,用于讀取輸入設(shè)備事件:static jboolean android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz, jobject
19、60;event) sp hub = gHub; if (hub = NULL) hub = new EventHub; gHub = hub;
20、60; . bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode, &flags, &value,
21、 &when); env->SetIntField(event, gInputOffsets.mDeviceId, (jint)deviceId); env->SetIntField(event, gInputOffsets.mScancode, (jint)scancode); env->SetIntField(event, gInputOffsets.mKeycode, (jint)
22、keycode); . return res; readEvent調(diào)用hub->getEvent讀了取事件,然后將掃描碼和鍵碼等轉(zhuǎn)換成JAVA的結(jié)構(gòu)。在frameworks/base/services/java/com/android/server/KeyInputQueue.java里創(chuàng)建了一個線程,它循環(huán)地讀取事件,然后把事件放入事件隊列里。在KeyInputQueue的構(gòu)造函數(shù)中,這個線程被啟動。Thread mThread = new Thread("Inp
23、utDeviceReader") public void run() android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY); try RawInputEvent ev = new RawInputEvent(); while (true) InputDevice di; readEvent(ev); send = preprocessEvent(di, ev); addLocked(di, curTime, ev.flags, ., me); ;4、 按鍵事件分
24、發(fā)在frameworks/base/services/java/com/android/server/WindowManagerService.java里創(chuàng)建了一個輸入事件分發(fā)線程,它負責(zé)把事件分發(fā)到相應(yīng)的窗口上去。在WindowManagerService的構(gòu)造函數(shù)中有:private WindowManagerService(Context context, PowerManagerService pm,boolean haveInputMethods) mQueue = new KeyQ();mInputThread = new InputDispatcherThread();
25、; . mInputThread.start(); KeyQ 是抽象類 KeyInputQueue 的實現(xiàn),所以 new KeyQ類的時候?qū)嶋H上在 KeyInputQueue 類中創(chuàng)建了一個線程 InputDeviceReader 專門用來從設(shè)備讀取按鍵事件。之后調(diào)用mInputThread.start()啟動一個線程 InputDispatcherThread 。Inpu
26、tDispatcherThread 線程從 KeyQ 的事件隊列中讀取按鍵事件,在process() 方法中進行事件處理:QueuedEvent ev = mQueue.getEvent(int)(!configChanged && curTime < nextKeyTime) ? (nextKeyTime-curTime) : 0);switch (ev.classType) case RawInputEvent.CLASS_KEYBOARD:
27、60; . dispatchKey(KeyEvent)ev.event, 0, 0); mQueue.recycleEvent(ev); break; case RawInputEvent.CLASS_TOUCHSCREEN:
28、60; /Log.i(TAG, "Read next event " + ev); dispatchPointer(ev, (MotionEvent)ev.event, 0, 0); break; case RawInputEvent.CLASS_TRACKBALL: dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0); break;在process() 方法中,首先從事件隊列中讀取發(fā)生的事件,并根據(jù)讀取到事件類型的不同分成三類(KEYBOARD、TOU
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度教育培訓(xùn)檔口租賃合同
- T-ZJCX 0046-2024 簾子線直捻機
- 二零二五年度公車私用行為規(guī)范與責(zé)任追究協(xié)議
- 二零二五年度全新碼頭租賃協(xié)議及倉儲服務(wù)合作協(xié)議
- 2025年度果園租賃與農(nóng)業(yè)科技研發(fā)合同
- 二零二五年度廣告代理合同解除與權(quán)益調(diào)整協(xié)議
- 2025年度高科技企業(yè)計件工資勞動合同
- 2025年度智能合同履約跟蹤與風(fēng)險控制管理辦法
- 2025年度消防設(shè)施定期維護與消防通道清理合同
- 二零二五年度美發(fā)店員工勞動健康保險與意外傷害合同
- 2025年湖南高速鐵路職業(yè)技術(shù)學(xué)院單招職業(yè)傾向性測試題庫附答案
- 2025屆高考英語二輪復(fù)習(xí)備考策略課件
- 《高鐵乘務(wù)安全管理與應(yīng)急處置(第3版)》全套教學(xué)課件
- 歷年湖北省公務(wù)員筆試真題2024
- 2.2 說話要算數(shù) 第二課時 課件2024-2025學(xué)年四年級下冊道德與法治 統(tǒng)編版
- 《工程勘察設(shè)計收費標準》(2002年修訂本)
- 潔凈室空調(diào)凈化系統(tǒng)驗證方案(通過BSI和華光審核)
- 2024年電力交易員(中級工)職業(yè)鑒定理論考試題庫-下(多選、判斷題)
- 數(shù)學(xué)物理方程(很好的學(xué)習(xí)教材)PPT課件
- 電力建設(shè)工程質(zhì)量監(jiān)督檢查大綱新版
- GB-T-15894-2008-化學(xué)試劑-石油醚
評論
0/150
提交評論