1 前言
IMS 是 InputManagerService 的簡稱,主要負責輸入事件管理,
1.1 基本概念
- 輸入設備:螢屏、電源/音量、鍵鼠、充電口、藍牙、wifi 等
- 設備節點:當輸入設備可用時,Linux 內核會在 /dev/input 中創建對應的設備節點
- 輸入事件:觸摸事件、按鍵事件、滑鼠事件、插拔事件等
- 輸入子系統:負責采集 Linux 內核中輸入事件原始資訊,原始資訊由 Kernel space 的驅動層一直傳遞到 User space 的設備節點
IMS 所做的作業就是監聽 /dev/input 下的所有的設備節點,當設備節點有資料時,對資料進行加工處理并找到合適的 Window,將輸入事件派發給它,
1.2 IMS 框架

(1)EventHub
- 監聽、掃描、打開 /dev/input 目錄下的輸入設備
- 根據組態檔和鍵值映射檔案對設備進行配置和鍵值映射
- 將所有設備添加到本地串列中
- 抽取驅動程式上報的 inputEvent,主要包含設備可用性變化事件(設備事件)、設備節點中讀取的原始輸入事件,
(2)InputReader
- 根據設備型別添加不同 InputMapper
- 通過 EventHub.getEvents() 獲取 EventHub 中未處理的事件
(3)InputDispatcher
- 事件過濾,并發給上層,
2 Java 層 IMS 初始化流程
2.1 IMS 啟動流程
(1)main
/frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
(2)run
/frameworks/base/services/java/com/android/server/SystemServer.java
private void run() {
try {
...
// 創建Looper
Looper.prepareMainLooper();
// 加載libandroid_servers.so
System.loadLibrary("android_servers");
// 創建系統的 Context:ContextImpl.createSystemContext(new ActivityThread())
createSystemContext();
// 創建 SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
...
}
...
try {
//啟動引導服務,ActivityManagerService、ActivityTaskManagerService、PackageManagerService、PowerManagerService、DisplayManagerService 等
startBootstrapServices();
//啟動核心服務,BatteryService、UsageStatusService 等
startCoreServices();
//啟動其他服務,InputManagerService、WindowManagerService、CameraService、AlarmManagerService 等
startOtherServices();
...
}
...
// 開啟訊息回圈
Looper.loop();
}
(3)startOtherServices
/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
WindowManagerService wm = null;
...
InputManagerService inputManager = null;
...
try {
...
inputManager = new InputManagerService(context);
...
//PhoneWindowManager 是 WMP 的實作類
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager, false, DUMP_FLAG_PRIORITY_CRITICAL);
...
mActivityManagerService.setWindowManager(wm);
...
wm.onInitReady(); //initPolicy
...
//wm 的 mInputManagerCallback 屬性在定義時就被初始化
inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
inputManager.start();
...
}
}
通過 ServiceManager.addService() 將 Context.INPUT_SERVICE 與 IMS 系結,因此在其他行程中可以通過如下方式獲取 IMS,
IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
IInputManager im = IInputManager.Stub.asInterface(b);
2.2 IMS 初始化
(1)構造方法
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputManagerService(Context context) {
this.mContext = context;
//在 android.display 執行緒中處理訊息
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
...
//mPtr 為 JNI 層 NativeInputManager 物件的地址
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());
}
nativeInit() 方法在 JNI 層創建了 NativeInputManager 物件,并回傳其地址(后文會介紹);LocalService 是 IMS 的內部類,也是 InputManagerInternal 的實作類,
(2)setWindowManagerCallbacks
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void setWindowManagerCallbacks(WindowManagerCallbacks callbacks) {
mWindowManagerCallbacks = callbacks;
}
callbacks 來自 WMS.mInputManagerCallback,屬于 InputManagerCallback 類(IMS.WindowManagerCallbacks 的實作類),WMS.mInputManagerCallback 在定義時就被初始化,
(3)start
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public void start() {
//啟動 Native 層的 InputReaderThread 和 InputDispatcherThread 執行緒
nativeStart(mPtr);
//注冊監聽器
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
registerAccessibilityLargePointerSettingObserver();
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
updateAccessibilityLargePointerFromSettings();
}
nativeStart() 方法啟動 Native 層 InputReaderThread 和 InputDispatcherThread 執行緒(后面會介紹),
3 Native 層 IMS 初始化流程
本節主要介紹 IMS 構造方法中呼叫 nativeInit() 方法、start() 方法中呼叫 nativeStart() 方法的后續流程,
如圖,展示了 IMS 初始化流程,淺藍色、綠色、紫色分別表示 Java 層、JNI 層、Native 層,

