You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
android-notes/blogs/Android/Framework/Interview/其他应用组件相关/静态广播的注册和收发原理.md

7.3 KiB

静态广播的注册和收发原理
//...
else if(tagName.equals("receiver")) {
    // class Activity extends Component<ActivityIntentInfo>{}
	Activity a = parseActivity(owner, res, parser, attrs, flags, ...);
	owner.receivers.add(a);
}

广播的发送

@Override
public void sendBroadcast(Intent intent) {
    ActivityManagerNative.getDrfault().broadcastIntent(mMainThread.getApplicationThread(), intent, ...);
}
int broadcastIntent(IApplicationThread caller, Intent intent, ...) {
    int res = broadcastIntentLocked(callerApp, ...);
    return res;
}
int broadcastIntentLocked(ProcessRecord callerApp, ...) {
    // 找静态注册的 receiver
    List receivers = collectReceiverComponents(intent, resolvedType, ...);
    // 找动态注册的 receiver
    List registeredReceivers = mReceiverResolver.queryIntent(intent, ...);
    if(!ordered && registeredReceivers.size()>0) {
        // 处理动态 receiver,加到并行分发队列
    }
    // 给没有处理完的动态 receiver,跟静态 receiver 合并到一起
    if((receivers != null && receivers.size() > 0)){
        // 处理剩下的 receiver,加到串行分发队列
        BroadcastQueue queue = boradcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, ...);
        queue.enqueueOrderedBroadcastLocked(r);
        queue.scheduleBroadcast();
    }
    return ActivityManager.BROADCAST_SUCCESS;
}
final void processNextBroadcast(boolean formMsg){
    // 先给并行分发的广播分发完,然后接下来分发串行广播
    // 如果有 pending 的广播,就先直接返回,这个广播在等待应用进程启动
    // 如果当前广播分发超时了,就废弃这个广播,处理下一个广播
    // 如果没有超时,并且正在分发中,就先返回,什么也不做
    // 如果当前的广播已经分发完一个 receive 了,就继续分发下一个 receive
    // 如果这个 receive 是动态注册的 receive,就直接分发
    // 如果这个 receive 是静态注册的 receive,就先看进程启动没有
    // 如果进程启动了,就直接分发
    // 没启动的话就先启动进程,然后给广播标记为 pending
    // 进程启动后 attachApplication 时继续处理这个 pending 的广播
}
// 超时
do{
    r = mOrderedBroadcasts.get(0);
    if(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers)){
        // 超时善后工作
        boradcastTimeoutLocked(false);
        forceReceive = true;
        r.state = BroadcastRecord.IDLE;
    }
    if(r.state != BroadcastRecord.IDLE){
        return;
    }
    if(r.receivers == null || r.nextReceiver >= numReceivers || forceReceive) {
        cancelBroadcastTimeoutLocked();
        mOrderBroadcasts.remove(0);
        continue;
    }
} while(r == null);

final void boradcastTimeoutLocked(boolean fromMsg) {
    BroadcastRecord r = mOrderedBroadcasts.get(0);
    Object curReceiver = r.receivers.get(r.nextReceiver - 1);
    // 找到当前分发的 receiver 对应的进程
    
    if(mPendingBroadcast == r){
        mPendingBroadcast = null;
    }
    finishReceiverLocked(r, r.resultCode, ...);
    scheduleBroadcastsLocked();
    mHandler.post(new AppNotResponding(app, anrMessage));
}

