ActivityManagerService分发广播

前文Android发送广播中,客户端通过Binder调用AMS发送广播后,会将广播和广播接收者构造成BroadcastRecord,然后根据广播和广播接收者的类型来决定加入队列:
1. 前台广播,放入前台广播队列
2. 后台广播,放入后台广播队列
3. 静态注册的广播接收器和有序广播对应的动态注册的广播接收器放入到前台或后台的串行数组(mOrderedBroadcasts)中
4. 普通广播对应的动态注册的广播接收器放入前台或后台的并行数组(mParallelBroadcasts)中
加入队列后,会调用BroadcastQueue的scheduleBroadcastsLocked函数启动分发。
本文将分析AMS如何理由BroadcastQueue来进行分发广播,即消息处理中心主要的逻辑。

初始化

BroadcastQueue在ActivityManagerService构造函数中初始化

ActivityManagerService的构造函数

mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", BROADCAST_FG_TIMEOUT, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", BROADCAST_BG_TIMEOUT, true);
mBroadcastQueues[0] = mFgBroadcastQueue; 
mBroadcastQueues[1] = mBgBroadcastQueue;

可以看出,这里构造了两条队列,一条是前台广播队列,一条是后台广播队列。两者这里的主要区别是名字不同以及超时时间不同,前台队列的超时时间是BROADCAST_FG_TIMEOUT 其为10s,后台队列的超时时间是BROADCAST_BG_TIMEOUT是60s。然后将两个队列放入到数组mBroadcastQueues中。

消息处理

AMS中广播到来时,会调用scheduleBroadcastsLocked来启动分发广播

public void scheduleBroadcastsLocked() {
    if (mBroadcastsScheduled) {
        return;
    }
    mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
    mBroadcastsScheduled = true;
}

mBroadcastsScheduled表示当前是否即将开始分发,如果为真,则直接返回,如果为否,则发送消息BROADCAST_INTENT_MSG到mHandler中,并置mBroadcastsScheduled为真,该值会在processNextBroadcast中置为false。

这里的mHandler是指BroadcastHandler

private final class BroadcastHandler extends Handler {
    public BroadcastHandler(Looper looper) {
        super(looper, null, true);
    }
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case BROADCAST_INTENT_MSG: {
                processNextBroadcast(true);
            } break;
        }
    }
};

收到BROADCAST_INTENT_MSG消息后,会调用processNextBroadcast函数,这里的true表示是从BroadcastHandler中调用的。这里的Looper是AMS构造的ServiceThread的Looper,且前台和后台队列共用一个Looper。

BroadcastQueue.processNextBroadcast
函数主要分以下几步:
1. 如果是从mHandler中调用的,则置mBroadcastsScheduled为false
2. 分发并行广播
3. 有序广播动态注册接收器分发
4. 静态注册接收器分发(对应进程已启动)
5. 静态注册接收器分发(对应进程未启动)

Step 1 清除mBroadcastsScheduled标志

BroadcastQueue.processNextBroadcast
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

if (fromMsg) {
    mBroadcastsScheduled = false;
}

fromMsg表示是从mHandler中调用的,清除该标志,后续AMS可以调用scheduleBroadcastsLocked启动下一次分发。

Step 2 分发并行广播

BroadcastQueue.processNextBroadcast
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
    r = mParallelBroadcasts.remove(0);
    r.dispatchTime = SystemClock.uptimeMillis();
    r.dispatchClockTime = System.currentTimeMillis();
    final int N = r.receivers.size();
    for (int i=0; i<N; i++) {
         Object target = r.receivers.get(i);
         deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
    }
    addBroadcastToHistoryLocked(r);
}

这里是依次取出并行队列mParallelBroadcasts中的BroadcastRecord,设置其dispatchTime和dispatchClockTime。前者是从系统开机到现在的毫秒数(手机睡眠的时间不包括在内); 后者是从1970年1月1日 UTC到现在的毫秒数;dispatchClockTime是通过System.currentTimeMillis()函数获取的时间,该时间可以通过System.setCurrentTimeMillis()函数修改的,在某些情况下,一旦时间更改,时间间隔就不准了。
然后循环取出BroadcastRecord.receivers中的IIntentReceiver,即需要接收该广播的接收器,然后调用
deliverToRegisteredReceiverLocked进行分发。
最后调用addBroadcastToHistoryLocked函数将BroadcastRecord加入到历史队列中。

