input系统一 loop线程的创建与运行

转自http://blog.csdn.net/coldsnow33/article/details/15809965

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方法。

  1. public class SystemServer {  
  2. ......  
  3.    public static final void init2() {  
  4.         Slog.i(TAG, "Entered the Android system server!");  
  5.         Thread thr = new ServerThread();  
  6.         thr.setName("android.server.ServerThread");  
  7.         thr.start();  
  8.     }  
  9. }  
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方法:

  1. public class SystemServer {  
  2.     @Override  
  3.   public void run() {  
  4.   ......  
  5.          Slog.i(TAG, "Input Manager");  
  6.             inputManager = new InputManagerService(context, wmHandler);  
  7.   
  8.             Slog.i(TAG, "Window Manager");  
  9.             wm = WindowManagerService.main(context, power, display, inputManager,  
  10.                     uiHandler, wmHandler,  
  11.                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,  
  12.                     !firstBoot, onlyCore);  
  13.             ServiceManager.addService(Context.WINDOW_SERVICE, wm);  
  14.             ServiceManager.addService(Context.INPUT_SERVICE, inputManager);  
  15.   
  16.             ActivityManagerService.self().setWindowManager(wm);  
  17.   
  18.             inputManager.setWindowManagerCallbacks(wm.getInputMonitor());  
  19.             inputManager.start();  
  20.   
  21.             display.setWindowManager(wm);  
  22.             display.setInputManager(inputManager);  
  23. }  
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()方法。

  1. public static WindowManagerService main(final Context context,  
  2.             final PowerManagerService pm, final DisplayManagerService dm,  
  3.             final InputManagerService im,  
  4.             final Handler uiHandler, final Handler wmHandler,  
  5.             final boolean haveInputMethods, final boolean showBootMsgs,  
  6.             final boolean onlyCore) {  
  7.         final WindowManagerService[] holder = new WindowManagerService[1];  
  8.         wmHandler.runWithScissors(new Runnable() {  
  9.             @Override  
  10.             public void run() {  
  11.                 holder[0] = new WindowManagerService(context, pm, dm, im,  
  12.                         uiHandler, haveInputMethods, showBootMsgs, onlyCore);  
  13.             }  
  14.         }, 0);  
  15.         return holder[0];  
  16.     }  
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,其构造函数也是长又长,不是代码长,是结构名字长;相关的一句是:

  1. mInputManager = inputManager;  
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的构造方法。

  1. public InputManagerService(Context context, Handler handler) {  
  2.        this.mContext = context;  
  3.        this.mHandler = new InputManagerHandler(handler.getLooper());  
  4.   
  5.        mUseDevInputEventForAudioJack =  
  6.                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);  
  7.        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="  
  8.                + mUseDevInputEventForAudioJack);  
  9.        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());  
  10.    }  
 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空间函数的对应关系。

  1. static JNINativeMethod gInputManagerMethods[] = {  
  2.     /* name, signature, funcPtr */  
  3.     { "nativeInit",  
  4.             "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)I",  
  5.             (void*) nativeInit },  
  6. ......  
  7. };  
static JNINativeMethod gInputManagerMethods[] = {
    /* name, signature, funcPtr */
    { "nativeInit",
            "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)I",
            (void*) nativeInit },
......
};

继续nativeInit()。

  1. static jint nativeInit(JNIEnv* env, jclass clazz,  
  2.         jobject serviceObj, jobject contextObj, jobject messageQueueObj) {  
  3.     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);  
  4.     if (messageQueue == NULL) {  
  5.         jniThrowRuntimeException(env, "MessageQueue is not initialized.");  
  6.         return 0;  
  7.     }  
  8.   
  9.     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,  
  10.             messageQueue->getLooper());  
  11.     im->incStrong(0);  
  12.     return reinterpret_cast<jint>(im);  
  13. }  
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,其构造函数为:

  1. NativeInputManager::NativeInputManager(jobject contextObj,  
  2.         jobject serviceObj, const sp<Looper>& looper) :  
  3.         mLooper(looper) {  
  4.     JNIEnv* env = jniEnv();  
  5.   
  6.     mContextObj = env->NewGlobalRef(contextObj);  
  7.     mServiceObj = env->NewGlobalRef(serviceObj);  
  8.   
  9.     {  
  10.         AutoMutex _l(mLock);  
  11.   
  12.         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;  
  13.         mLocked.pointerSpeed = 0;  
  14.         mLocked.pointerGesturesEnabled = true;  
  15.         mLocked.showTouches = false;  
  16.     }  
  17.   
  18.     sp<EventHub> eventHub = new EventHub();  
  19.     mInputManager = new InputManager(eventHub, thisthis);  
  20. }  
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系统的管理者。接着上一节;看一下它的构造函数。

  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  
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号还有点权力。

  1. void InputManager::initialize() {  
  2.     mReaderThread = new InputReaderThread(mReader);  
  3.     mDispatcherThread = new InputDispatcherThread(mDispatcher);      
  4. }  
