1. SystemServer 中啟動(dòng) IMS
上一章節(jié)中,介紹了輸入事件的整體架構(gòu)設(shè)計(jì)和 java 層 InputManagerService 的啟動(dòng)涯雅,接下來將從源碼中詳細(xì)跟蹤 IMS 的啟動(dòng)鲜结;首先從 SystemServer.java 中 startOtherServices() 方法開始:
private void startOtherServices() {
// 創(chuàng)建 IMS
inputManager = new InputManagerService(context); // 見1.2
// 創(chuàng)建 WMS
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
mActivityManagerService.setWindowManager(wm);
// wm.getInputMonitor() 獲取到的是InputMonitor
inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); // IMS 和 WMS 相互關(guān)聯(lián) 見 1.1
inputManager.start(); // 見1.2
}
1.1 InputMonitor:通信橋梁的建立 (InputMonitor 是 IMS 和 WMS 之間的紐帶,在是在 WMS 中初始化的);
final InputMonitor mInputMonitor = new InputMonitor(this);
public InputMonitor getInputMonitor() {
return mInputMonitor;
}
關(guān)于 InputMonitor 是 IMS 和 WMS 之間的紐帶精刷,其具體的交互是通過 InputDispatcher 完成的拗胜,在源碼中具體表現(xiàn)為兩個(gè)方面:InputDispatcher -> InputMonitor -> WMS 和 WMS -> InputMonitor -> InputDispatcher;
// InputDispatcher -> InputMonitor -> WMS:實(shí)現(xiàn)了 IMS 中的 WindowManagerCallbalck 接口
public interface WindowManagerCallbacks {
public void notifyConfigurationChanged(); // 配置變更
public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen); // LID 開關(guān)
public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered);
// 連接 InputDispatcher 與應(yīng)用的 socket 連接怒允;
public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
// ANR
public long notifyANR(InputApplicationHandle inputApplicationHandle,
InputWindowHandle inputWindowHandle, String reason);
// 以下三個(gè)回調(diào)接口是 WMS 處理事件時(shí)優(yōu)先
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags);
public long interceptKeyBeforeDispatching(InputWindowHandle focus,
KeyEvent event, int policyFlags);
// 事件在整個(gè)處理流程均未處理時(shí)埂软,與 WMS 協(xié)商解決
public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
KeyEvent event, int policyFlags);
public int getPointerLayer();
}
// 當(dāng)IMS接收到相應(yīng)輸入事件后,會(huì)通過mWindowManagerCallbacks 來調(diào)用mInputMonitor對(duì)象方法:
// return mWindowManagerCallbacks.notifyConfigurationChanged();
// return mWindowManagerCallbacks.notifyANR();
// ...
// WMS -> InputMonitor -> InputDispatcher:通過 InputMonitor 向 WMS 提供訪問一系列訪問 InputDistacher 的接口纫事;
// 比如 InputDispatcher 中的當(dāng)前窗口焦點(diǎn)勘畔,就是WMS 通過 InputMonitor 中的 updateInputWindowsLw() 通知的;
在這里先預(yù)留兩個(gè)問題:InputDispatcher 時(shí)如何通知應(yīng)用程序窗口有事件產(chǎn)生丽惶,又是如何與目標(biāo)窗口(InputTaget)之間進(jìn)行通信的炫七?
1.2 InputManagerService 的初始化和 start() 方法:IMS 從 java 層到 native 層的啟動(dòng);
(1)InputManagerService.java 的構(gòu)造函數(shù):從 InputManagerService.java 構(gòu)造函數(shù)開始钾唬,初始化 input 輸入事件關(guān)鍵類万哪;
//(1)InputManagerService.java中:構(gòu)造函數(shù)
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
// native方法,com_android_server_input_InputManagerService.cpp中
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
//(2)nativeInit():native方法抡秆,com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// MessageQueue的指針
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// native 層的 NativeInputManager 對(duì)象奕巍,并返回該對(duì)象的指針,賦值給 Java 層的 mPtr琅轧;
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
// reinterpret_cast() 用在任意指針(或引用)類型之間的轉(zhuǎn)換
return reinterpret_cast<jlong>(im);
}
//(3)native 層 NativeInputManager的構(gòu)造函數(shù):com_android_server_input_InputManagerService.cpp 中
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
// ...
sp<EventHub> eventHub = new EventHub();
// 這就是 input 輸入事件番外2 中提到的 mInputManager(輸入事件的幾個(gè)關(guān)鍵類都在其中)
mInputManager = new InputManager(eventHub, this, this);
}
//(4)native 層 InputManager 的構(gòu)造函數(shù):frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize(); // 執(zhí)行下方的 initialize() 方法
}
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
(2)InputManagerService.java 的 start() 方法:
(a)input 輸入事件從 java 層 的啟動(dòng)到 native 方法 nativeStart(mPtr) 的執(zhí)行伍绳;
(b)nativeStart(mPtr) 方法啟動(dòng)處理線程:處理線程啟動(dòng)后,就代表 IMS 在 native 層成功啟動(dòng)乍桂;
//(a)InputManagerService.java 的 start() 方法:從 java 層啟動(dòng) IMS
public void start() {
Slog.i(TAG, "Starting input manager");
// 在 InputManagerService 的對(duì)象 inputManager 初始化過程中執(zhí)行的 nativeInit() 已經(jīng)對(duì) mPtr 賦值冲杀;
nativeStart(mPtr); // 關(guān)鍵方法
// 將inputmanagerservice添加到 Wathcdog中,Watchdog檢測(cè)service是否正常工作
Watchdog.getInstance().addMonitor(this);
// 監(jiān)聽Settings.System.POINTER_SPEED睹酌、Settings.System.SHOW_TOUCHES 的變化权谁,并通知native層
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
// 接收 ACTION_USER_SWITCHED,這是關(guān)于多用戶切換的操作
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
//(b)nativeStart(mPtr):com_android_server_input_InputManagerService.cpp 中
static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
// 將傳入的 mPtr 強(qiáng)轉(zhuǎn)為 NativeInputManager 對(duì)象憋沿;reinterpret_cast() 方法上面有介紹過
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
// 執(zhí)行的是 InputManager 的 start() 方法旺芽;
// 1.2 的代碼塊 c 中:在初始化 NativeInputManager 時(shí)(構(gòu)造函數(shù)中),也對(duì)成員變量 mInputManager 進(jìn)行了初始化
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
status_t InputManager::start() {
// 執(zhí)行 mDispatcherThread 和 mReaderThread 的 run() 方法辐啄,啟動(dòng)處理線程采章; 詳見 2 中的分析;
status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
// 先啟動(dòng)分發(fā)線程壶辜,再啟動(dòng)讀取線程悯舟;這里是為了保證當(dāng)事件開始讀取時(shí),一定會(huì)被分發(fā)砸民;
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;
}
至此抵怎,IMS 在 native 層的啟動(dòng)過程基本完成奋救,接下來分析線程啟動(dòng)后,做了哪些事情反惕、事件的讀取與分發(fā)又是如何完成的 (涉及到后續(xù)章節(jié)尝艘,待更新);
2. 處理線程的分析
Thread 類是 Android 為線程操作而做的一個(gè)封裝姿染,其內(nèi)部封裝了 pthread 線程工具背亥,提供了與 Java 層Thread 類相似的 API;Thread 類提供了一個(gè)名為 threadLoop() 的純虛函數(shù)盔粹,當(dāng)線程開始運(yùn)行后隘梨,將會(huì)在內(nèi)建的線程循環(huán)中不斷地調(diào)用 threadLoop(),直到此函數(shù)返回 false舷嗡,則退出線程循環(huán),從而結(jié)束線程嵌莉。
2.1 線程類簡(jiǎn)介:
(1)Thread 類的構(gòu)造函數(shù):
Thread::Thread(bool canCallJava) //注意這里需要傳入的參數(shù) canCallJava
: mCanCallJava(canCallJava),
mThread(thread_id_t(-1)),
mLock("Thread::mLock"),
mStatus(NO_ERROR),
mExitPending(false), mRunning(false)
#ifdef HAVE_ANDROID_OS
, mTid(-1)
#endif
{
}
(2)Thread 類的 run() 方法:
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
Mutex::Autolock _l(mLock);
if (mRunning) {
// thread already started
return INVALID_OPERATION;
}
// reset status and exitPending to their default value, so we can
// try again after an error happened (either below, or in readyToRun())
mStatus = NO_ERROR;
mExitPending = false;
mThread = thread_id_t(-1);
// hold a strong reference on ourself
mHoldSelf = this;
mRunning = true;
bool res;
//如果mCanCallJava為真进萄,則調(diào)用createThreadEtc函數(shù),線程函數(shù)是_threadLoop锐峭。
//_threadLoop是Thread.cpp中定義的一個(gè)函數(shù)中鼠。
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
if (res == false) {
mStatus = UNKNOWN_ERROR; // something happened!
mRunning = false;
mThread = thread_id_t(-1);
mHoldSelf.clear(); // "this" may have gone away after this.
return UNKNOWN_ERROR;
}
(3)_threadLoop(void* user) 方法:循環(huán)調(diào)用 threadLoop();
int Thread::_threadLoop(void* user)
{
Thread* const self = static_cast<Thread*>(user);
sp<Thread> strong(self->mHoldSelf);
wp<Thread> weak(strong);
self->mHoldSelf.clear();
// ...
bool first = true;
do { // 循環(huán)調(diào)用 threadLoop()
bool result;
if (first) {
first = false;
self->mStatus = self->readyToRun();
result = (self->mStatus == NO_ERROR);
if (result && !self->exitPending()) {
result = self->threadLoop();
}
} else {
result = self->threadLoop();
}
{
Mutex::Autolock _l(self->mLock);
if (result == false || self->mExitPending) { // threadLoop() 返回為 false 時(shí)沿癞,結(jié)束線程
self->mExitPending = true;
self->mRunning = false;
self->mThread = thread_id_t(-1);
// note that interested observers blocked in requestExitAndWait are
// awoken by broadcast, but blocked on mLock until break exits scope
self->mThreadExitedCondition.broadcast();
break;
}
}
strong.clear(); // 釋放引用
// And immediately, re-acquire a strong reference for the next loop
strong = weak.promote();
} while(strong != 0);
return 0;
}
這里對(duì)線程只是做了簡(jiǎn)單的介紹援雇,如果想進(jìn)一步了解,可以參考 framework 線程類椎扬;
2.2 事件讀取線程 InputReaderThread 和分發(fā)線程 InputDispatcherThread:
(1)InputDispatcherThread:
構(gòu)造函數(shù):這里只是構(gòu)建出 InputDispatcherThread 的實(shí)例惫搏;
InputDispatcherThread::InputDispatcherThread(const sp<InputDispatcherInterface>& dispatcher) :
Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}
循環(huán)執(zhí)行任務(wù):通過上面可知,nativeStart(mPtr) -> InputManager::start() 中執(zhí)行了分發(fā)線程的 run() 方法蚕涤,而 run() 方法中循環(huán)執(zhí)行 threadLoop() 方法筐赔,接下來看看這個(gè)方法:
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce(); // 這里也很簡(jiǎn)單,也就是循環(huán)執(zhí)行 mDispatcher 的 dispatchOnce() 方法揖铜;
return true; // return true 表示一直循環(huán)執(zhí)行
}
(2)InputReaderThread:與 InputDispatcherThread 一致茴丰,比較簡(jiǎn)單;
// 構(gòu)造函數(shù)
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
Thread(/*canCallJava*/ true), mReader(reader) {
}
// 循環(huán)執(zhí)行任務(wù)
bool InputReaderThread::threadLoop() {
mReader->loopOnce(); // 循環(huán)執(zhí)行 mReader的 loopOnce() 方法天吓;
return true;
}
小結(jié):
SystemServer.java 中 startOtherServices():創(chuàng)建 java 層的 IMS(inputManager)贿肩,同時(shí)創(chuàng)建 WMS(wm),并通過inputManager.setWindowManagerCallbacks(wm.getInputMonitor()) 進(jìn)行相互關(guān)聯(lián)龄寞;最后執(zhí)行 inputManager.start() 啟動(dòng) IMS汰规;
(1)InputManagerService.java 中的構(gòu)造函數(shù):調(diào)用 mPtr = nativeInit(...),創(chuàng)建 native 層的 NativeInputManager萄焦,并保存其返回的指針于 mPtr 中控轿;
(2)InputManagerService.java 的 start() 方法:調(diào)用 nativeStart(mPtr)冤竹,IMS 在 native 層啟動(dòng);nativeInit() 方法:創(chuàng)建 NativeInputManager 對(duì)象并返回其指針茬射,同時(shí)創(chuàng)建 InputManager 的對(duì)象和輸入事件所需幾個(gè)關(guān)鍵類的對(duì)象(EventHub, InputDispatcher, InputDispatcherThread, InputReader, InputReaderThread) 鹦蠕;
nativeStart(mPtr) 方法:執(zhí)行了事件分發(fā)線程(mDispatcherThread) 和 事件讀取線程(mReaderThread)的 run() 方法,至此 native 層 IMS 的啟動(dòng)完成在抛;