BroadcastQueue.deliverToRegisteredReceiverLocked
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
            BroadcastFilter filter, boolean ordered) {
        //这里省略了权限检查部分
    performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
           new Intent(r.intent), r.resultCode, r.resultData,
           r.resultExtras, r.ordered, r.initialSticky, r.userId);
}

该函数首先是进行权限检查,检查通过了会调用performReceiveLocked函数进行分发

BroadcastQueue.performReceiveLocked
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

private static void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
    if (app != null) {
        if (app.thread != null) {
            //one-way call,非阻塞回调
            app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                    data, extras, ordered, sticky, sendingUser, app.repProcState);
        } else {
            // Application has died. Receiver doesn't exist.
            throw new RemoteException("app.thread must not be null");
        }
    } else {
        receiver.performReceive(intent, resultCode, data, extras, ordered,
                sticky, sendingUser);
    }
}

这里的app和app.thread不为空,则调用app.thread.scheduleRegisteredReceiver函数,该函数是one-way即不会等待客户端执行完成即立刻返回。这样设计也是合理的,因为分发过程是需要synchronized AMS的,如果客户端执行很慢,BroadcastQueue一直在等待,不释放AMS锁,则AMS将无法分发其他的广播,会导致系统很不稳定。 app.thread对应于ActivityThread.ApplicationThread类,其实例在ContextImpl调用registerReceiver时作为参数传给AMS。

ActivityThread.ApplicationThread.scheduleRegisteredReceiver
函数定义在frameworks/base/core/java/android/app/ActivityThread.java

public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
    updateProcessState(processState, false);
    receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
}

该函数主要是调用IIntentReceiver的performReceive函数
其对应于LoadedApk.ReceiverDispatcher中的InnerReceiver类

LoadedApk.ReceiverDispatcher.InnerReceiver performReceive
函数定义在frameworks/base/core/java/android/app/LoadedApk.java

public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    LoadedApk.ReceiverDispatcher rd = mDispatcher.get();  
    if (rd != null) {
         rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
     } else {
         IActivityManager mgr = ActivityManagerNative.getDefault();
         try {
             if (extras != null) {
                 extras.setAllowFds(false);
             }    
             mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
         } catch (RemoteException e) { 
         }    
    }    
}

这里mDispatcher是一个WeakReference,如果app调用了unregisterReceiver,则该引用get时会为空,我们这边未调用unregister,所以此处rd不为空,rd是LoadedApk.ReceiverDispatcher类型

LoadedApk.ReceiverDispatcher.performReceive
函数定义在frameworks/base/core/java/android/app/LoadedApk.java

public void performReceive(Intent intent, int resultCode, String data,
    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
    Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
    if (!mActivityThread.post(args)) {
        if (mRegistered && ordered) {
            IActivityManager mgr = ActivityManagerNative.getDefault();
            args.sendFinished(mgr);
        }
    }
}

函数new了一个Args(LoadedApk.ReceiverDispatcher.Args),然后调用mActivityThread的post函数,将该Args加入到队列中,Args实现了Runnable,mActivityThread是LoadedApk.ReceiverDispatcher的成员变量Handler,在registerReceiver时会注册该Handler,如果没有则会选择主Handler,该handler决定了BroadcastReceiver的onReceive方法运行在哪个线程。

LoadedApk.ReceiverDispatcher.Args.run
函数定义在frameworks/base/core/java/android/app/LoadedApk.java

public void run() {
    final BroadcastReceiver receiver = mReceiver;
    final boolean ordered = mOrdered;     

    final IActivityManager mgr = ActivityManagerNative.getDefault();
    final Intent intent = mCurIntent;
    mCurIntent = null;

    if (receiver == null || mForgotten) {
        if (mRegistered && ordered) {
            sendFinished(mgr);
        }
        return;
    }

    try {
        ClassLoader cl =  mReceiver.getClass().getClassLoader();
        intent.setExtrasClassLoader(cl);
        setExtrasClassLoader(cl);
        receiver.setPendingResult(this);
        receiver.onReceive(mContext, intent);
    } catch (Exception e) {
    //错误处理  
    }

    if (receiver.getPendingResult() != null) {
        finish();
    }
}