void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);    
}

这就是了,传说中的创建线程对象。这里分别创建了class InputReaderThread(负责input事件的获取)和class InputDispatcherThread(负责input消息的发送)的实例,用于初始化InputManager的mReaderThread和mDispatcherThread成员。class InputDispatcherThread和class InputReaderThread 类似。

  1. class InputReaderThread : public Thread {  
  2. public:  
  3.     InputReaderThread(const sp<InputReaderInterface>& reader);  
  4.     virtual ~InputReaderThread();  
  5.   
  6. private:  
  7.     sp<InputReaderInterface> mReader;  
  8.   
  9.     virtual bool threadLoop();  
  10. };  
class InputReaderThread : public Thread {
public:
    InputReaderThread(const sp<InputReaderInterface>& reader);
    virtual ~InputReaderThread();

private:
    sp<InputReaderInterface> mReader;

    virtual bool threadLoop();
};

看到threadLoop()方法就仿佛看到了希望,为什么这样说?因为我抢先看了threadLoop()实现。

  1. bool InputReaderThread::threadLoop() {  
  2.     mReader->loopOnce();  
  3.     return true;  
  4. }  
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

接着有跟到了void InputReader::loopOnce();果然这个函数就是需要loop的函数。我坚信在代码的某个旮旯深处;会调用这个threadLoop(),至于是哪个旮旯,就先放一放;当务之急是搞明白input系统中的管家和家丁们的职责和特权。正如三国杀,只有了解手中武将牌的能力和特权,才能掌握胜算。接下来的一段是摘抄的。

Eventhub

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

InputReader

