分析Input子系統的啟動主要是看InputManagerService的啟動,InputManagerService是java層的一個系統服務,繼承IInputManager.Stub,作為binder服務端,在SystemServer中啟動:
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
......
t.traceBegin("StartInputManagerService");
inputManager = new InputManagerService(context);
t.traceEnd();
......
}
InputManagerService
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"執行緒,
nativeInit
// 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,
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::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)
createInputDispatcher
//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物件 - 為需要監聽的fd構建一個
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.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()函式,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/182551.html
標籤:java