函数调用了receiver.setPendingResult(this);然后调用receiver.onReceive(mContext, intent);函数,这里就是我们熟悉的重写的BroadcastReceiver的onReceive函数。最后会判断receiver.getPendingResult() != null,如果为真,调用finish函数,由于Args继承于BroadcastReceiver.PendingResult类,所以会调用其finish函数。

BroadcastReceiver.PendingResult.finish
该函数定义在frameworks/base/core/java/android/content/BroadcastReceiver.java

public final void finish() {
    if (mType == TYPE_COMPONENT) {
        ...            
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing broadcast to " + mToken);
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        sendFinished(mgr);
    }   
}

函数判断该类型是否是TYPE_COMPONENT,在ReceiverDispatcher中的PendingResult是TYPE_REGISTERED,但是mOrderedHint为false,因为非串行分发。所以这里不做任何处理。
至此并行队列中的广播从AMS分发,到各个APP端的流程已经结束。

Step 3 有序广播动态注册接收器分发

BroadcastQueue.processNextBroadcast
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

if (nextReceiver instanceof BroadcastFilter) {
    // Simple case: this is a registered receiver who gets
    // a direct call.
    BroadcastFilter filter = (BroadcastFilter)nextReceiver;
    deliverToRegisteredReceiverLocked(r, filter, r.ordered);
    if (r.receiver == null || !r.ordered) {
        r.state = BroadcastRecord.IDLE;
        scheduleBroadcastsLocked();
    } else {
      if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) { 
            scheduleTempWhitelistLocked(filter.owningUid,
                     brOptions.getTemporaryAppWhitelistDuration(), r);
      }
    }
    return;
}

nextReceiver instanceof BroadcastFilter 这里的nextReceiver是BroadcastRecord的接收器,在串行队列的广播里,如果是有序广播对应的动态注册的接收器,则nextReceiver是BroadcastFilter类型,否则是静态注册的接收器,是ResolveInfo类型。
因此上面是在分发动态注册的接收器,由于是动态注册的,BroadcastReceiver对应的进程肯定已经运行起来了,因此直接调用deliverToRegisteredReceiverLocked函数。跟Step 2中分发的函数流程大体相同。但是deliverToRegisteredReceiverLocked函数中会根据是否是有序广播来修改r.state,
r.state = BroadcastRecord.CALL_DONE_RECEIVE; 在Step2中说过,deliverToRegisteredReceiverLocked函数最后调用到app.thread.scheduleRegisteredReceiver,该函数是one-way的即不等待客户端的执行完成就返回,那有序广播又是如何等待客户端BroadcastReceiver执行完成才分发下一个的呢?

BroadcastQueue在分发时,会判断串行队列中的第一个BroadcastRecord的state是否为idle,如果是,则分发下一个,如果不是,则直接返回。有序广播在调用deliverToRegisteredReceiverLocked函数中会设置BroadcastRecord的state为CALL_DONE_RECEIVE。这样在processNextQueue中就会直接返回。当客户端的BroadcastReceiver执行完成后会发送消息给AMS,然后重置该状态,以便BroadcastQueue可以分发给下一个。
BroadcastQueue.processNextBroadcast函数

if (r.state != BroadcastRecord.IDLE) {
     return;
}

deliverToRegisteredReceiverLocked函数分发到各个APP端的流程同上面的Step 2,并行广播的分发。但是有不同的是在最后调用BroadcastReceiver.PendingResult的finish函数时,mOrderedHint为真。

BroadcastReceiver.PendingResult.finish
该函数定义在frameworks/base/core/java/android/content/BroadcastReceiver.java

public final void finish() {
    if (mType == TYPE_COMPONENT) {
        ...            
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
        if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                        "Finishing broadcast to " + mToken);
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        sendFinished(mgr);
    }   
}