3.1 nativeInit 后續流程
(1)gInputManagerMethods
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static const JNINativeMethod gInputManagerMethods[] = {
//Java 層呼叫的 nativeInit 方法對應 JNI 層的 nativeInit 方法
{ "nativeInit",
"(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
(void*) nativeInit },
//Java 層呼叫的 nativeStart 方法對應 JNI 層的 nativeStart 方法
{ "nativeStart", "(J)V",
(void*) nativeStart },
...
}
gInputManagerMethods 陣列列出了 Java 層呼叫 nativeInit()、nativeStart() 方法到 JNI 層具體呼叫方法的映射關系,
(2)nativeInit
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
//Java 層呼叫:mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
static jlong nativeInit(JNIEnv* env, jclass, jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
//獲取 JNI 層訊息佇列
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
...
//創建 NativeInputManager
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper());
im->incStrong(0);
//回傳 NativeInputManager 物件指標給 Java 層(mPtr)
return reinterpret_cast<jlong>(im);
}
NativeInputManager 是在該檔案中定義的類,
(3)NativeInputManager
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
#include <inputflinger/InputManager.h>
NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
mServiceObj = env->NewGlobalRef(serviceObj);
...
mInteractive = true;
//創建 Native 層 InputManager,2 個 this 分別為:InputReaderPolicyInterface、InputDispatcherPolicyInterface
mInputManager = new InputManager(this, this);
defaultServiceManager()->addService(String16("inputflinger"), mInputManager, false);
}
NativeInputManager 實作了 RefBase、InputReaderPolicyInterface、InputDispatcherPolicyInterface、PointerControllerPolicyInterface 4個介面,
InputManager.h 中定義了抽象的 InputManager 類,InputManager.cpp 實作了 InputManager.h 中的抽象方法,
(4)InputManager
/frameworks/native/services/inputflinger/InputManager.h
class InputManager : public InputManagerInterface, public BnInputFlinger {
...
public:
InputManager(const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
virtual status_t start();
...
virtual void setInputWindows(const std::vector<InputWindowInfo>& handles, const sp<ISetInputWindowsListener>& setInputWindowsListener);
virtual void transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken);
...
virtual void registerInputChannel(const sp<InputChannel>& channel);
private:
sp<InputReaderInterface> mReader;
sp<InputReaderThread> mReaderThread;
sp<InputClassifierInterface> mClassifier;
sp<InputDispatcherInterface> mDispatcher;
sp<InputDispatcherThread> mDispatcherThread;
void initialize();
};
注意:InputManager 繼承了 BnInputFlinger 介面(Binder 跨行程通訊的服務端),
(5)InputManager
/frameworks/native/services/inputflinger/InputManager.cpp
#include "InputManager.h"
#include "InputReaderFactory.h"
InputManager::InputManager(const sp<InputReaderPolicyInterface>& readerPolicy, const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
//創建 InputDispatcher
mDispatcher = new InputDispatcher(dispatcherPolicy);
mClassifier = new InputClassifier(mDispatcher);
//創建 InputReader,createInputReader() 是 InputReaderFactory 類的方法
mReader = createInputReader(readerPolicy, mClassifier);
initialize();
}
(6)InputDispatcher
/frameworks/native/services/inputflinger/InputDispatcher.cpp
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
mPolicy(policy), ... {
//創建訊息回圈
mLooper = new Looper(false);
mReporter = createInputReporter();
...
policy->getDispatcherConfiguration(&mConfig);
}
(7)createInputReader
/frameworks/native/services/inputflinger/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) {
return new InputReader(new EventHub(), policy, listener);
}
注意:此處創建了 EventHub,并注入到 InputReader 中,
(8)InputReader
/frameworks/native/services/inputflinger/InputReader.cpp
InputReader::InputReader(const sp<EventHubInterface>& eventHub, const sp<InputReaderPolicyInterface>& policy, const sp<InputListenerInterface>& listener) :
mContext(this), mEventHub(eventHub), mPolicy(policy), ... {
mQueuedListener = new QueuedInputListener(listener);
...
}
(9)EventHub
/frameworks/native/services/inputflinger/EventHub.cpp
EventHub::EventHub(void) :
mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
mOpeningDevices(nullptr), mClosingDevices(nullptr),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false), mNeedToScanDevices(true),
mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
...
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
...
mINotifyFd = inotify_init();
mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
...
int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
...
int wakeFds[2];
result = pipe(wakeFds);
...
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
...
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
...
eventItem.data.fd = mWakeReadPipeFd;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
...
}
(10)initialize
/frameworks/native/services/inputflinger/InputManager.cpp
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
InputReaderThread 和 InputDispatcherThread 都繼承了 Thread 類,
在 InputManager.h 檔案中,已申明 InputReaderThread 和 InputDispatcherThread 的原始碼不再開源,如下,
/*
* By design, the InputReaderThread class and InputDispatcherThread class do not share any
*/
3.2 nativeStart 后續流程
(1)nativeStart
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass, jlong ptr) {
//通過物件地址獲取 NativeInputManager 物件指標
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
//呼叫 Native 層 InputManager 的 start() 方法
status_t result = im->getInputManager()->start();
...
}
inline sp<InputManager> getInputManager() const {
return mInputManager;
}
(2)start
/frameworks/native/services/inputflinger/InputManager.cpp
status_t InputManager::start() {
//開啟 DispatcherThread 執行緒
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
...
//開啟 ReaderThread 執行緒
result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
...
return OK;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/250246.html
標籤:其他