InputReader从EventHub中读取原始事件数据(RawEvent),并由各个InputMapper处理之后输入对应的input listener。
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(),这是一段旅程的开始,从此踏上寻找不老泉的征途。

  1. public void start() {  
  2.        Slog.i(TAG, "Starting input manager");  
  3.        nativeStart(mPtr);  
  4.   
  5.        // Add ourself to the Watchdog monitors.  
  6.        Watchdog.getInstance().addMonitor(this);  
  7.   
  8.        registerPointerSpeedSettingObserver();  
  9.        registerShowTouchesSettingObserver();  
  10.   
  11.        mContext.registerReceiver(new BroadcastReceiver() {  
  12.            @Override  
  13.            public void onReceive(Context context, Intent intent) {  
  14.                updatePointerSpeedFromSettings();  
  15.                updateShowTouchesFromSettings();  
  16.            }  
  17.        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);  
  18.   
  19.        updatePointerSpeedFromSettings();  
  20.        updateShowTouchesFromSettings();  
  21.  }  
 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空间的地址。

  1. static JNINativeMethod gInputManagerMethods[] = {  
  2.     { "nativeStart""(I)V",  
  3.             (void*) nativeStart },  
  4. };  
  5. static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {  
  6.     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  
  7.   
  8.     status_t result = im->getInputManager()->start();  
  9.     if (result) {  
  10.         jniThrowRuntimeException(env, "Input manager could not be started.");  
  11.     }  
  12. }  
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()都做了什么?

  1. status_t InputManager::start() {  
  2.     status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  
  3.     if (result) {  
  4.         ALOGE("Could not start InputDispatcher thread due to error %d.", result);  
  5.         return result;  
  6.     }  
  7.   
  8.     result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);  
  9.     if (result) {  
  10.         ALOGE("Could not start InputReader thread due to error %d.", result);  
  11.   
  12.         mDispatcherThread->requestExit();  
  13.         return result;  
  14.     }  
  15.      
  16.     return OK;  
  17. }  
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(),就可以接着启动了。

  1. status_t Thread::run(const char* name, int32_t priority, size_t stack)  
  2. {  
  3.     Mutex::Autolock _l(mLock);  
  4.   
  5.     if (mRunning) {  
  6.         // thread already started  
  7.         return INVALID_OPERATION;  
  8.     }  
  9.   
  10.     // reset status and exitPending to their default value, so we can  
  11.     // try again after an error happened (either below, or in readyToRun())  
  12.     mStatus = NO_ERROR;  
  13.     mExitPending = false;  
  14.     mThread = thread_id_t(-1);  
  15.       
  16.     // hold a strong reference on ourself  
  17.     mHoldSelf = this;  
  18.   
  19.     mRunning = true;  
  20.   
  21.     bool res;  
  22.     if (mCanCallJava) {  
  23.         res = createThreadEtc(_threadLoop,  
  24.                 this, name, priority, stack, &mThread);  
  25.     } else {  
  26.         res = androidCreateRawThreadEtc(_threadLoop,  
  27.                 this, name, priority, stack, &mThread);  
  28.     }  
  29.       
  30.     if (res == false) {  
  31.         mStatus = UNKNOWN_ERROR;   // something happened!  
  32.         mRunning = false;  
  33.         mThread = thread_id_t(-1);  
  34.         mHoldSelf.clear();  // "this" may have gone away after this.  
  35.   
  36.         return UNKNOWN_ERROR;  
  37.     }  
  38.       
  39.     // Do not refer to mStatus here: The thread is already running (may, in fact  
  40.     // already have exited with a valid mStatus result). The NO_ERROR indication  
  41.     // here merely indicates successfully starting the thread and does not  
  42.     // imply successful termination/execution.  
  43.     return NO_ERROR;  
  44.   
  45.     // Exiting scope of mLock is a memory barrier and allows new thread to run  
  46. }  
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()就是谁了,不是都不行。

  1. int Thread::_threadLoop(void* user)  
  2. {  
  3.     Thread* const self = static_cast<Thread*>(user);  
  4.   
  5.     sp<Thread> strong(self->mHoldSelf);  
  6.     wp<Thread> weak(strong);  
  7.     self->mHoldSelf.clear();  
  8.   
  9. #ifdef HAVE_ANDROID_OS  
  10.     // this is very useful for debugging with gdb  
  11.     self->mTid = gettid();  
  12. #endif  
  13.   
  14.     bool first = true;  
  15.   
  16.     do {  
  17.         bool result;  
  18.         if (first) {  
  19.             first = false;  
  20.             self->mStatus = self->readyToRun();  
  21.             result = (self->mStatus == NO_ERROR);  
  22.   
  23.             if (result && !self->exitPending()) {  
  24.                 // Binder threads (and maybe others) rely on threadLoop  
  25.                 // running at least once after a successful ::readyToRun()  
  26.                 // (unless, of course, the thread has already been asked to exit  
  27.                 // at that point).  
  28.                 // This is because threads are essentially used like this:  
  29.                 //   (new ThreadSubclass())->run();  
  30.                 // The caller therefore does not retain a strong reference to  
  31.                 // the thread and the thread would simply disappear after the  
  32.                 // successful ::readyToRun() call instead of entering the  
  33.                 // threadLoop at least once.  
  34.                 result = self->threadLoop();  
  35.             }  
  36.         } else {  
  37.             result = self->threadLoop();  
  38.         }  
  39.   
  40.         // establish a scope for mLock  
  41.         {  
  42.         Mutex::Autolock _l(self->mLock);  
  43.         if (result == false || self->mExitPending) {  
  44.             self->mExitPending = true;  
  45.             self->mRunning = false;  
  46.             // clear thread ID so that requestExitAndWait() does not exit if  
  47.             // called by a new thread using the same thread ID as this one.  
  48.             self->mThread = thread_id_t(-1);  
  49.             // note that interested observers blocked in requestExitAndWait are  
  50.             // awoken by broadcast, but blocked on mLock until break exits scope  
  51.             self->mThreadExitedCondition.broadcast();  
  52.             break;  
  53.         }  
  54.         }  
  55.           
  56.         // Release our strong reference, to let a chance to the thread  
  57.         // to die a peaceful death.  
  58.         strong.clear();  
  59.         // And immediately, re-acquire a strong reference for the next loop  
  60.         strong = weak.promote();  
  61.     } while(strong != 0);  
  62.       
  63.     return 0;  
  64. }  
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;是一个纯虚函数,需要子类重写;那回到孩子身上吧。

  1. bool InputReaderThread::threadLoop() {  
  2.     mReader->loopOnce();  
  3.     return true;  
  4. }  
bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

这个不是之前抢先看的东东吗?现在是DVD版的了,要清楚很多了。

  1. void InputReader::loopOnce() {  
  2.     int32_t oldGeneration;  
  3.     int32_t timeoutMillis;  
  4.     bool inputDevicesChanged = false;  
  5.     Vector<InputDeviceInfo> inputDevices;  
  6.     { // acquire lock  
  7.         AutoMutex _l(mLock);  
  8.   
  9.         oldGeneration = mGeneration;  
  10.         timeoutMillis = -1;  
  11.   
  12.         uint32_t changes = mConfigurationChangesToRefresh;  
  13.         if (changes) {  
  14.             mConfigurationChangesToRefresh = 0;  
  15.             timeoutMillis = 0;  
  16.             refreshConfigurationLocked(changes);  
  17.         } else if (mNextTimeout != LLONG_MAX) {  
  18.             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  19.             timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);  
  20.         }  
  21.     } // release lock  
  22.   
  23.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
  24.   
  25.     { // acquire lock  
  26.         AutoMutex _l(mLock);  
  27.         mReaderIsAliveCondition.broadcast();  
  28.   
  29.         if (count) {  
  30.             processEventsLocked(mEventBuffer, count);  
  31.         }  
  32.   
  33.         if (mNextTimeout != LLONG_MAX) {  
  34.             nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);  
  35.             if (now >= mNextTimeout) {  
  36. #if DEBUG_RAW_EVENTS  
  37.                 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);  
  38. #endif  
  39.                 mNextTimeout = LLONG_MAX;  
  40.                 timeoutExpiredLocked(now);  
  41.             }  
  42.         }  
  43.   
  44.         if (oldGeneration != mGeneration) {  
  45.             inputDevicesChanged = true;  
  46.             getInputDevicesLocked(inputDevices);  
  47.         }  
  48.     } // release lock  
  49.   
  50.     // Send out a message that the describes the changed input devices.  
  51.     if (inputDevicesChanged) {  
  52.         mPolicy->notifyInputDevicesChanged(inputDevices);  
  53.     }  
  54.   
  55.     // Flush queued events out to the listener.  
  56.     // This must happen outside of the lock because the listener could potentially call  
  57.     // back into the InputReader's methods, such as getScanCodeState, or become blocked  
  58.     // on another thread similarly waiting to acquire the InputReader lock thereby  
  59.     // resulting in a deadlock.  This situation is actually quite plausible because the  
  60.     // listener is actually the input dispatcher, which calls into the window manager,  
  61.     // which occasionally calls into the input reader.  
  62.     mQueuedListener->flush();  
  63. }  
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差不多。

  1. bool InputReaderThread::threadLoop() {  
  2.     mReader->loopOnce();  
  3.     return true;  
  4. }  
  5. bool InputDispatcherThread::threadLoop() {  
  6.     mDispatcher->dispatchOnce();  
  7.     return true;  
  8. }  
  9. void InputDispatcher::dispatchOnce() {  
  10.     nsecs_t nextWakeupTime = LONG_LONG_MAX;  
  11.     { // acquire lock  
  12.         AutoMutex _l(mLock);  
  13.         mDispatcherIsAliveCondition.broadcast();  
  14.   
  15.         // Run a dispatch loop if there are no pending commands.  
  16.         // The dispatch loop might enqueue commands to run afterwards.  
  17.         if (!haveCommandsLocked()) {  
  18.             dispatchOnceInnerLocked(&nextWakeupTime);  
  19.         }  
  20.   
  21.         // Run all pending commands if there are any.  
  22.         // If any commands were run then force the next poll to wake up immediately.  
  23.         if (runCommandsLockedInterruptible()) {  
  24.             nextWakeupTime = LONG_LONG_MIN;  
  25.         }  
  26.     } // release lock  
  27.   
  28.     // Wait for callback or timeout or wake.  (make sure we round up, not down)  
  29.     nsecs_t currentTime = now();  
  30.     int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);  
  31.     mLooper->pollOnce(timeoutMillis);  
  32. }  
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机制实现外界事件请求作出响应。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值