因为mOrderedHint为真,所以会调用sendFinish(mgr)函数

BroadcastReceiver.PendingResult.sendFinished
该函数定义在frameworks/base/core/java/android/content/BroadcastReceiver.java

public void sendFinished(IActivityManager am) {
    synchronized (this) {
        if (mFinished) {
            throw new IllegalStateException("Broadcast already finished");
        }
        mFinished = true;

        try {
            if (mResultExtras != null) {
                        mResultExtras.setAllowFds(false);
            }
            if (mOrderedHint) {
                am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                                mAbortBroadcast, mFlags);
            } else {
        ...
            }
        } catch (RemoteException ex) {
        }
    }
}

mOrderedHint为真,所以会调用AMS的finishReceiver函数,通知AMS,客户端已经处理完成,可以进行下一次的分发了。
ActivityManagerServce.finishReceiver
该函数定义在frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中

public void finishReceiver(IBinder who, int resultCode, String resultData,
            Bundle resultExtras, boolean resultAbort, int flags) {
    final long origId = Binder.clearCallingIdentity();
    try { 
        boolean doNext = false;
        BroadcastRecord r;

        synchronized(this) {
            BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
            r = queue.getMatchingOrderedReceiver(who);
            if (r != null) {
                doNext = r.queue.finishReceiverLocked(r, resultCode,
                     resultData, resultExtras, resultAbort, true);
            }     
        }     
        if (doNext) {
            r.queue.processNextBroadcast(false);
        }     
        trimApplications();
    } finally {
        Binder.restoreCallingIdentity(origId);
    }     
}

函数调用queue.getMatchingOrderedReceiver(who);来获取BroadcastRecord,该函数比较mOrderedBroadcasts数组中的第一个BroadcastRecord是否跟who相同,如果相同返回该对象,否则返回null。如果找到匹配的,则调用BroadcastQueue的finishReceiverLocked函数

BroadcastQueue.finishReceiverLocked
该函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java中

public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
     String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
    //...
    r.state = BroadcastRecord.IDLE;
    //...省略了情况BroadcastRecord中状态的代码
    if (waitForServices && r.curComponent != null && r.queue.mDelayBehindServices
                && r.queue.mOrderedBroadcasts.size() > 0
                && r.queue.mOrderedBroadcasts.get(0) == r) {
        ActivityInfo nextReceiver;
        if (r.nextReceiver < r.receivers.size()) {
            Object obj = r.receivers.get(r.nextReceiver);
            nextReceiver = (obj instanceof ActivityInfo) ? (ActivityInfo)obj : null;
        } else {
            nextReceiver = null;
        }
        if (receiver == null || nextReceiver == null
                    || receiver.applicationInfo.uid != nextReceiver.applicationInfo.uid
                    || !receiver.processName.equals(nextReceiver.processName)) {
            if (mService.mServices.hasBackgroundServices(r.userId)) {
                r.state = BroadcastRecord.WAITING_SERVICES;
                return false;
            }
        }
    }
}

该函数,首先设置BroadcastRecord的state为idle,然后判断是否当前是否需要等待后台服务(前台广播队列不需要等待,后台广播队列需要),如果后台有服务未启动,并且需要等待,则置状态为WAITING_SERVICES,然后返回false,表示不继续分发广播。
这里需要等待服务有几个条件
(1)后台广播队列(r.queue.mDelayBehindServices)
(2)参数指定了需要等待后台服务(waitForServices)
(3)如果当前的是静态注册的广播(r.curComponent != null)
(4)串行队列不为空
(5)串行队列的第一个BroadcastRecord等于当前的要结束的BroadcastRecord
(6)存在待启动的后台服务
第3点是因为当processNextReceiver判断receiver是静态注册的时,会设置curComponent属性
但是及时
第4点和第5点在我们的前面说讲的分发流程中是满足的。

但即使都满足还有一种情况不需要等待,即当前的BroadcastReceiver不为空,并且下一个Receiver是存在且是静态注册的,并且两个属于同一个进程。

