<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### **概述** 在Android應用程序中,有一類特殊的消息,是專門負責與用戶進行交互的,它們就是觸摸屏和鍵盤等輸入事件。觸摸屏和鍵盤事件是統一由系統輸入管理器InputManager進行分發的。也就是說,InputManager負責從硬件接收輸入事件,然后再將接收到的輸入事件分發當前激活的窗口處理。此外,InputManager也能接收模擬的輸入事件,用來模擬用戶觸摸和點擊等事件。當前激活的窗口所運行在的線程接收到InputManager分發過來的輸入事件之后,會將它們封裝成輸入消息,然后交給當前獲得焦點的控件處理。 主要講Android應用程序輸入事件的分發和處理過程,主要涉及到輸入管理InputManager、輸入事件監控線程InputReader、輸入事件分發線程InputDispatcher,以及應用程序主線程消息循環。 * Android輸入系統概述 * 輸入管理器的啟動過程 * 輸入通道的注冊過程 * 輸入事件的分發過程 * 軟鍵盤輸入事件的分發過程 #### **Android輸入系統概述** **輸入管理器框架** ![](https://box.kancloud.cn/4f6d8b5f2b2dfd443090c6b272e25155_681x571.jpg) **輸入管理器與應用程序通過輸入通道交互** ![](https://box.kancloud.cn/69060a95c6b569044ba833adcff037e7_434x201.png) **輸入通道** ![](https://box.kancloud.cn/f00c0230d6b40bc5635313bb1d541fdf_539x388.jpg) > 注:mFd指向的是一個socket #### **輸入管理器的啟動過程** **由System Server創建和啟動** ![](https://box.kancloud.cn/0661dfeca45764716f4d05360862b7f0_662x548.png) 注:inputManager.setWindowManagerCallbacks:設置回調,例如用來截獲輸入事件 **創建InputManagerService** ![](https://box.kancloud.cn/72e71fba156010b1c123e0b86820faf0_639x263.png) **創建NativeInputManager** ![](https://box.kancloud.cn/96fca6b31145c51cab0cddce78312892_894x296.png) **創建InputManager、InputReader和InputDispatcher,以及InputReaderThread、 InputDispatcherThread** ![](https://box.kancloud.cn/a42a83147dc6c29edd20ad370b992d9d_633x223.png) **啟動InputManagerService** ![](https://box.kancloud.cn/72e71fba156010b1c123e0b86820faf0_639x263.png) **啟動NativeInputManager** ![](https://box.kancloud.cn/96fca6b31145c51cab0cddce78312892_894x296.png) **啟動InputManager** ![](https://box.kancloud.cn/8a782db31d2e53271d26fefce55534ca_808x293.png) **啟動InputDispatcher** **InputDispatcher.dispatchOnce** ![](https://box.kancloud.cn/52141b141aa8aeb871de3ade1fe714a6_769x410.png) > 注:InputDispatcher負責分發IO事件,IO事件分為兩種類型。一種普通的輸入事件,另一種是輸入設備本身的事件,例如,輸入設備配置發生改變事件。普通的輸入事件由dispatchOnceInnerLocked處理,輸入設備事件由runCommandsLockedInterruptible處理。InputDispatcher本身也維護著兩個隊列,一個是mInboundQueue,保存的是普通的輸入事件,另一個是mCommandQueue,保存的是輸入設備事件。 **啟動InputReader** * **InputReaderThread.threadLoop** ![](https://box.kancloud.cn/b3b603d72f8d5a63a4962c2bcfdf726f_362x78.png) * **InputReader.loopOnce** ![](https://box.kancloud.cn/c195f5c187f1d43f2c99f850b5ec0d12_797x561.png) > 注:mNextTimeout:振動設備是按照一定的頻率來進行的,這個頻率就可以通過設置mNextTimeout來獲得 * **EventHub.getEvents** ![](https://box.kancloud.cn/d1e337233c2cf581f1f45da94da44654_898x576.png) * **EventHub.scanDevicesLocked** ![](https://box.kancloud.cn/49d976fcb4a4cad0c089858daa128884_521x201.png) > 注:虛擬鍵盤:設備不一定有鍵盤,但是程序在測試的時候時候需要模擬鍵盤輸入,這時候模擬的鍵盤輸入就看作是從虛擬鍵盤發出的。EventHub只存一定會存在虛擬鍵盤。 * **EventHub.scanDirLocked** ![](https://box.kancloud.cn/1f32e67f23bd6505f59b581be8d391ae_561x391.png) > 注:可以用getevent –i命令來查看/dev/input目錄下各個文件所對應的輸入設備信息 * **EventHub.openDeviceLocked** ![](https://box.kancloud.cn/3d8fb906ee897c6967794d1c60412a4b_717x576.png) > 注:Key Map Configuraton File和Configuration File:保存在/system/usr或者/data/system/devices目錄下 #### **輸入通道的注冊過程** **Activity窗口的組成** ![](https://box.kancloud.cn/07b0ecdff8c9064793b0f57e91fee43e_581x281.jpg) > 注:InputChannel是在應用程序請求WMS創建一個Activity窗口時創建的,也就是調用ViewRootImpl.setView開始創建的,在這個過程中,也會同時注冊InputChannel,包括Server端InputChannel和客戶端InputChannel **創建InputChannel ** * **ViewRootImpl.setView** ![](https://box.kancloud.cn/f4f7a176405a74da9209eace18175465_744x482.png) > 注:mInputQueueCallback不等于null表示由view自己來接管輸入事件,否則的話就由ViewRootImpl來接管 * **Session.addToDisplay** ![](https://box.kancloud.cn/8e5f8ae9a10d7e72542638bf23a2de93_796x212.png) * **WMS.addWindow** ![](https://box.kancloud.cn/4fa0a2c33d54b05e0ed7d0d80d7d9eba_775x575.png) * **InputChannel.openInputChannelPair** ![](https://box.kancloud.cn/f249c8e21305b8b459d7d4d0b53e627a_593x261.png) * **nativeOpenInputChannelPair** ![](https://box.kancloud.cn/9c6b18d1a115f0eaad45f761c88ee6df_752x308.png) * **InputChannel::openInputChannelPair** ![](https://box.kancloud.cn/6c9dd9017ea5c7c46024e5e37f5a14dd_675x432.png) **注冊Server端InputChannel** ![](https://box.kancloud.cn/8dad7a2078e6ae737b4a2eb4832315d4_653x448.png) > 注:win.mInputWindowHandle:窗口句柄,用來描述窗口的大小和位置等信息 * **IMS.registerInputChannel** ![](https://box.kancloud.cn/0da664a739be6463d7dd1f5139c54636_671x243.png) * **nativeRegisterInputChannel** ![](https://box.kancloud.cn/764f59aebd9aa15405512c149b9a20ad_749x244.png) * **NativeInputManager.registerInputChannel** ![](https://box.kancloud.cn/b510b114dd5f02fa201931f3f3acb4e0_606x103.png) * **InputDispatcher.registerInputChannel** ![](https://box.kancloud.cn/a447aa5db2fa7ff2e59e6b62b9fcc9ca_759x464.png) * **Looper.addFd** ![](https://box.kancloud.cn/ce5f24ad89d000d80cffbda106827171_783x51.png) ![](https://box.kancloud.cn/0b1261c6e83aca4587bbab2cb66e78f9_805x539.png) **更新當前激活窗口** ![](https://box.kancloud.cn/5aa13d334d3ca065dddff724aa8cc923_659x447.png) * **WMS.updateFoucsedWindowLocked** ![](https://box.kancloud.cn/7b9d0fc1bc35840c783c026c3cc84000_730x272.png) > 注:computeFocusedWindowLocked:從窗口堆棧從上到下搜索,如果它的宿主App是當前Focused的App,那么它就是Focused窗口。Focused App在窗口切換時已經確定 * **WMS. finishUpdateFocusedWindowAfterAssignLayersLocked** ![](https://box.kancloud.cn/4a1ec3d3ead930dd95394ebf98e9c886_775x141.png) * **InputMonitor.setInputFocusLw** ![](https://box.kancloud.cn/971646614d40433bf7fa32e95b632c45_681x355.png) > 注:這里傳進來的參數updateInputWindows的值等于false,不會馬上調用updateInputWindowsLw來更新窗口,但是接下來新的窗口請求WMS進行layout時,就會調用updateInputWindowsLw來更新窗口 * **InputMonitor. updateInputWindowsLw** ![](https://box.kancloud.cn/1dfb1e5b6e767b285f8beff853abc625_700x547.png) >注: universeBackground:類型為TYPE_UNIVERSE_BACKGROUND的窗口 > TYPE_UNIVERSE_BACKGROUND的窗口:Behind the universe of the real windows, in multiuser systems shows on all users’windows * **InputManagerService.setInputWindows** ![](https://box.kancloud.cn/9726c3e6618505b1c18b83ec3ceb20d7_642x166.png) * **nativeSetInputWindows** ![](https://box.kancloud.cn/3720113136e034fc41b6cb77aca29b3c_583x103.png) * **NativeInputManager.setInputWindows** ![](https://box.kancloud.cn/18196f14ddcf6dcabe7dc59c4daaa7c2_724x352.png) * **InputDispatcher.setInputWindows** ![](https://box.kancloud.cn/16b34ffb4ce46f2ebd1cd76b099d040a_785x480.png) **注冊Client端InputChannel** ![](https://box.kancloud.cn/30983683431e69dd793148bb464f2e0b_631x413.png) * **new WindowInputEventReceiver ** ![](https://box.kancloud.cn/1c5df2506d93fb233c61fd34ff02e579_680x209.png) * **new InputEventReceiver ** ![](https://box.kancloud.cn/3b8dc3f8a04d3726e0acd7a96ef25294_600x243.png) * **nativeInit** ![](https://box.kancloud.cn/14d740ea5553e3fec753a9368a6b8545_798x257.png) * **NativeInputEventReceiver.initialize** ![](https://box.kancloud.cn/043b241cfffd7e7a07ce02dca750e2dc_711x81.png) > 注:IO事件發生時, NativeInputEventReceriver::handleEvent將被調用 #### **輸入事件的分發過程** **輸入事件處理框架** ![](https://box.kancloud.cn/6320968a871a231e54a2a9664dd39fa5_516x252.png) **InputReader獲得輸入事件** * **InputReader獲得輸入事件--EventHub.getEvents** ![](https://box.kancloud.cn/2a322d4c8d61c5b198df62cf3ea48945_731x615.png) * **InputReader獲得輸入事件 – InputReader.loopOnce ** ![](https://box.kancloud.cn/c195f5c187f1d43f2c99f850b5ec0d12_797x561.png) * **InputReader獲得輸入事件 – InputReader.processEventsLocked ** ![](https://box.kancloud.cn/9d8903fa554a0fec91d13bf84054f744_721x244.png) * **InputReader獲得輸入事件 – InputReader.processEventsForDeviceLocked** ![](https://box.kancloud.cn/b81291c54f609df62fbede4689ad9e39_651x278.png) * **InputReader獲得輸入事件—InputDevice.process** ![](https://box.kancloud.cn/e95f6a269f890a18b302327348aa790c_725x238.png) * **InputReader獲得輸入事件—KeyboardInputMapper.process** ![](https://box.kancloud.cn/50e8e925a99e1a1dc1c4a6d26eaa112f_852x358.png) * **InputReader獲得輸入事件—KeyboardInputMapper.processKey** ![](https://box.kancloud.cn/5f9b4bb4546a7b1887b8ac50f52e4c64_766x323.png) * **InputReader獲得輸入事件—InputDispatcher.notifyKey** ![](https://box.kancloud.cn/d988910226a1233737cfd68bb40acfc0_594x608.png) * **InputReader獲得輸入事件—InputDispatcher. enqueueInboundKeyLocked** ![](https://box.kancloud.cn/fdeed536c67d0b377e7132ca3cbd9ffe_1375x96.png)![](https://box.kancloud.cn/68dc7bb8f1e3734c237024fd73e97303_623x89.png) **InputDispatcher分發鍵盤事件** * **InputDispatcher分發鍵盤事件 – InputDispatcher. dispatchOnceInnerLocked** ![](https://box.kancloud.cn/e909047f55aade541344ccbac581245b_795x548.png) * **InputDispatcher分發鍵盤事件 – InputDispatcher. dispatchKeyLocked** ![](https://box.kancloud.cn/901a340a49d4993ba5ada26a93e000c4_738x496.png) > 注: > HOME鍵會被PhoneWindowManager的成員函數interceptKeyBeforeDispatching攔載,切換至Home App,這是通過post一個command到InputDispatcher的Command Queue去執行實現的 > findFocusedWindowTargetsLocked – 會調用checkInjectionPermission來檢查當前處理的鍵盤事件是否是注入的,如果是的話,再檢查注入者是否有權限。注入事件的時候也會做權限檢查。 > 注入輸入事件: > 1. InputManagerService.injectInputEvent > 2. InputDispatcher::injectInputEvent > findFocusedWindowTargetsLocked還會檢查上次分發給Target Window的輸入事件是否已經有5s內處理完成,沒有處理完成的話就會產生一個ANR Command,并且post到InputDispatcher的Command Queue去執行,最終的ANR窗口是通過mPolicy來通知AMS彈出的 * **InputDispatcher分發鍵盤事件 – InputDispatcher.dispatchMotionLocked** ![](https://box.kancloud.cn/b231f9a975d0a151ba9e5b1283919758_741x476.png) * **InputDispatcher分發鍵盤事件-- InputDispatcher.dispatchEventLocked** ![](https://box.kancloud.cn/23f279a8b7716e21b7e71c48d762eec0_811x244.png) * **InputDispatcher分發鍵盤事件-- InputDispatcher.prepareDispatchCycleLocked** ![](https://box.kancloud.cn/e40f04876544e80e276918303046620d_869x491.png) > 注:標志位的解釋參見InputDispatcher.h * **InputDispatcher分發鍵盤事件-- InputDispatcher.startDispatchCycleLocked** ![](https://box.kancloud.cn/3359d23e797cc0a518552aae9fc33019_695x573.png) * **InputDispatcher分發鍵盤事件—InputPublisher.publishKeyEvent** ![](https://box.kancloud.cn/4c2d06837a09267288577dd6ecdb8910_510x482.png) * **InputDispatcher分發鍵盤事件— InputChannel::sendMessage** ![](https://box.kancloud.cn/d6ae9c6839b53ca36871786db2baeec5_679x141.png) **App獲得鍵盤事件** * **App獲得鍵盤事件— NativeInputEventReceiver.handleEvent** ![](https://box.kancloud.cn/14c056aa1fec13ef3033cd4d2f5c04e5_756x126.png) >注: 應用程序可以通過InputEventReceiver.nativeConsumeBatchedInputEvents來批量處理InputDispatcher分發過來的輸入事件 * **App獲得鍵盤事件—NativeInputEventReceiver.consumeEvents** ![](https://box.kancloud.cn/2ffb05751c7a7cb445d226c78a81e2a1_842x611.png) >注: InputConsumer.consumer的返回值等于WOULD_BLOCK時表示當前沒有發生輸入事件,這時候就會開始批量處理剛才緩存起來的輸入事件 * **App獲得鍵盤事件—InputComsumer.consume** ![](https://box.kancloud.cn/1879169f6c0cfe7c0cb3793b860a4ba6_820x665.png) > 注:AMOTION_EVENT_ACTION_MOVE和AMOTION_EVENT_ACTION_HOVER_MOVE類型的事件會被緩存起來批量處理 * **App獲得鍵盤事件—InputChannel.receiveMessage** ![](https://box.kancloud.cn/41f5f1967bb53876b424e0ec4a8f3ef4_560x306.png) * **App獲得鍵盤事件—InputEventReceiver.dispatchInputEvent** ![](https://box.kancloud.cn/834455503da85d52bfbcb3e9a8f8ac72_582x139.png) * **App獲得鍵盤事件—WindowInputEventReceiver.onInputEvent** ![](https://box.kancloud.cn/ec941002ec5944ddd0e1b6d638e2a143_681x288.png) * **App獲得鍵盤事件—ViewRootImpl.enqueueInputEvent** ![](https://box.kancloud.cn/427ceef05f71f75478d719f7985fca42_737x524.png) **App獲得鍵盤事件—ViewRootImpl. scheduleProcessInputEvents** ![](https://box.kancloud.cn/f90d5f628a40ce5ead2e9ebc5ba4f48f_694x260.png) * **App獲得鍵盤事件—ViewRootImpl. doProcessInputEvents** ![](https://box.kancloud.cn/230c756d827dcdc54d7bcb77a90061f5_722x295.png) * **App獲得鍵盤事件—ViewRootImpl. deliverInputEvent** ![](https://box.kancloud.cn/3610528165f0809bef739f9376d349a3_728x410.png) * **App獲得鍵盤事件—ViewRootImpl. deliverKeyEvent** ![](https://box.kancloud.cn/96ac4ab061ce149fda7e31cd0699eaf1_887x580.png) * **App獲得鍵盤事件—InputMethodCallback. finishedEvent** ![](https://box.kancloud.cn/156a25656d545f8bf1be4a7d42930e09_869x376.png) * **App獲得鍵盤事件—ViewRootImpl.dispatchImeFinishedEvent** ![](https://box.kancloud.cn/eeb9ec829e34e3b5271ece567a83d4ab_685x243.png) * **App獲得鍵盤事件—ViewRootImpl. handleImeFinishedEvent** ![](https://box.kancloud.cn/4ca6c8f8321f0584ff0498565f4f5389_709x560.png) * **App獲得鍵盤事件—ViewRootImpl. deliverKeyEventPostIme** ![](https://box.kancloud.cn/82f4ef134c42ed4d223dfb6545424601_681x359.png) * **App獲得鍵盤事件—DecorView. dispatchKeyEvent** ![](https://box.kancloud.cn/7f892afa215bd71ff4f51c834d00ece8_878x531.png) >注: getCallback返回的Callback接口指向當前Activity > PhoneWindow.onKeyDown和PhoneWindow.onKeyUp會對MENU和BACK等實體鍵進行處理,對MENU鍵的處理對應于openPanel的實現,對BACK鍵的處理對應于closePanel的實現 * **App獲得鍵盤事件—Activity.dispatchKeyEvent** ![](https://box.kancloud.cn/c2e7157867021e3b15467e9074a6c649_574x344.png) > 注:getWindow獲得的是一個PhoneWindow * **App獲得鍵盤事件—PhoneWindow.superDispatchKeyEvent** ![](https://box.kancloud.cn/265ad56e9955facad6c2899bb15d2333_706x606.png) >注: DecorView.dispatchKeyEvent將KeyEvent分發給當前獲得焦點的View處理 **在App中,依次獲得鍵盤事件的順序** * View(Pre Input Method) * Input Method * View(Post Input Method) * Activity * Phone Window(處理MENU、BACK等按鍵) **HOME按鍵被PhoneWindowManager攔截,直接切換至Home App** **TextView、輸入法和輸入法管理器的關系** ![](https://box.kancloud.cn/544fa15a79c6a20aa485a73ec5304bb7_637x315.png) **輸入法通過InputConnection.commitText分發過來的字符被封裝成一個類型為FLAG_DELIVER_POST_IME的KeyEvent** **在ViewRootImpl中,類型為FLAG_DELIVER_POST_IME的KeyEvent不用經過輸入法處理,而直接通過deliverKeyEventPostIme分發給View Hierarchy處理** **deliverKeyEventPostIme的處理過程與實體 鍵經過輸入法處理后的過程是一樣的** * View * Activity * Phone Window
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看