在【Android】app中阻塞的looper为什么可以响应touch事件_消息队列阻塞为什么还能响应点击事件-CSDN博客
里面,我们查看到input事件唤醒应用中的looper阻塞,
作为对比,我们再看看广播中的唤醒,我们知道,在注册的广播接收器收到消息时,即广播的receiver调用的时候,是执行在主线程的,这显然是handler调用唤起的,比如亮屏这样的系统广播,我们猜测是AMS通过广播的相关处理,通过唤醒应用中的binder线程,调用相关方法,里面再调用主线程关联的handler来唤醒主线程looper阻塞,
过程比较复杂,这里说说大概流程,AMS通过IApplicationThread这个app的代理对象来进行调用,执行到app进程中,(这个时候是在ApplicationThread这个binder线程里)
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
最终调用到广播binder对象的
ReceiverDispatcher.performReceive方法里,里面post到主进程。
参考:Android 广播内部机制详解(三)_android broadcastqueue is skipped in restrictedpac-CSDN博客
4.3.4 ReceiverDispatcher.performReceive
文件:LoadedApk.java
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
// 见4.3.5
final Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
if (intent == null) {
Log.wtf(TAG, "Null intent received");
} else {
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+ " seq=" + seq + " to " + mReceiver);
}
}
// 将广播信息放到args中,post到主线程中执行,见4.3.5
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
// 告诉AMS,广播处理完毕,动态的有序广播会走这里见4.3.6
args.sendFinished(mgr);
}
}
}
mActivityThread继承于handler类,
public final class ActivityThread extends ClientTransactionHandler
ActivityThread是app的主线程,
可以看出,looper的阻塞唤醒可以由其他线程的handler消息(本质还是消息队列里的某个fd)和监听的fd上有消息(如input)