回到AMS的finishReceiver函数,如果调用BroadcastQueue.finishReceiverLocked返回为true,表示需要分发给下一个,则调用processNextBroadcast函数,继续分发给下一个receiver,如果没有receiver了,则会调用mOrderedBroadcasts.remove(0)将当前的这个BroadcastRecord移除,表示一个广播分发完成。

至此有序广播的动态注册的接收器的分发已经完成,不过还有一点未分析,即sendOrderedBroadcast函数有个参数BroadcastReceiver resultReceiver,(函数原型sendOrderedBroadcast(Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler)),这里的resultReceiver是什么用的呢?又是何时会调用呢?运行在哪个线程呢?

从函数参数的名字上看,这个应该是有序广播处理结束后会回调该receiver。
从上一篇Android发送广播一文可知,调用sendOrderedBroadcast会调用到ContextImpl.sendOrderedBroadcast,该函数又调用了ContextImpl的另一个重载函数sendOrderedBroadcast
该函数定义在frameworks/base/core/java/android/app/ContextImpl.java

void sendOrderedBroadcast(Intent intent,
           String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
            Handler scheduler, int initialCode, String initialData,
            Bundle initialExtras, Bundle options) {
    IIntentReceiver rd = null;
    if (resultReceiver != null) {
        if (mPackageInfo != null) {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }    
            rd = mPackageInfo.getReceiverDispatcher(
                 resultReceiver, getOuterContext(), scheduler,
                 mMainThread.getInstrumentation(), false);
        } else {
            if (scheduler == null) {
                scheduler = mMainThread.getHandler();
            }    
            rd = new LoadedApk.ReceiverDispatcher(
                resultReceiver, getOuterContext(), scheduler, null, false).getIIntentReceiver();
        }
    }
    ...    
}

如果resultReceiver不为空,则判断scheduler是否为空,如果为空,则获取mMainThread.getHandler()即主线程的Handler,然后调用LoadedApk.getReceiverDispatcher这里传入的参数中有resultReceiver,scheduler, false。
Android BroadcastReceiver的注册 中知道此处的resultReceiver是最后需要回调的对象,scheduler决定了BroadcastReceiver运行在哪个线程,false表示非注册的BroadcastReceiver。

如果指定了Handler,则resultReceiver运行在该Handler对应的线程中,否则就运行在主线程中。

有序广播客户端执行完成后,会调用AMS的finishReceiver,然后调用BroadcastQueue的finishReceiverLocked,最后如果继续分发,则会调用BroadcastQueue.processNextBroadcast

该函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java中

do {
    if (mOrderedBroadcasts.size() == 0) {
        mService.scheduleAppGcsLocked();
        if (looped) {                
            mService.updateOomAdjLocked();
        }
        return;
    }
    r = mOrderedBroadcasts.get(0);
    boolean forceReceive = false;
    int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
    if (mService.mProcessesReady && r.dispatchTime > 0) {
        long now = SystemClock.uptimeMillis();
        if ((numReceivers > 0) &&
                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
            broadcastTimeoutLocked(false); // forcibly finish this broadcast
            forceReceive = true;
            r.state = BroadcastRecord.IDLE;
        }
    }
    if (r.state != BroadcastRecord.IDLE) {
        return;
    }

    if (r.receivers == null || r.nextReceiver >= numReceivers
                        || r.resultAbort || forceReceive) {
        if (r.resultTo != null) {
            try {
                performReceiveLocked(r.callerApp, r.resultTo,
                                new Intent(r.intent), r.resultCode,
                                r.resultData, r.resultExtras, false, false, r.userId);
                            r.resultTo = null;
            } catch (RemoteException e) {
                            r.resultTo = null;
            }
        }
        cancelBroadcastTimeoutLocked();
        addBroadcastToHistoryLocked(r);
        mOrderedBroadcasts.remove(0);
        r = null;
        looped = true;
        continue;
    }
} while (r == null);

