Android中input系统的相关代码路径:

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事件能被实时处理,冥冥之中有某个服务会运行某些监听线程,不停的监测它。我是这样想的。


一 loop线程的创建

1 SystemServer

android init进程启动SystemServer,负责android服务的启动和管理。/core/java/com/android/internal/os/ZygoteInit.java中private static boolean startSystemServer()启动SystemServer,最后调用env->GetStaticMethodID(clazz, "init2", "()V")启动线程池,并进入它的run方法。
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的实例。
至此,需要知道的是:创建了一个class WindowManagerService的实例wm,wm的一个成员变量mInputManager是class InputManagerService的实例。
(3) add WINDOW_SERVICE = "window"和INPUT_SERVICE = "input"服务。
(4) 添加WindowManagerService到服务列表。
(5) 设置了mWindowManagerCallbacks = wm.getInputMonitor()。
(6) start (启动)inputManager。
(7) 设置与window manager和input manager相关联的display manager。
至此,需要知道的是:android ini进程启动了一个服务总管SystemServer,它添加了一个WindowManagerService服务,这个服务中有一个mInputManager成员,是class InputManagerService的一个实例,这是与input系统相关的一个结构了。

2 InputManagerService和NativeInputManager

我们只关心input相关的信息,看一下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成员变量。
至此,需要知道的是:android ini进程启动了一个服务总管SystemServer,它添加了一个WindowManagerService服务,这个服务中有一个mInputManager成员;是class InputManagerService的一个实例,也就是java层的input设备管理器,它和native层的input设备管理器怎么联系的呢?InputManagerService中有一个mPtr成员,保存了native空间input设备管理器mInputManager宿主NativeInputManager的指针。

3 InputManager中线程的创建

native空间的input设备管理器是InputManager的实例,它是input系统的管理者。接着上一节;看一下它的构造函数。
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系统中的管家和家丁们的职责和特权。正如三国杀,只有了解手中武将牌的能力和特权,才能掌握胜算。接下来的一段是摘抄的。

Eventhub

它是系统中所有事件的中央处理站。它管理所有系统中可以识别的输入设备的输入事件,此外,当设备增加或删除时,EventHub将产生相应的输入事件给系统。EventHub通过getEvents函数,给系统提供一个输入事件流。它也支持查询输入设备当前的状态(如哪些键当前被按下)。而且EventHub还跟踪每个输入调入的能力,比如输入设备的类别,输入设备支持哪些按键。

InputReader

InputReader从EventHub中读取原始事件数据(RawEvent),并由各个InputMapper处理之后输入对应的inputlistener。
InputReader拥有一个InputMapper集合。它做的大部分工作在InputReader线程中完成,但是InputReader可以接受任意线程的查询。
为了可管理性,InputReader使用一个简单的Mutex来保护它的状态。
InputReader拥有一个EventHub对象,但这个对象不是它创建的,而是在创建InputReader时作为参数传入的。

InputDispatcher

InputDispatcher负责把事件分发给输入目标,其中的一些功能(如识别输入目标)由独立的policy对象控制。

InputManager

InputManager是系统事件处理的核心,它虽然不做具体的事,但管理工作还是要做的,比如接受我们客户的投诉和索赔要求,或者老板的出气筒。
InputManager使用两个线程:
1)InputReaderThread叫做"InputReader"线程,它负责读取并预处理RawEvent,applies
policy并且把消息送入DispatcherThead管理的队列中。
2)InputDispatcherThread叫做"InputDispatcher"线程,它在队列上等待新的输入事件,并且
异步地把这些事件分发给应用程序。
InputReaderThread类与InputDispatcherThread类不共享内部状态,所有的通信都是单向的,
从InputReaderThread到InputDispatcherThread。
两个类可以通过InputDispatchPolicy进行交互。
InputManager类从不与Java交互,而InputDispatchPolicy负责执行所有与系统的外部交互,包括调用DVM业务。

二 loop线程的启动

1 SystemServer

基本每个启动都是由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。

2 InputManager中线程的运行

mInputManager是一个class InputManager的实例,继续到它的start()都做了什么?
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中有很多形式的类型转换,有待研究。
毫无悬念的调用了result = self->threadLoop(),在Thread中 virtual bool threadLoop() = 0;是一个纯虚函数,需要子类重写;那回到孩子身上吧。
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事件。
(2) processEventsLocked(mEventBuffer, count);处理input事件。
现在回过头看看user是mDispatcherThread的情况,都说了和InputReaderThread差不多。
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输入消息进行分发。
(2) mLooper->pollOnce(timeoutMillis)等待下一次输入事件,会调用Looper::pollOnce(),据说Looper里主要通过linux管道方式实现进程间通信,通过epoll机制实现外界事件请求作出响应。

更多相关文章

  1. (四)Android事件分发机制 - 总结篇
  2. 关于安卓 TextView 添加点击事件
  3. Android 实例子源代码文件下载地址380个合集
  4. Android事件处理之监听事件
  5. Android JNI简单实例(android 调用C/C++代码)
  6. android一些不常用的事件
  7. android添加触摸事件
  8. Android与js交互实例

随机推荐

  1. Android中ActionBar居中
  2. Android软键盘调用
  3. Android(安卓)Adapter详解
  4. a64_7.1-v3.1android拉伸绘制矩形区域距
  5. Android(安卓)WebView的使用方法总结
  6. Android(安卓)中Observer模式的使用
  7. Android(安卓)之主题
  8. android开发秘籍笔记
  9. Android(安卓)Audio Effect 机制初探
  10. Android――Dialog