转自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方法。
- 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();
- }
- }
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);
- }
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];
- }
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());
- }
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 },
- ......
- };
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);
- }
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);
- }
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::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);
- }
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();
- };
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处理之后输入对应的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(),这是一段旅程的开始,从此踏上寻找不老泉的征途。
- 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();
- }
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.");
- }
- }
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;
- }
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
- }
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;
- }
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();
- }
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);
- }
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机制实现外界事件请求作出响应。