在processNextBroadcast函数中存在如下判断
if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive)
运行到这行,说明BroadcastRecord是串行分发的(静态注册的Receiver和有序广播对应的动态注册的Receiver),这个判断说明,该广播没有接收器,或者已经分发完成或者被某一个BroadcastReceiver终止(resultAbort)了,或者超时退出(forceReceive),则会做如下几件事情:
1.发送结束的信息给resultTo,这里就对应前面sendOrderedBroadcast指定的resultReceiver
2.调用cancelBroadcastTimeoutLocked,取消超时的消息
3.从mOrderedBroadcasts移除该广播
第一步会调用performReceiveLocked函数调用客户端的BroadcastReceiver,这里跟前面Step 2 中调用performReceiveLocked流程是一样的。 至此可以知道发送有序广播指定的BroadcastReceiver会在超时或者分发完成或者被某一个BroadcastReceiver终止之后收到回调。

Step 4 静态注册接收器分发(对应进程已启动)

BroadcastQueue.processNextBroadcast
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
                    info.activityInfo.applicationInfo.uid, false);
if (app != null && app.thread != null) {
    app.addPackage(info.activityInfo.packageName,
          info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);                                                                                     
    processCurBroadcastLocked(r, app);       
    return;
}

获取ProcessRecord,如果其已经存在了,则调用processCurBroadcastLocked函数分发
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

private final void processCurBroadcastLocked(BroadcastRecord r,
            ProcessRecord app) throws RemoteException {
    r.receiver = app.thread.asBinder();
    r.curApp = app; 
    app.curReceiver = r; 
    app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
    mService.updateLruProcessLocked(app, false, null);
    mService.updateOomAdjLocked();

    // Tell the application to launch this receiver.
    r.intent.setComponent(r.curComponent);

    boolean started = false;
    try {
        mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
        app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
                    app.repProcState);
            started = true;
    } finally {
        if (!started) {
            r.receiver = null;
            r.curApp = null;
            app.curReceiver = null;
        }    
    }    
}

该函数会调用app.thread.scheduleReceiver函数调用客户端的BroadcastReceiver,动态注册的receiver是调用的app.thread.scheduleRegisteredReceiver,同样的,scheduleReceiver也是one-way的,并不会等待客户端执行完成。但是由于在调用processCurBroadcastLocked前将r.state设置为了APP_RECEIVE r.state = BroadcastRecord.APP_RECEIVE;并且在下一次调用processNextBroadcast时会检查该状态,如果不是IDLE则继续等待,这样就实现了串行分发。

app.thread.scheduleReceiver
是ActivityThread.ApplicationThread中的函数

函数定义在frameworks/base/core/java/android/app/ActivityThread.java中

public final void scheduleReceiver(Intent intent, ActivityInfo info,
                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
                boolean sync, int sendingUser, int processState) {
            updateProcessState(processState, false);
            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
                    sync, false, mAppThread.asBinder(), sendingUser);
            r.info = info;
            r.compatInfo = compatInfo;
            sendMessage(H.RECEIVER, r);
} 

这里实例化一个ReceiverData,其为PendingResult类型跟前面的Args一样,用于处理BroadcastReceiver处理结束之后的事情,ReceiverData初始化时指定类型为TYPE_COMPONENT。然后调用sendMessage函数加入到Looper中,这里的Handler对应ActivityThread.H中,之后会执行handleMessage函数

case RECEIVER:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
        handleReceiver((ReceiverData)msg.obj);
         maybeSnapshot();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;

调用handleReceiver来进一步处理
该函数主要处理
1.加载自定义的BroadcastReceiver类,并实例化
2.调用自定义的BroadcastReceiver的onReceive函数
3.调用ReceiverData的finish
ReceiverData继承自BroadcastReceiver.PendingResult类,因此调用PendingResult的finish函数

BroadcastReceiver.PendingResult.finish
该函数定义在frameworks/base/core/java/android/content/BroadcastReceiver.java

public final void finish() {
    if (mType == TYPE_COMPONENT) {           
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        if (QueuedWork.hasPendingWork()) {       
            QueuedWork.singleThreadExecutor().execute( new Runnable() {
                  @Override public void run() {            
                            sendFinished(mgr);                       
                  }
            });
        } else {
            sendFinished(mgr);
        }
    } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
          //...
    }
}