// 没有超时的情况
int recldx = r.nextReceiver++;
r.receiverTime = SystemClock.uptimeMillis();
if(recldx == 0){
    r.dispatchTime = r.receiverTime;
    r.dispatchClockTime = System.currentTimeMillis();
}
if(!mPendingBroadcastTimeoutMessage) {
    long timeoutTime = r.receiverTime + mTimeoutPeriod;
    setBroadcastTimeoutLocked(timeoutTime);
}
final Object nextReceiver = r.receivers.get(index);
if(nextReceiver instanceof BroadcastFilter) {
    // 如果是动态 receiver,直接分发
    BroadcastFilter filter = (BroadcastFilter)nextReceiver;
    deliverToRegisterReceiverLocked(r, filter, r.ordered);
    return;
}
// 静态 receiver,分发之前先判断进程是否已经启动
r.state = BroadcastRecord.APP_RECEIVE;
ProcessRecord app = mService.getProcessRecordLocked(targetProcess, ...);
if(app != null && app.thread != null){
    // 进程已经启动,直接分发
    processCurBroadcastLocked(r, app);
    return;
}
// 启动进程,并且设置 pending 状态
r.curApp = mService.startProcessLocked(targetProcess, ...);
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recldx;

广播的接收

// 动态 receiver
void deliverToRegisteredReceiverLocked(BroadcastRecord r, ...) {
    performReceiveLocked(filter.receiverList.app, ...);
    if(ordered) {
        r.state = BroadcastRecord.CALL_DONE_RECEIVE;
    }
}
void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, ...) {
    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode, ...);
}
// 调到应用端处理
void scheduleRegisteredReceiver(){
    final BroadcastReceiver receiver = mReceiver;
    final boolean ordered = mOrdered;
    final Intent intent = mCurIntent;
    mCurIntent = null;
    receiver.setPendingResult(this);
    receiver.onReceive(mContext, intent);
    if(receiver.getPendingResult() != null){
        finish();
    }
}
// 通知 AMS 广播已经分发完了
void finish(){
    IActivityManager mgr = ActivityManagerNative.getDefault();
    mgr.finishReceiver(...);
}
void finishReceiver(IBinder who, int resultCode, ...) {
    boolean doNext = false;
    BroadcastRecord r = queue.getMatchingOrderedReceiver(who);
    doNext = r.queue.finishReceiverLocked(r, resultCode, ...);
    if(doNext){
        r.queue.processNextBroadcast(false);
    }
}
public boolean finishReceiverLocked(BroadcastRecord r, ...) {
    final int state = r.state;
    return state == BroadcastRecord.APP_RECEIVE
        || state == BroadcastRecord.CALL_DONE_RECEIVE;
}

静态 receiver 分发:

void processCurBroadcastLocked(BroadcastRecord r, ...) {
    r.receiver = app.thread.asBinder();
    r.curApp = app;
    app.curReceiver = r;
    app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver, ...);
}
void scheduleReceiver(Intent intent, ActivityInfo info, ...) {
    ReceiverData r = new ReceiverData(intent, resultCode, data, ...);
    r.info = info;
    r.compatInfo = compatInfo;
    sendMessage(H.RECEIVER, r);
}
private void handleReceiver(ReceiverData data) {
    LoadedApk pakcageInfo = getPackageInfoNoCheck(...);
    BroadcastReceiver receiver;
    receiver = cl.loadClass(component).newInstance();
    Application app = packageInfo.makeApplication(false, ...);
    ContextImpl context = app.getBaseContext();
    receiver.setPendingResult(data);
    receiver.onReceive(context.getReceiverRestrictedContext(), data.intent);
    if(receiver.getPendingResult() != null) {
        data.finish();
    }
}

应用进程启动之后,向 AMS 报告,然后启动 pengdingBroadcast:

boolean attachApplicationLocked(IApplicationThread thread, ...) {
	sendPendingBroadcastsLocked(app);
}
boolean sendPendingBroadcastsLocked(ProcessRecord app) {
    for(BroadcastQueue queue : mBroadcastQueues){
        queue.sendPendingBroadcastsLocked(app);
    }
}
boolean sendPendingBroadcastsLocked(ProcessRecord app) {
    final BroadcastRecord br = mPendingBroadcast;
    if(br != null && br.curApp.pid == app.pid) {
        mPendingBroadcast = null;
        processCurBroadcastLocked(br, app);
    }
}

说说静态广播的注册和收发原理

  1. 静态广播是怎么注册的
  2. 静态广播是串行分发的
  3. 静态广播的生命周期及上下文