7.4 第三步:Looper线程循环阶段

Looper线程完成准备和初始化Handler的工作后,便进入loop方法,该方法位于frameworks/base/core/java/android/os/Looper.java中,代码如下:


public static void loop(){

final Looper me=myLooper();//获取线程局部变量中存储的Looper对象

if(me==null){//调用loop方法前必须首先调用prepare方法

throw new RuntimeException("No Looper;Looper.prepare()

wasn't called on this thread.");

}

final MessageQueue queue=me.mQueue;//获取Looper中存储的MessageQueue

//在IPCThreadState中记录当前线程所属的PID和UID

Binder.clearCallingIdentity();

final long ident=Binder.clearCallingIdentity();

for(;){//在无限循环中轮询MessageQueue

Message msg=queue.next();//可能阻塞

if(msg==null){

//无消息时,消息队列退出

return;

}

Printer logging=me.mLogging;

msg.target.dispatchMessage(msg);//将读取的消息发送到消息处理器

final long newIdent=Binder.clearCallingIdentity();

if(ident!=newIdent){

}

msg.recycle();//将处理过的消息重新初始化并放入消息池中

}

}


Loop方法的主要工作可以分为四部分:

1)调用Binder.clearCallingIdentity方法记录并获取当前线程身份信息。

2)调用MessageQueue.next方法循环监听获取消息。

3)调用Message中target成员变量的dispatchMessag,分发消息到处理器。

4)调用Message的recycle()方法,回收消息并更新消息池。

接下来分析这四部分内容。

7.4.1 记录并获取当前线程身份信息

clearCallingIdentity方法用于记录并获取当前线程身份信息,其定义于frameworks/base/core/java/android/os/Binder.java中,这是一个Native方法,其实现方法定义于frameworks/base/core/jni/android_util_Binder.cpp中,代码如下:


static jlong android_os_Binder_clearCallingIdentity(JNIEnv*env, jobject clazz)

{

return IPCThreadState:self()->clearCallingIdentity();

}


Native层的实现方法,把请求转发给IPCThreadState的clearCallingIdentity方法处理。关于IPCThreadState的内容已经在第5章详细分析过,这里直接分析其clearCallingIdentity方法,代码如下:


int64_t IPCThreadState:clearCallingIdentity()

{

/*将调用线程所属的UID左移32位,然后与调用线程所属的PID做或运算,这样

便将两个32位的整数存入一个64位的整数中,分别占据高32位和低32位/

int64_t token=((int64_t)mCallingUid<<32)|mCallingPid;

clearCaller();//记录mCallingUid和mCallingPid

return token;

}


clearCallingIdentity方法首先将mCallingUid和mCallingPid存入一个64位整数中,该整数作为token返回给调用端,用来标志线程身份信息。然后,调用clearCaller方法在IPCThreadState中记录mCallingUid和mCallingPid。clearCaller方法很简单,其代码如下:


void IPCThreadState:clearCaller()

{

mCallingPid=getpid();

mCallingUid=getuid();

}