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();
}