因为ReceiverData指定的类型是TYPE_COMPONENT,则会调用sendFinished函数

BroadcastReceiver.PendingResult.sendFinished
该函数定义在frameworks/base/core/java/android/content/BroadcastReceiver.java

public void sendFinished(IActivityManager am) {
    synchronized (this) {
        if (mFinished) {
            throw new IllegalStateException("Broadcast already finished");
        }
        mFinished = true;

        try {
            if (mResultExtras != null) {
                        mResultExtras.setAllowFds(false);
            }
            if (mOrderedHint) {
        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
                                mAbortBroadcast, mFlags);
            } else {
        am.finishReceiver(mToken, 0, null, null, false, mFlags);
            }
        } catch (RemoteException ex) {
        }
    }
}

如果收到的是有序广播,则mOrderedHint为true,会调用AMS的finishReceiver函数;
如果收到的是无序广播(此处的接收器为静态注册),则mOrderedHint为false,所以走到else部分,调用AMS的finishReceiver函数。之后的流程跟有序广播的分发是一致的

Step 5 静态注册接收器分发(对应进程未启动)

如果静态注册的接收器所在的进程未启动,则需要先启动进程才可以分发。

BroadcastQueue.processNextBroadcast
函数定义在frameworks/base/core/java/com/android/server/am/BroadcastQueue.java

if ((r.curApp=mService.startProcessLocked(targetProcess,
         info.activityInfo.applicationInfo, true,
         r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
         "broadcast", r.curComponent,
         (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
         == null) {
      // Ah, this recipient is unavailable.  Finish it if necessary,
      // and mark the broadcast record as ready for the next.
      logBroadcastReceiverDiscardLocked(r);
      finishReceiverLocked(r, r.resultCode, r.resultData,
               r.resultExtras, r.resultAbort, false);
      scheduleBroadcastsLocked();
      r.state = BroadcastRecord.IDLE;
      return;
}

mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;

调用AMS的startProcessLocked函数启动BroadcastReceiver所在的进程,然后判断返回值是否为null,如果为空,表明启动进程失败,需要重置部分状态,并分发广播给下一个接收器。如果启动成功,则需要设置mPendingBroadcast为当前正在分发的BroadcastRecord,表明需要等待客户端启动完成才可以再分发。
Android进程启动流程这里暂不做详细分析,在进程启动后,会调用AMS的attachApplication,其中会调用到attachApplicationLocked函数

ActivityManagerService.attachApplicationLocked
函数定义在frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

if (!badApp && isPendingBroadcastProcessLocked(pid)) {
   try {
       didSomething |= sendPendingBroadcastsLocked(app);
   } catch (Exception e) {
       badApp = true;
   }
}

函数会调用isPendingBroadcastProcessLocked判断当前的APP是否存在待接收的广播接收器,如果存在则调用sendPendingBroadcastLocked函数

ActivityManagerService.isPendingBroadcastProcessLocked
函数定义在frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public boolean isPendingBroadcastProcessLocked(int pid) {
    return mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid;
} 

如果mPendingBroadcast不为空,并且当前的待接收的APP的pid等于查询的pid,如果是说明刚启动的进程有待接收的广播,或者说该进程是通过收到广播才启动的。

此处的curApp是何时赋值的呢?
前面在调用AMS的startProcessLocked时将返回值赋值给了r.curApp。

ActivityManagerService.sendPendingBroadcastLocked
函数定义在frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
    boolean didSomething = false;
    final BroadcastRecord br = mPendingBroadcast;
    if (br != null && br.curApp.pid == app.pid) {
        if (br.curApp != app) {     
            return false;
        }
        try {
            mPendingBroadcast = null;                
            processCurBroadcastLocked(br, app);      
            didSomething = true;
        } catch (Exception e) {
            ...
        }
    }
    return didSomething;
}

该函数调用将mPendingBroacast置null,表示没有广播正在等待应用启动。同时调用processCurBroadcastLocked来分发,接下来跟前面的分发进程已经启动的静态注册的接收器的流程是一样的。

参考
https://justanapplication.wordpress.com/tag/flag_receiver_replace_pending/

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值