Android7 Input(一)Android Input服務初始化

本系列博客主要描述Android 7.1系統中輸入管理服務InputManagerService的源碼分析。

概述

本文主要描述了InputManagerService服務的初始化和啟動,在Android7系統上InputManagerService服務的框架如下所示:

注:箭頭的方向,并不能真實代表數據流向方向。

1、FrameWorks層:inputManagerService對外提供服務的模塊;

2、JNI層:因為InputManagerService要去管理底層硬件輸入設備,而在Android 7系統的所有與硬件相關的部分,都會涉及到JNI層。用C++代碼去管理硬件設備;

3、Inputfliger: 是InputManager事件處理的核心事件,包括事件的獲取和分發等;

4、kernel層,主要涉及的input輸入驅動,并且將設備產生的事件通過inpu子系統上傳給C++ inputflinger層;

5、硬件層,具體的輸入設備,因為輸入設備的類型很過,這里只是大概羅列出了嵌入式設備上常用的幾個;

InputManagerService服務的初始化和啟動比較簡單,由SystemServer服務創建并拉起。

源碼路徑

本文描述中涉及的源碼有:

frameworks/base/services/java/com/android/server/SystemServer.java

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

framesworks/native/services/inputflinger/inputManager.cpp

InputManagerServie服務的初始化

java層的服務初始化

在系統核心服務SystemServer初始化中,在啟動其他服務startOtherService方法中,會創建InputManagerService服務。代碼片段如下所示:

frameworks/base/services/java/com/android/server/SystemServer.java

 private void startOtherServices() {......traceBeginAndSlog("StartInputManagerService");/* 創建InputManagerService服務 */inputManager = new InputManagerService(context);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);traceBeginAndSlog("StartWindowManagerService");wm = WindowManagerService.main(context, inputManager,mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);ServiceManager.addService(Context.WINDOW_SERVICE, wm);/* 注冊InputManagerServie服務  */ServiceManager.addService(Context.INPUT_SERVICE, inputManager);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);if (!disableVrManager) {traceBeginAndSlog("StartVrManagerService");mSystemServiceManager.startService(VrManagerService.class);Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}mActivityManagerService.setWindowManager(wm);/* 設置InputManagerService的窗口回調接口 */inputManager.setWindowManagerCallbacks(wm.getInputMonitor());......}

1、在systemServer的服務中創建InputManagerService;

2、設置InputManagerService的窗口回調接口,因此最終的事件要傳遞給上層App的Windows窗口去處理;

創建InputManagerService并進入它的構造方法繼續初始化,代碼片段如下所示:

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

 public InputManagerService(Context context) {this.mContext = context;/* 創建Handler, 并使用displayThead現成的Looper */this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());mUseDevInputEventForAudioJack =context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="+ mUseDevInputEventForAudioJack);/* 調用InputManagerService服務的JNI方法nativeInit繼續初始化 */mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());String doubleTouchGestureEnablePath = context.getResources().getString(R.string.config_doubleTouchGestureEnableFile);mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :new File(doubleTouchGestureEnablePath);LocalServices.addService(InputManagerInternal.class, new LocalService());}

在構造方法中:

1、創建InputManagerHander,并使用DisplayThread線程的Looper處理Handler消息;

2、調用InputManagerService服務的JNI方法nativeInit()方法繼續初始化,并且將mHandler.getLooper().getQueue()隊列傳遞給JNI層,在前面的初始化中InputManagerService自己的Handler使用了DisplayThread的Looper, 也就是說,在這個地方等同于將DisplayThread線程的消息隊列傳遞給了InputManagerService的JNI層;

native層的初始化

根據前面的描述,InputManagerService服務的Java層調用nativeInit方法,繼續初始化Native層,初始化代碼片段,如下所示:

