分析Input子系統的啟動主要是看InputManagerService
的啟動,InputManagerService
是java層的一個系統服務,繼承IInputManager.Stub
,作為binder伺服器端,在SystemServer
中啟動:
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
......
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context);
t.traceEnd();
......
}
public InputManagerService(Context context) {
this.mContext = context;
//建立handler,執行在"android.display"執行緒
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
......
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
InputManagerService
建構函式中建立了一個InputManagerHandler
,使用的是"android.display"執行緒的looper物件,執行在"android.display"執行緒。
// com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
//java層MessageQueue的mPtr指向native層MessageQueue,這裡
//就是將mPtr強轉為native層MessageQueue
sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == nullptr) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
//建立NativeInputManager
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast<jlong>(im);
}
nativeInit實際上就做了一件事,拿到java層InputManagerService
傳遞下來的"android.display"執行緒的Looper對應的MessageQueue獲取native層MessageQueue,之後通過此native層MessageQueue的Looper建立NativeInputManager
。
// com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
//java層的InputManagerService物件
mServiceObj = env->NewGlobalRef(serviceObj);
{
AutoMutex _l(mLock);
mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
mLocked.pointerSpeed = 0;
mLocked.pointerGesturesEnabled = true;
mLocked.showTouches = false;
mLocked.pointerCapture = false;
mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
}
mInteractive = true;
//建立InputManager
mInputManager = new InputManager(this, this);
//將mInputManager新增到ServiceManager,可以通過getService獲取
defaultServiceManager()->addService(String16("inputflinger"),
mInputManager, false);
}
NativeInputManager
建構函式也很簡單,就是建立了InputManager
,並新增到ServiceManager,InputManager
是binder伺服器端,它的建構函式中接收兩個物件:InputReaderPolicyInterface
和InputDispatcherPolicyInterface
public:
InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy);
而NativeInputManager
是這兩個物件的子類,所以傳遞的是this
class NativeInputManager : public virtual RefBase,
public virtual InputReaderPolicyInterface,
public virtual InputDispatcherPolicyInterface,
public virtual PointerControllerPolicyInterface {
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
//(1)
mDispatcher = createInputDispatcher(dispatcherPolicy);
//(2)
mClassifier = new InputClassifier(mDispatcher);
//(3)
mReader = createInputReader(readerPolicy, mClassifier);
}
InputManager
建構函式中建立了這三個物件:
private:
sp<InputDispatcherInterface> mDispatcher;
sp<InputClassifierInterface> mClassifier;
sp<InputReaderInterface> mReader;
};
現在來分別看看這三個物件的初始化過程,首先看(1):mDispatcher = createInputDispatcher(dispatcherPolicy)
//InputDispatcherFactory.cpp
sp<InputDispatcherInterface> createInputDispatcher(
const sp<InputDispatcherPolicyInterface>& policy) {
return new android::inputdispatcher::InputDispatcher(policy);
}
這裡簡單粗暴的直接new了一個InputDispatcher
,InputDispatcher
是InputDispatcherInterface
的子類,InputDispatcher
是一個非常重要的物件,它是Input事件傳送到對應視窗的分發者
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
mDispatchEnabled(false),
mDispatchFrozen(false),
mInputFilterEnabled(false),
// mInTouchMode will be initialized by the WindowManager to the default device config.
// To avoid leaking stack in case that call never comes, and for tests,
// initialize it here anyways.
mInTouchMode(true),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT) {
//建立自己的Looper
mLooper = new Looper(false);
mReporter = createInputReporter();
mKeyRepeatState.lastKeyEntry = nullptr;
//獲取java層的一些設定引數,寫到mConfig中,主要就是如下兩個值:
//public static final int DEFAULT_LONG_PRESS_TIMEOUT = 400;
//private static final int KEY_REPEAT_DELAY = 50;
policy->getDispatcherConfiguration(&mConfig);
}
接著再看第二個物件:(2)
mClassifier = new InputClassifier(mDispatcher);
// --- InputClassifier ---
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener)
: mListener(listener), mHalDeathRecipient(new HalDeathRecipient(*this)) {}
它的建構函式非常簡單,將前面建立的InputDispatcher
儲存在了mListener
中,並建立了一個監聽HAL的死亡回撥物件,InputClassifierM
是一個空殼子,它提供的如下函數內部實現都是呼叫到了InputDispatcher
中去:
class InputClassifier : public InputClassifierInterface {
public:
explicit InputClassifier(const sp<InputListenerInterface>& listener);
virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
virtual void notifyKey(const NotifyKeyArgs* args) override;
virtual void notifyMotion(const NotifyMotionArgs* args) override;
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
再看第三個物件(3)
mReader = createInputReader(readerPolicy, mClassifier);
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener) {
return new InputReader(std::make_unique<EventHub>(), policy, listener);
}
同樣是直接new的一個InputReader
,它接收了一個EventHub
物件,這個物件非常重要,它是讀取驅動原始Input事件的主要類,InputReader
建構函式比較簡單,程式碼不多,所以我們先來分析EventHub
的初始化。
// --- InputReader ---
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
mQueuedListener = new QueuedInputListener(listener);
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
EventHub
繼承EventHubInterface
,這是它的建構函式:
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) {
ensureProcessCanBlockSuspend();
//建立epoll,對EPOLL_CLOEXEC個fd進行監聽
mEpollFd = epoll_create1(EPOLL_CLOEXEC);
//建立inotify
mINotifyFd = inotify_init();
//對"/dev/input"目錄下的檔案進行監聽,監聽事件是檔案的建立與刪除
mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
if (isV4lScanningEnabled()) {
//對"/dev"目錄進行監聽
mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
} else {
mVideoWd = -1;
}
//建立epoll事件結構體
struct epoll_event eventItem = {};
//監聽事件:
//EPOLLIN :表示對應的檔案描述符可以讀(包括對端SOCKET正常關閉);
//EPOLLWAKEUP:系統會在事件排隊時就保持喚醒,從epoll_wait呼叫開始,持續要下一次epoll_wait呼叫
eventItem.events = EPOLLIN | EPOLLWAKEUP;
//epoll監聽的fd為mINotifyFd
eventItem.data.fd = mINotifyFd;
//將mINotifyFd新增到epoll
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;
//將讀管道新增到epoll
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
如果有看過我前一篇文章AndroidR Input子系統(1)INotify與Epoll機制就會對上面這段程式碼非常熟悉了,簡單總結下INotify與Epoll:
INotify的用法分為三步:
inotify_init
建立一個inotify物件inotify_add_watch
對檔案路徑進行監聽read
讀取監聽到的事件Epoll的使用步驟也很簡單:
epoll_create
建立epoll物件epoll_event
結構體,並註冊到epoll_ctl
進行監聽epoll_wait
進入監聽狀態,傳入一個epoll_event
結構體陣列,用於收集監聽到的事件epoll_event
結構體陣列,依次取出事件處理EventHub
建構函式中結合INotify與Epoll對"/dev/input"目錄進行監聽,以及建立了一對管道,將讀端mWakeReadPipeFd
新增到Epoll進行監聽,之後只需要呼叫epoll_wait
等待事件發生就行了,至於在哪裡調的epoll_wait
,我們後面再看。
EventHub
建立完之後再回來看InputReader
,它的建構函式就比較簡單了。
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
//建立QueuedInputListener,並傳入InputClassifier
mQueuedListener = new QueuedInputListener(listener);
{ // acquire lock
AutoMutex _l(mLock);
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
} // release lock
}
到此InputManager
的建構函式中建立的三個物件InputDispatcher
,InputClassifier
,InputReader
就分析完了,即InputManagerService
構造方法中呼叫的nativeInit
函數就結束了,接著再回到SystemService
中,InputManagerService
建立完成之後,會呼叫它的start
方法:
//SystemService.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
......
inputManager = new InputManagerService(context);
......
inputManager.start();
.....
}
//InputManagerService.java
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr);
// 新增Watchdog的監聽
Watchdog.getInstance().addMonitor(this);
//註冊一系列Settings資料庫值的監聽
.....
}
這個方法中我們關注的是nativeStart
這個方法,mPtr指向nativeInit
中建立的NativeInputManager
,
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.");
}
}
NativeInputManager
的getInputManager
返回nativeStart
建立的InputManager
,呼叫其start
函數:
status_t InputManager::start() {
//(1)
status_t result = mDispatcher->start();
if (result) {
ALOGE("Could not start InputDispatcher thread due to error %d.", result);
return result;
}
//(2)
result = mReader->start();
if (result) {
ALOGE("Could not start InputReader due to error %d.", result);
mDispatcher->stop();
return result;
}
return OK;
}
這個函數中非常重要的兩步就是分別呼叫了InputDispatcher
和InputReader
的start
函數,首先來看(1):
//InputDispatcher.cpp
status_t InputDispatcher::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputDispatcher", [this]() { dispatchOnce(); }, [this]() { mLooper->wake(); });
return OK;
}
mThread
如果已經存在則返回,否則建立,mThread
型別為InputThread
,InputThread
內部有一個Thread
,InputThread
的建構函式中接受三個引數:
class InputThread {
public:
explicit InputThread(std::string name, std::function<void()> loop,
std::function<void()> wake = nullptr);
一個string,代表此執行緒名稱,還有兩個std::function
,傳遞的則是兩個Lambda
表示式,這兩個Lambda
表示式中分別呼叫dispatchOnce()
和mLooper->wake()
這兩個函數,接著再看InputThread
建構函式的具體實現:
//InputThread.cpp
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
: mName(name), mThreadWake(wake) {
mThread = new InputThreadImpl(loop);
mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
InputThread
建構函式中將接收的兩個Lambda
表示式一個傳遞給了InputThreadImpl
,另一個儲存在了自己mThreadWake
中,
InputThreadImpl
繼承Thread
,是一個執行緒,
接著呼叫run
函數啟動執行緒,執行緒啟動之後就會呼叫自己的threadLoop
函數:
class InputThreadImpl : public Thread {
public:
explicit InputThreadImpl(std::function<void()> loop)
: Thread(/* canCallJava */ true), mThreadLoop(loop) {}
~InputThreadImpl() {}
private:
std::function<void()> mThreadLoop;
bool threadLoop() override {
mThreadLoop();
return true;
}
};
InputThreadImpl
的threadLoop
函數很簡單,呼叫了自己的mThreadLoop
函數,mThreadLoop
接收了一個Lambda
表示式:([this]() { dispatchOnce(); }
),即
執行緒啟動時就會呼叫
InputThreadImplInputDispatcher
的dispatchOnce
函數,至於dispatchOnce
的細節我們在後面再分析。
接著我們再來看看InputReader
的start
函數:
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
InputReader
的start
函數就和InputDispatcher
有異曲同工之妙了,只不過執行緒的名字和兩個Lambda
表示式不一樣,所以我們知道最終這個執行緒啟動之後會呼叫InputReader
的loopOnce()
函數。
到此Input
系統的啟動篇就分析完了,我們大致總結一下:
SystemServer
建立InputManagerService
這個系統服務。InputManagerService
構造方法中建立"android.display"執行緒,呼叫nativeInit
函數,將"android.display"執行緒的Looper對應的MessageQueue傳遞到native層。nativeInit
函數中建立NativeInputManager
物件,並將其指標返回到java層mPtr
儲存。NativeInputManager
建構函式中建立InputManager
物件,並將其註冊到ServiceManager
,其服務名稱為:「inputflinger」,InputManager
建構函式中建立三個重要物件:InputDispatcher
,InputClassifier
,InputReader
,比較重要的是在構造InputReader
是建立了EventHub
物件。EventHub
建構函式中通過inotify和epoll機制對目錄"/dev/input"監聽,主要監聽此目錄下檔案的建立和刪除,到此nativeInit
函數完畢。SystemServer
中會接著呼叫InputManagerService
的start
方法,此方法中呼叫nativeStart
作進一步初始化,nativeStart
函數中呼叫InputManager
的start
函數。InputManager
的start
函數中分別呼叫了InputDispatcher
和InputReader
的start
函數,即分別啟動了其內部執行緒InputThreadImpl
,InputDispatcher
內部執行緒(名字:「InputDispatcher」)啟動呼叫了自己的dispatchOnce()
函數,InputReader
內部執行緒(名字:「InputReader」)啟動呼叫了自己的loopOnce()
函數。