frameworks/base/core/java/android/os/ServiceManager.java
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
frameworks/base/services/java/com/android/server/wm/InputManager.java
frameworks/base/services/jni/com_android_server_InputManager.cpp
frameworks/base/services/input/*
input事件能被实时处理,冥冥之中有某个服务会运行某些监听线程,不停的监测它。我是这样想的。
public class SystemServer { ...... public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } }那么这个线程对象是一个ServerThread的实例。它的run方法:
public class SystemServer { @Override public void run() { ...... Slog.i(TAG, "Input Manager"); inputManager = new InputManagerService(context, wmHandler); Slog.i(TAG, "Window Manager"); wm = WindowManagerService.main(context, power, display, inputManager, uiHandler, wmHandler, factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL, !firstBoot, onlyCore); ServiceManager.addService(Context.WINDOW_SERVICE, wm); ServiceManager.addService(Context.INPUT_SERVICE, inputManager); ActivityManagerService.self().setWindowManager(wm); inputManager.setWindowManagerCallbacks(wm.getInputMonitor()); inputManager.start(); display.setWindowManager(wm); display.setInputManager(inputManager); }
(1) 创建了一个java层input设备管理器inputManager。
(2) 运行WindowManagerService.main()方法。
public static WindowManagerService main(final Context context, final PowerManagerService pm, final DisplayManagerService dm, final InputManagerService im, final Handler uiHandler, final Handler wmHandler, final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore) { final WindowManagerService[] holder = new WindowManagerService[1]; wmHandler.runWithScissors(new Runnable() { @Override public void run() { holder[0] = new WindowManagerService(context, pm, dm, im, uiHandler, haveInputMethods, showBootMsgs, onlyCore); } }, 0); return holder[0]; }参数好多,代码不长。runWithScissors() run了一个特殊的同步task,不出意外,可以执行到Runnable.run()。run()里new了一个WindowManagerService,其构造函数也是长又长,不是代码长,是结构名字长;相关的一句是:
mInputManager = inputManager;mInputManager是class WindowManagerService的一个成员变量,是class InputManagerService的实例。
public InputManagerService(Context context, Handler handler) { this.mContext = context; this.mHandler = new InputManagerHandler(handler.getLooper()); mUseDevInputEventForAudioJack = context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack); Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack=" + mUseDevInputEventForAudioJack); mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue()); }
看到了nativeInit()进入native空间了。base/services/jni/com_android_server_input_InputManagerService.cpp 里有一张表可以找到java空间与native空间函数的对应关系。
static JNINativeMethod gInputManagerMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)I", (void*) nativeInit }, ...... };继续nativeInit()。
static jint nativeInit(JNIEnv* env, jclass clazz, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj); if (messageQueue == NULL) { jniThrowRuntimeException(env, "MessageQueue is not initialized."); return 0; } NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, messageQueue->getLooper()); im->incStrong(0); return reinterpret_cast<jint>(im); }创建了一个 NativeInputManager的实例im,其构造函数为:
NativeInputManager::NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper) : mLooper(looper) { JNIEnv* env = jniEnv(); mContextObj = env->NewGlobalRef(contextObj); mServiceObj = env->NewGlobalRef(serviceObj); { AutoMutex _l(mLock); mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE; mLocked.pointerSpeed = 0; mLocked.pointerGesturesEnabled = true; mLocked.showTouches = false; } sp<EventHub> eventHub = new EventHub(); mInputManager = new InputManager(eventHub, this, this); }这里又出现了两个input系统相关的结构class EventHub和class InputManager。先创建了一个class EventHub的强指针eventHub,并以此为参数创建了一个class InputManager实例mInputManager,要注意的是这个mInputManager是class NativeInputManager的一个成员变量,是class InputManager的实例;前面提到的mInputManager是class WindowManagerService的一个成员变量,是class InputManagerService的实例。至此,创建了一个native层的input设备管理器mInputManage。jint nativeInit()最后return reinterpret_cast<jint>(im)一个NativeInputManager指针到mPtr中,InputManagerService的mPtr成员变量。
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(); }
InputManager是大管家,怎么会自己干活呢,肯定是找家丁啊。家丁1号mEventHub,是class EventHub的实例。家丁2号mDispatcher,是class InputDispatcher的实例。家丁3号mReader,是class InputReader的实例。构造mReader时需要eventHub和mDispatcher作为参数,看来家丁3号还有点权力。
void InputManager::initialize() { mReaderThread = new InputReaderThread(mReader); mDispatcherThread = new InputDispatcherThread(mDispatcher); }这就是了,传说中的创建线程对象。这里分别创建了class InputReaderThread(负责input事件的获取)和class InputDispatcherThread(负责input消息的发送)的实例,用于初始化InputManager的mReaderThread和mDispatcherThread成员。class InputDispatcherThread和class InputReaderThread 类似。
class InputReaderThread : public Thread { public: InputReaderThread(const sp<InputReaderInterface>& reader); virtual ~InputReaderThread(); private: sp<InputReaderInterface> mReader; virtual bool threadLoop(); };看到threadLoop()方法就仿佛看到了希望,为什么这样说?因为我抢先看了threadLoop()实现。
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true; }接着有跟到了void InputReader::loopOnce();果然这个函数就是需要loop的函数。我坚信在代码的某个旮旯深处;会调用这个threadLoop(),至于是哪个旮旯,就先放一放;当务之急是搞明白input系统中的管家和家丁们的职责和特权。正如三国杀,只有了解手中武将牌的能力和特权,才能掌握胜算。接下来的一段是摘抄的。
InputManager是系统事件处理的核心,它虽然不做具体的事,但管理工作还是要做的,比如接受我们客户的投诉和索赔要求,或者老板的出气筒。
InputManager使用两个线程:
1)InputReaderThread叫做"InputReader"线程,它负责读取并预处理RawEvent,applies
policy并且把消息送入DispatcherThead管理的队列中。
2)InputDispatcherThread叫做"InputDispatcher"线程,它在队列上等待新的输入事件,并且
异步地把这些事件分发给应用程序。
InputReaderThread类与InputDispatcherThread类不共享内部状态,所有的通信都是单向的,
从InputReaderThread到InputDispatcherThread。
两个类可以通过InputDispatchPolicy进行交互。
InputManager类从不与Java交互,而InputDispatchPolicy负责执行所有与系统的外部交互,包括调用DVM业务。
基本每个启动都是由start完成的,start似曾相识,回到SytemServer的run(),就能找到它的身影。inputManager.start(),这是一段旅程的开始,从此踏上寻找不老泉的征途。
public void start() { Slog.i(TAG, "Starting input manager"); nativeStart(mPtr); // Add ourself to the Watchdog monitors. Watchdog.getInstance().addMonitor(this); registerPointerSpeedSettingObserver(); registerShowTouchesSettingObserver(); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updatePointerSpeedFromSettings(); updateShowTouchesFromSettings(); } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler); updatePointerSpeedFromSettings(); updateShowTouchesFromSettings(); }还记得mPtr吗?那个曾经的它。它是一个锋芒的针,存了一个native空间的input设备管理器的宿主NativeInputManager,这注定了它属于native世界的命运,它要从那里开始nativeStart(mPtr)。好吧,再去它的世界看看;怎么去?求助中转站啊,那里有一张表可以找到native空间的地址。
static JNINativeMethod gInputManagerMethods[] = { { "nativeStart", "(I)V", (void*) nativeStart }, }; static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) { NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr); status_t result = im->getInputManager()->start(); if (result) { jniThrowRuntimeException(env, "Input manager could not be started."); } }im就是mPtr的变身;是NativeInputManager的指针。im->getInputManager()返回的就是native的input设备管理器mInputManager。
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; }还记得InputManager()->initialize()创建的两个线程对象吗?现在走到了他们的run()方法。貌似这两个线程对象没有run()啊,那就找他的爸爸呗,它们是Thread的子类,自然继承了Thread的run()方法。找到了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; 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; } // Do not refer to mStatus here: The thread is already running (may, in fact // already have exited with a valid mStatus result). The NO_ERROR indication // here merely indicates successfully starting the thread and does not // imply successful termination/execution. return NO_ERROR; // Exiting scope of mLock is a memory barrier and allows new thread to run }查找关键字_threadLoop,createThreadEtc()负责创建android线程;其中,int Thread::_threadLoop(void* user)函数最为线程函数,this传给线程函数的参数user;this是什么?就是mDispatcherThread或mReaderThread,谁用了这,这个run()就是谁了,不是都不行。
int Thread::_threadLoop(void* user) { Thread* const self = static_cast<Thread*>(user); sp<Thread> strong(self->mHoldSelf); wp<Thread> weak(strong); self->mHoldSelf.clear(); #ifdef HAVE_ANDROID_OS // this is very useful for debugging with gdb self->mTid = gettid(); #endif bool first = true; do { bool result; if (first) { first = false; self->mStatus = self->readyToRun(); result = (self->mStatus == NO_ERROR); if (result && !self->exitPending()) { // Binder threads (and maybe others) rely on threadLoop // running at least once after a successful ::readyToRun() // (unless, of course, the thread has already been asked to exit // at that point). // This is because threads are essentially used like this: // (new ThreadSubclass())->run(); // The caller therefore does not retain a strong reference to // the thread and the thread would simply disappear after the // successful ::readyToRun() call instead of entering the // threadLoop at least once. result = self->threadLoop(); } } else { result = self->threadLoop(); } // establish a scope for mLock { Mutex::Autolock _l(self->mLock); if (result == false || self->mExitPending) { self->mExitPending = true; self->mRunning = false; // clear thread ID so that requestExitAndWait() does not exit if // called by a new thread using the same thread ID as this one. 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; } } // Release our strong reference, to let a chance to the thread // to die a peaceful death. strong.clear(); // And immediately, re-acquire a strong reference for the next loop strong = weak.promote(); } while(strong != 0); return 0; }selt是user的一个变身了,假设user是mReaderThread,先不管mDispatcherThread。我说的变身一般是只类型转换,java中有很多形式的类型转换,有待研究。
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true; }这个不是之前抢先看的东东吗?现在是DVD版的了,要清楚很多了。
void InputReader::loopOnce() { int32_t oldGeneration; int32_t timeoutMillis; bool inputDevicesChanged = false; Vector<InputDeviceInfo> inputDevices; { // acquire lock AutoMutex _l(mLock); oldGeneration = mGeneration; timeoutMillis = -1; uint32_t changes = mConfigurationChangesToRefresh; if (changes) { mConfigurationChangesToRefresh = 0; timeoutMillis = 0; refreshConfigurationLocked(changes); } else if (mNextTimeout != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout); } } // release lock size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE); { // acquire lock AutoMutex _l(mLock); mReaderIsAliveCondition.broadcast(); if (count) { processEventsLocked(mEventBuffer, count); } if (mNextTimeout != LLONG_MAX) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); if (now >= mNextTimeout) { #if DEBUG_RAW_EVENTS ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f); #endif mNextTimeout = LLONG_MAX; timeoutExpiredLocked(now); } } if (oldGeneration != mGeneration) { inputDevicesChanged = true; getInputDevicesLocked(inputDevices); } } // release lock // Send out a message that the describes the changed input devices. if (inputDevicesChanged) { mPolicy->notifyInputDevicesChanged(inputDevices); } // Flush queued events out to the listener. // This must happen outside of the lock because the listener could potentially call // back into the InputReader's methods, such as getScanCodeState, or become blocked // on another thread similarly waiting to acquire the InputReader lock thereby // resulting in a deadlock. This situation is actually quite plausible because the // listener is actually the input dispatcher, which calls into the window manager, // which occasionally calls into the input reader. mQueuedListener->flush(); }(1) mEventHub->getEvents()获取input事件。
bool InputReaderThread::threadLoop() { mReader->loopOnce(); return true; } bool InputDispatcherThread::threadLoop() { mDispatcher->dispatchOnce(); return true; } void InputDispatcher::dispatchOnce() { nsecs_t nextWakeupTime = LONG_LONG_MAX; { // acquire lock AutoMutex _l(mLock); mDispatcherIsAliveCondition.broadcast(); // Run a dispatch loop if there are no pending commands. // The dispatch loop might enqueue commands to run afterwards. if (!haveCommandsLocked()) { dispatchOnceInnerLocked(&nextWakeupTime); } // Run all pending commands if there are any. // If any commands were run then force the next poll to wake up immediately. if (runCommandsLockedInterruptible()) { nextWakeupTime = LONG_LONG_MIN; } } // release lock // Wait for callback or timeout or wake. (make sure we round up, not down) nsecs_t currentTime = now(); int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime); mLooper->pollOnce(timeoutMillis); }(1) dispatchOnceInnerLocked(&nextWakeupTime)对input输入消息进行分发。