a、nativeInit()

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,jobject serviceObj, jobject contextObj, jobject messageQueueObj) {/* 將java層的messageQueue對象轉化到對應的native層的messageQueue對象 */sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);if (messageQueue == NULL) {jniThrowRuntimeException(env, "MessageQueue is not initialized.");return 0;}/* 創建NativeInputManager輸入管理 */NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,messageQueue->getLooper());im->incStrong(0);/* 將native層的對象指針返回java層 */return reinterpret_cast<jlong>(im);
}

1、將java層的MessageQueue對象轉化到它對應native層的C++對象,這個比較管理,涉及到后面的事件處理,暫時先不描述;

2、創建NativeInputManager對象;

3、返回JNI創建的C++對象的指針返回java層;

b、NativeInputManger的初始化

NativeInputManager的初始化,關鍵代碼片段如下所示:

NativeInputManager::NativeInputManager(jobject contextObj,jobject serviceObj, const sp<Looper>& looper) :mLooper(looper), mInteractive(true) {....../* 創建EventHub() 事件獲取*/sp<EventHub> eventHub = new EventHub();mInputManager = new InputManager(eventHub, this, this);

1、創建EventHub()對象,該對象,主要就是獲取輸入事件(各種輸入設備產生的事件和軟件模擬產生的事件);

2、創建InputManager對象;

c、InputManager對象的初始化

framesworks/native/services/inputflinger/inputManager.cpp

InputManager對象初始化中如下所示:

   const sp<EventHubInterface>& eventHub,const sp<InputReaderPolicyInterface>& readerPolicy,const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {/* 創建事件分發對象 */mDispatcher = new InputDispatcher(dispatcherPolicy);/* 創建事件獲取對象 */mReader = new InputReader(eventHub, readerPolicy, mDispatcher);initialize();

1、創建事件分發對象;

2、創建事件獲取對象;

3、創建事件分發和事件獲取線程,如下所示:

void InputManager::initialize() {/* 創建事件獲取線程 */mReaderThread = new InputReaderThread(mReader);/* 創建事件分發線程 */mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

至此,InputManagerService服務從java層的初始化過程到JNI層的初始化過程,描述完成.

InputManagerService服務啟動

Java層的啟動

InputManagerSerivice服務在Java層的啟動,也是在SystemServer服務中完成。非常簡單。執行代碼片段如下所示:

frameworks/base/services/java/com/android/server/SystemServer.java

/* 設置InputManagerService的窗口回調接口 */inputManager.setWindowManagerCallbacks(wm.getInputMonitor());/* 啟動InputManagerService服務 */inputManager.start();

然后調用InputManagerService中的start方法,關鍵執行代碼片段如下:

public void start() {Slog.i(TAG, "Starting input manager");/* 調用JNI層nativeStart */nativeStart(mPtr);// Add ourself to the Watchdog monitors.Watchdog.getInstance().addMonitor(this);

1、直接調用jni層的nativeStart的接口;

Native層的啟動

jni層的啟動,關鍵代碼片段如下所示:

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);status_t result = im->getInputManager()->start();if (result) {jniThrowRuntimeException(env, "Input manager could not be started.");}
}

最終調用InputManager的start方法

framesworks/native/services/inputflinger/inputManager.cpp

status_t InputManager::start() {/* 開啟分發線程 */status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputDispatcher thread due to error %d.", result);return result;}/* 開啟事件獲取線程 */result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);if (result) {ALOGE("Could not start InputReader thread due to error %d.", result);mDispatcherThread->requestExit();return result;}return OK;
}

總結

1、InputManagerService服務的注冊和啟動都在SystemServer服務中完成;

2、InputManagerservice服務初始化過程中會在native層注冊事件獲取和分發的線程;

3、整個初始化過程中,從Java層到native層都傳遞了DisplayThread線程的Looper的MessageQueue;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898370.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898370.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898370.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用于 RGB-D 顯著目標檢測的點感知交互和 CNN 誘導的細化網絡(問題)

摘要 問題一&#xff1a;但在對自模態和跨模態的全局長距離依賴關系進行建模方面仍顯不足。什么意思&#xff1f; 自模態&#xff08;Intra-modal&#xff09;全局依賴&#xff1a;在同一模態內&#xff0c;長距離像素之間的信息交互對于理解全局背景很重要&#xff0c;但 CN…

html5基于Canvas的經典打磚塊游戲開發實踐

基于Canvas的經典打磚塊游戲開發實踐 這里寫目錄標題 基于Canvas的經典打磚塊游戲開發實踐項目介紹技術棧核心功能實現1. 游戲初始化2. 游戲對象設計3. 碰撞檢測系統4. 動畫系統5. 用戶界面設計 性能優化1. 渲染優化2. 內存管理 項目亮點技術難點突破項目總結 項目介紹 在這個…

MySQL外鍵約束下的索引刪除難題:從報錯到完美解決的實戰指南

&#x1f6a8; MySQL外鍵約束下的索引刪除難題&#xff1a;從報錯到完美解決的實戰指南 &#x1f525; 問題背景&#xff1a;一個看似簡單的刪除操作引發的連環坑 場景復現&#xff1a;某日接到需求&#xff0c;需刪除 invite_codes 表中的冗余索引 FKnqn27fyjlgio5y60eieohi0…

使用 request 的 axios 狀態碼分析

request.interceptors.response.use(function(response){},function(error){})后端返回結果code400不經過response,直接跳到error。 當后端返回狀態碼為 400 時直接進入 error 回調而不經過 response 回調&#xff0c;這是因為 axios 默認會將狀態碼不在 200 - 299 范圍內的響…

Rust嵌入式開發環境搭建指南(基于Stm32+Vscode)

Rust嵌入式開發環境搭建指南(基于Stm32+Vscode) 部分目錄如下所示: 目錄 簡介Rust開發環境安裝STM32開發工具鏈安裝VSCode環境配置VSCode插件安裝調試器配置項目創建與配置常見問題與解決方案簡介 本文檔旨在指導開發者如何搭建基于Rust語言的STM32嵌入式開發環境。相比傳…

動態規劃合集——動態規劃基本原理

動態規劃合集——動態規劃基本原理 動態規劃原理1258&#xff1a;【例9.2】數字金字塔 動態規劃原理深度優先搜索記憶化搜索動態規劃&#xff08;順推&#xff09;動態規劃原理題解分析 滾動數組優化動態規劃&#xff08;逆推&#xff09; 動態規劃原理 從數塔問題出發理解動態…

如何讓節卡機器人精準對點?

如何讓節卡機器人精準對點&#xff1f; JAKA Zu 軟件主界面主要由功能欄、開關欄、菜單欄構成。 菜單欄&#xff1a;控制柜管理&#xff0c;機器人管理與軟件管理組成。主要功能為對控制柜關機、APP 設置、機器人本體設 置、控制柜設置、連接機器人和機器人顯示等功能。 開關…

自動化測試工具-Playwright介紹和快速實例

Playwright 是什么 Playwright 是由 Microsoft 開發的開源自動化測試工具,專為現代 Web 應用設計。它支持 Chromium、Firefox 和 WebKit 內核的瀏覽器,能夠跨平臺(Windows、macOS、Linux)運行,提供強大的瀏覽器自動化能力,適用于測試、爬蟲和監控等場景。 Playwright的…

軟考程序員考試知識點匯總

軟考程序員考試&#xff08;初級資格&#xff09;主要考察計算機基礎理論、編程能力及軟件開發相關知識。以下是核心知識點總結及備考建議&#xff1a; 一、計算機基礎 數制與編碼 二進制、八進制、十進制、十六進制轉換原碼、反碼、補碼表示&#xff08;整數與浮點數&#xf…

實時視頻分析的破局之道:藍耘 MaaS 如何與海螺 AI 視頻實現高效協同

一、藍耘 MaaS 平臺&#xff1a;AI 模型全生命周期管理的智能引擎 藍耘 MaaS&#xff08;Model-as-a-Service&#xff09;平臺是由藍耘科技推出的 AI 模型全生命周期管理平臺&#xff0c;專注于為企業和開發者提供從模型訓練、推理到部署的一站式解決方案。依托云原生架構、高…

設計模式(行為型)-策略模式

目錄 定義 類圖 角色 角色詳解 Strategy&#xff08;抽象策略類&#xff09;? Context&#xff08;環境類 / 上下文類&#xff09;? ConcreteStrategy&#xff08;具體策略類&#xff09;? 優缺點 優點? 缺點? 使用場景 類行為差異場景? 動態算法選…

【算法day14】三數之和

三數之和 https://leetcode.cn/problems/3sum/description/ 給你一個整數數組 nums &#xff0c;判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i ! j、i ! k 且 j ! k &#xff0c;同時還滿足 nums[i] nums[j] nums[k] 0 。請你返回所有和為 0 且不重復的三元組。…

優化器/模型參數/超參數

參數&#xff08;Parameters&#xff09; vs. 超參數&#xff08;Hyperparameters&#xff09; 1.1 參數&#xff08;Parameters&#xff09; 定義&#xff1a;模型中需要學習的變量&#xff0c;例如神經網絡中的權重&#xff08;Weight&#xff09;和偏置&#xff08;Bias&a…

10、STL中的unordered_map使用方法

一、了解 1、unordered_map(哈希) unordered_map是借用哈希表實現的關聯容器。 訪問鍵值對O&#xff08;1&#xff09;&#xff0c;最壞情況O&#xff08;n&#xff09;&#xff0c;例如哈希沖突嚴重時。【n是一個哈希桶的元素數量】 unordered_map特性 鍵值對存儲&#xff…

C++ 頭文件說明

如果一個程序足夠大&#xff0c;代碼功能很多&#xff0c;可以想象&#xff0c;不可能把代碼寫在一個cpp文件里。我們需要模塊化&#xff0c;這樣的好處很多&#xff0c;方便分工合作&#xff0c;可讀性提高&#xff0c;調用也方便。 這個要怎么做呢&#xff1f; 很簡單直接當…

Lambda 表達式的語法:

在 Java 中&#xff0c;Lambda 表達式&#xff08;也稱為匿名方法&#xff09;是一種簡潔的表示方法接口&#xff08;Functional Interface&#xff09;實現的方式。它是 Java 8 引入的特性&#xff0c;目的是提高代碼的簡潔性和可讀性。 Lambda 表達式的語法&#xff1a; La…

C#零基礎入門篇(18. 文件操作指南)

## 一、文件操作基礎 在C#中&#xff0c;文件操作主要通過System.IO命名空間中的類來實現&#xff0c;例如File、FileStream、FileInfo等。 ## 二、常用文件操作方法 ### &#xff08;一&#xff09;文件讀取 1. **使用File.ReadAllText方法讀取文件內容為字符串** …

每日一題--內存池

內存池&#xff08;Memory Pool&#xff09;是一種高效的內存管理技術&#xff0c;通過預先分配并自主管理內存塊&#xff0c;減少頻繁申請/釋放內存的系統開銷&#xff0c;提升程序性能。它是高性能編程&#xff08;如游戲引擎、數據庫、網絡服務器&#xff09;中的核心優化手…

【Linux系統】Linux進程終止的N種方式

Linux系列 文章目錄 Linux系列前言一、進程終止的概念二、進程終止的場景三、進程終止的實現3.1 程序退出碼3.2 運行完畢結果正常3.3 運行完畢結果異常3.4 程序異常退出 總結 前言 進程終止是操作系統中&#xff0c;進程的一個重要階段&#xff0c;他標志著進程生命周期的結束…

正則表達式引擎深入探討

正則表達式引擎&#xff08;Regular Expression Engine&#xff09;是正則表達式得以“活起來”的核心。它是一個精密的軟件組件&#xff0c;負責接收正則表達式和輸入文本&#xff0c;解析模式并執行匹配或替換操作&#xff0c;最終輸出結果——可能是簡單的“是否匹配”&…