关闭

Android源码解析四大组件系列(七)---广播的发送过程

标签: android源码数据结构
577人阅读 评论(0) 收藏 举报
分类:

本篇文章的目录

1、广播数据结构分析
2、线程的切换
3、processNextBroadcast分析
  • 3.1、处理并行广播
  • 3.2、处理Pending广播
  • 3.3、处理有序广播
  • 3.4、获取下一条广播
  • 3.5、检查是否是动态广播
  • 3.6、检查是否是静态广播
  • 3.7、启动进程,处理未发送的静态广播
4、动态广播receiver处理
5、静态广播receiver处理

先了解一下广播的数据结构,然后在分析广播的处理过程。建议看本文,需要先看前面两篇文章

Android源码解析—广播的注册过程
Android源码解析—广播的处理过程

1、广播数据结构分析

final class BroadcastRecord extends Binder {

    final Intent intent;    // the original intent that generated us
    final ComponentName targetComp; // original component name set on the intent
    final ProcessRecord callerApp; // 广播调用者进程

    final String[] requiredPermissions; // 调用者需要的权限

    final List receivers;   //存储广播接收者, 包含 BroadcastFilter 和 ResolveInfo

    IIntentReceiver resultTo; // who receives final result if non-null
    long enqueueClockTime;  // 加入队列的时间
    long dispatchTime;      // 分发时间
    long dispatchClockTime; //分发时间
    long receiverTime;      // 接收时间.
    long finishTime;        ////广播完成时间

    int nextReceiver;       // 下一个广播接收者
    IBinder receiver;       //当前广播接收者
    int state;
    int anrCount;           //广播ANR次数

    ProcessRecord curApp;       // hosting application of current receiver.
    ComponentName curComponent; // the receiver class that is currently running.
    ActivityInfo curReceiver;   // info about the receiver that is currently running.

}

比较重要的数据成员有receivers,存储的都是广播接收器,callerApp是广播调用者进程,还要注意四个时间点,有入队列,分发,接收,完成,另外动态广播节点用BroadcastFilter描述,静态的用ResolveInfo描述。

  • ReceiverDispatcher: 客户端广播分发者对象,第一篇讲的很清楚了,ReceiverDispatcher的内部类InnerReceiver为binder对象,用于与AMS的传递与通信。

  • ReceiverList: 继承自ArrayList,存放了Receiver的binder对象以及其注册的BroadcastFilter列表。AMS中定义了
    final HashMap

2、线程的切换

上篇说到不管是有序广播、无序广播还是粘性广播最终都是调用scheduleBroadcastsLocked处理的。那么scheduleBroadcastsLocked做了什么?

    public void scheduleBroadcastsLocked() {
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
                + mQueueName + "]: current="
                + mBroadcastsScheduled);

        //mBroadcastsScheduled参数是用来标记是否已经向消息队列发送了一个类型为BROADCAST_INTENT_MSG消息
        if (mBroadcastsScheduled) {
            return;
        }
        //发送一个BROADCAST_INTENT_MSG消息
        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
        mBroadcastsScheduled = true;
    }

mHandler是BroadcastQueue的成员变量,定义如下

final BroadcastHandler mHandler;

它在BroadcastQueue构造函数中初始化

   BroadcastQueue(ActivityManagerService service, Handler handler,
            String name, long timeoutPeriod, boolean allowDelayBehindServices) {
        mService = service;
        mHandler = new BroadcastHandler(handler.getLooper());
        mQueueName = name;
        mTimeoutPeriod = timeoutPeriod;
        mDelayBehindServices = allowDelayBehindServices;
    }

参数中的handler是AMS中的MainHandler,所以BroadcastHandler采用的是ActivityManager线程的Looper,所以通过上面发送一个BROADCAST_INTENT_MSG消息,现在由system_server的binder线程切换到system_server的ActivityManager线程中。

    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: {
                    if (DEBUG_BROADCAST) Slog.v(
                            TAG_BROADCAST, "Received BROADCAST_INTENT_MSG");
                    // 处理广播
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                      //超时的时候走这里
                        broadcastTimeoutLocked(true);
                    }
                } break;
                case SCHEDULE_TEMP_WHITELIST_MSG: {
                    DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
                    if (dic != null) {
                        dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
                                msg.arg2, true, (String)msg.obj);
                    }
                } break;
            }
        }
    }

所以现在重点分析processNextBroadcast方法。

3、processNextBroadcast分析

processNextBroadcast方法的代码跟broadcastIntentLocked方法一样,也是很长,所以分段来分析。

3.1、处理并行广播

   mService.updateCpuStats();

    //fromMsg字段标记是否是从handleMessage中调用的该方法  
    if (fromMsg) {
        //设置该参数为false,表示前面发送到消息队列中的BROADCAST_INTENT_MSG消息已经被处理了
        mBroadcastsScheduled = false;
    }

    //并行广播在这里循环一次性处理掉
    while (mParallelBroadcasts.size() > 0) {
        r = mParallelBroadcasts.remove(0);
        r.dispatchTime = SystemClock.uptimeMillis();
        r.dispatchClockTime = System.currentTimeMillis();
        final int N = r.receivers.size();
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                + mQueueName + "] " + r);
        for (int i=0; i<N; i++) {
            Object target = r.receivers.get(i);
            if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                    "Delivering non-ordered on [" + mQueueName + "] to registered "
                    + target + ": " + r);
            //并行广播都是从deliverToRegisteredReceiverLocked发送出去的,此时r.receivers里面的都是BroadcastFilter
            deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
        }

        addBroadcastToHistoryLocked(r);
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                + mQueueName + "] " + r);
    }

3.2、处理Pending广播

如果一个广播在发送的时候,进程还没有启动起来,那么会将它存在mPendingBroadcast中。由于动态广播是不会保证一定能够收到的,所以mPendingBroadcast是用来描述一个正在等待静态注册的目标广播接收者启动的广播。

  // Now take care of the next serialized one...

    // If we are waiting for a process to come up to handle the next
    // broadcast, then do nothing at this point.  Just in case, we
    // check that the process we're waiting for still exists.
    if (mPendingBroadcast != null) {
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                "processNextBroadcast [" + mQueueName + "]: waiting for "
                + mPendingBroadcast.curApp);

        boolean isDead;
        // 检查这个静态注册的目标广播接收者所运行在的应用程序进程是否已经启动起来  
        synchronized (mService.mPidsSelfLocked) {
            ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
            isDead = proc == null || proc.crashing;
        }
        如果这个应用程序进程还活着,就会继续等待,否则就不等了
        if (!isDead) {
            // It's still alive, so keep waiting
            return;
        } else {
            Slog.w(TAG, "pending app  ["
                    + mQueueName + "]" + mPendingBroadcast.curApp
                    + " died before responding to broadcast");
            mPendingBroadcast.state = BroadcastRecord.IDLE;
            mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
            mPendingBroadcast = null;
        }
    }
    boolean looped = false;

3.3、处理有序广播

有序广播是一个接着一个处理的,并且还可以拦截,

do {
        //有序广播队列为0,不用处理,返回
        if (mOrderedBroadcasts.size() == 0) {
            // No more broadcasts pending, so all done!
            mService.scheduleAppGcsLocked();
            if (looped) {
                // If we had finished the last ordered broadcast, then
                // make sure all processes have correct oom and sched
                // adjustments.
                //更改一下OOM
                mService.updateOomAdjLocked();
            }
            return;
        }
        //获取一个有序广播(最顶部的BroadcastRecord)
        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))) {
                Slog.w(TAG, "Hung broadcast ["
                        + mQueueName + "] discarded after timeout failure:"
                        + " now=" + now
                        + " dispatchTime=" + r.dispatchTime
                        + " startTime=" + r.receiverTime
                        + " intent=" + r.intent
                        + " numReceivers=" + numReceivers
                        + " nextReceiver=" + r.nextReceiver
                        + " state=" + r.state);
                 //超时不能接收,就强制结束广播
                broadcastTimeoutLocked(false); // forcibly finish this broadcast
                forceReceive = true;
                //恢复初始状态。
                r.state = BroadcastRecord.IDLE;
            }
        }

        if (r.state != BroadcastRecord.IDLE) {
            if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST,
                    "processNextBroadcast("
                    + mQueueName + ") called when not idle (state="
                    + r.state + ")");
            return;
        }

         // 进入下面的条件有以下集中可能,一:广播没有接收者了,二:默认第一次r.nextReceiver = 0,但是它每次都会++,等待最后一个处理完了,再++就会得到一个不存在的nextReceiver,此时r.nextReceiver >= numReceivers,条件成立,三:
广播是否已经被拦截了,四:广播是否已经被强制结束了  
        if (r.receivers == null || r.nextReceiver >= numReceivers
                || r.resultAbort || forceReceive) {
            // No more receivers for this broadcast!  Send the final
            // result if requested...
            if (r.resultTo != null) {
                try {
                    if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                            "Finishing broadcast [" + mQueueName + "] "
                            + r.intent.getAction() + " app=" + r.callerApp);
                   //处理广播消息消息,调用到onReceive()
                    performReceiveLocked(r.callerApp, r.resultTo,
                        new Intent(r.intent), r.resultCode,
                        r.resultData, r.resultExtras, false, false, r.userId);
                    // Set this to null so that the reference
                    // (local and remote) isn't kept in the mBroadcastHistory.
                    r.resultTo = null;
                } catch (RemoteException e) {
                    r.resultTo = null;
                    Slog.w(TAG, "Failure ["
                            + mQueueName + "] sending broadcast result of "
                            + r.intent, e);

                }
            }

            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG");
                //r所描述的广播转发任务已经在规定时间内处理完了,需要remove掉前面给mHandler发送的BROADCAST_TIMEOUT_MSG消息。
            cancelBroadcastTimeoutLocked();

            if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                    "Finished with ordered broadcast " + r);

            // ... and on to the next...
            addBroadcastToHistoryLocked(r);
            if (r.intent.getComponent() == null && r.intent.getPackage() == null
                    && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
                // This was an implicit broadcast... let's record it for posterity.
                mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
                        r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
            }
            // 将r所描述的广播转发任务从有序广播队列中删除  
            mOrderedBroadcasts.remove(0);
            //赋值为null,进入下一次循环
            r = null;
            looped = true;
            continue;
        }
 } while (r == null);

 3.4、获取下一条广播

    //通过上面的循环,r就有值了,获取下一条广播
    int recIdx = r.nextReceiver++;

    // Keep track of when this receiver started, and make sure there
    // is a timeout message pending to kill it if need be.
    r.receiverTime = SystemClock.uptimeMillis();
    if (recIdx == 0) {
        r.dispatchTime = r.receiverTime;
        r.dispatchClockTime = System.currentTimeMillis();
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast ["
                + mQueueName + "] " + r);
    }
    if (! mPendingBroadcastTimeoutMessage) {
        long timeoutTime = r.receiverTime + mTimeoutPeriod;
        if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
                "Submitting BROADCAST_TIMEOUT_MSG ["
                + mQueueName + "] for " + r + " at " + timeoutTime);
        setBroadcastTimeoutLocked(timeoutTime);
    }ComponentName component

    final BroadcastOptions brOptions = r.options;
    final Object nextReceiver = r.receivers.get(recIdx);
 ```

####3.5、检查是否是动态广播
 //检查是否是动态广播

if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
“Delivering ordered [”
+ mQueueName + “] to registered ”
+ filter + “: ” + r);
//动态注册的广播给deliverToRegisteredReceiverLocked处理
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
//判断是否是无序广播
if (r.receiver == null || !r.ordered) {
// The receiver has already finished, so schedule to
// process the next one.
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, “Quick finishing [”
+ mQueueName + “]: ordered=”
+ r.ordered + ” receiver=” + r.receiver);
//将 r.state设置为IDLE,表示不需要等待它的前一个目标广播接收者处理完成一个广播,
// 就可以将该广播继续发送给它的下一个目标广播接收者处理
r.state = BroadcastRecord.IDLE;
//执行下一个广播,内部也是发送消息
scheduleBroadcastsLocked();
} else {
….
}
//有序广播一次只处理一个,直接返回就行
return;
}


####3.6、检查是否是静态广播

//如果上面没有return,那么肯定是静态注册的广播,静态注册注册的广播节点是ResolveInfo
ResolveInfo info = (ResolveInfo)nextReceiver;
//这个ComponentName会一直传递到ActivityThread,用来反射new广播接收者对象的
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);
//很多的条件判断,skip不满足就为true
boolean skip = false;
…….

 String targetProcess = info.activityInfo.processName;
 ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
        info.activityInfo.applicationInfo.uid, false);

 if (skip) {
    if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
            "Skipping delivery of ordered [" + mQueueName + "] "
            + r + " for whatever reason");
    r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
    r.receiver = null;
    r.curFilter = null;
//变成初始状态
    r.state = BroadcastRecord.IDLE;
//执行下个广播
    scheduleBroadcastsLocked();
    return;
 }

…….
//如果当前进程存在,调用processCurBroadcastLocked处理,静态广播都是走processCurBroadcastLocked处理的
if (app != null && app.thread != null) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
processCurBroadcastLocked(r, app);
//处理完直接返回,一次处理一个
return;
} catch (RemoteException e) {
Slog.w(TAG, “Exception when sending broadcast to ”
+ r.curComponent, e);
} catch (RuntimeException e) {
Slog.wtf(TAG, “Failed sending broadcast to ”
+ r.curComponent + ” with ” + r.intent, e);
// If some unexpected exception happened, just skip
// this broadcast. At this point we are not in the call
// from a client, so throwing an exception out from here
// will crash the entire system instead of just whoever
// sent the broadcast.
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
// We need to reset the state if we failed to start the receiver.
r.state = BroadcastRecord.IDLE;
return;
}

    // If a dead object exception was thrown -- fall through to
    // restart the application.
}

//程序走到这里,说明进程不存在,那么调用startProcessLocked启动进程,
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.
Slog.w(TAG, “Unable to launch app ”
+ info.activityInfo.applicationInfo.packageName + “/”
+ info.activityInfo.applicationInfo.uid + ” for broadcast ”
+ r.intent + “: process is bad”);
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
//启动失败就执行下一个
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}
//把当前的r存下来,方便下一次处理
mPendingBroadcast = r;
//设置当前的receiver的索引,用来表示将要启动的。
mPendingBroadcastRecvIndex = recIdx;

“`

3.7、启动进程,处理未发送的静态广播

当进程启动完成之后,会回调AMS的attachApplication,然后走到attachApplicationLocked。
“`
// Check if a next-broadcast receiver is in this process…
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it ‘bad’
Slog.wtf(TAG, “Exception thrown dispatching broadcasts in ” + app, e);
badApp = true;
}
}



// The app just attached; send any pending broadcasts that it should receive
boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
for (BroadcastQueue queue : mBroadcastQueues) {
didSomething |= queue.sendPendingBroadcastsLocked(app);
}
return didSomething;
}

public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
final BroadcastRecord br = mPendingBroadcast;
if (br != null && br.curApp.pid == app.pid) {
if (br.curApp != app) {
Slog.e(TAG, “App mismatch when sending pending broadcast to ”
+ app.processName + “, intended target is ” + br.curApp.processName);
return false;
}
try {
//目标进程已经成功启动了,那么mPendingBroadcast就可以赋值为null了
mPendingBroadcast = null;
//调用processCurBroadcastLocked处理广播
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, “Exception in new application when starting receiver ”
+ br.curComponent.flattenToShortString(), e);
logBroadcastReceiverDiscardLocked(br);
finishReceiverLocked(br, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, false);
scheduleBroadcastsLocked();
// We need to reset the state if we failed to start the receiver.
br.state = BroadcastRecord.IDLE;
throw new RuntimeException(e.getMessage());
}
}
return didSomething;
}

“`

看完上面的三个小节,到这里总结一下 processNextBroadcast()的代码逻辑:

  • 如果是动态广播接收者(无序),会调用deliverToRegisteredReceiverLocked一次性处理,即遍历并行列表(mParallelBroadcasts)的每一个BroadcastRecord以及其中的receivers列表,是一个双重循环。
  • 如果是静态广播接收者(有序),且对应进程已经创建,会调用processCurBroadcastLocked继续处理;
  • 如果是静态广播接收者(有序),且对应进程尚未创建,会调用startProcessLocked创建进程,之后仍然会调用processCurBroadcastLocked继续处理。

4、动态广播receiver处理

上面主要分析了动态广播接收者和静态广播接收者该如何处理,现在先看动态广播是如何处理的。就是分析deliverToRegisteredReceiverLocked方法实现。
“`
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
//权限判断, 检查发送者是否有权限,检查接收者是否有发送者所需的权限等等,
//此处省略,不符合的skip==true,下面就return。
….

    if (skip) {
        r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
        return;
    }

      ....
    //只有有序广播才会进入这个分支
    if (ordered) {
        r.receiver = filter.receiverList.receiver.asBinder();
        r.curFilter = filter;
        filter.receiverList.curBroadcast = r;
        r.state = BroadcastRecord.CALL_IN_RECEIVE;
        if (filter.receiverList.app != null) {
            // Bump hosting application to no longer be in background
            // scheduling class.  Note that we can't do that if there
            // isn't an app...  but we can only be in that case for
            // things that directly call the IActivityManager API, which
            // are already core system stuff so don't matter for this.
            r.curApp = filter.receiverList.app;
            filter.receiverList.app.curReceiver = r;
            mService.updateOomAdjLocked(r.curApp);
        }
    }
    try {
        if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                "Delivering to " + filter + " : " + r);
        if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
            // Skip delivery if full backup in progress
            // If it's an ordered broadcast, we need to continue to the next receiver.
            if (ordered) {
                skipReceiverLocked(r);
            }
        } else {
        //处理广播,filter.receiverList.receiver对应的是客户端ReceiverDispatcher的Binder实体——InnerReceiver
            performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                    new Intent(r.intent), r.resultCode, r.resultData,
                    r.resultExtras, r.ordered, r.initialSticky, r.userId);
        }
        if (ordered) {
            r.state = BroadcastRecord.CALL_DONE_RECEIVE;
        }
    } catch (RemoteException e) {
       ....
    }
}

“`

 void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
        // Send the intent to the receiver asynchronously using one-way binder calls.
        if (app != null) {
            if (app.thread != null) {
                try {
                    //终于走到ActivityThread里面了
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                } catch (RemoteException ex) {
                    .....
                }
            } 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);
        }
    }
       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);
           //走到ReceiverDispatcher中的performReceive实际是InnerReceiver内部类当中的方法
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

终于走到客户端的ReceiverDispatcher(广播分发者)了,ReceiverDispatcher知道我们这个广播要分发给谁。此时正式由SystemServer进程回到客户端进程了。

    @Override
     public void performReceive(Intent intent, int resultCode, String data,
            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
        final LoadedApk.ReceiverDispatcher rd;
         ......
        if (rd != null) {
            rd.performReceive(intent, resultCode, data, extras,
                    ordered, sticky, sendingUser);
        } else {
            // The activity manager dispatched a broadcast to a registered
            // receiver in this process, but before it could be delivered the
            // receiver was unregistered.  Acknowledge the broadcast on its
            // behalf so that the system's broadcast sequence can continue.
            if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                    "Finishing broadcast to unregistered receiver");
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                if (extras != null) {
                    extras.setAllowFds(false);
                }
                mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }

可以看到我们调用ReceiverDispatcher中InnerReceiver的performReceive之后,紧接着在内部调用了ReceiverDispatcher的performReceive方法,再看ReceiverDispatcher的performReceive方法。

 public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            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);
                }
            }
            //post了一个消息给主线程
            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);
                    ///发送完成本次广播处理,用来进行下次的广播处理。
                    args.sendFinished(mgr);
                }
            }
        }

上面的mActivityThread在第一篇文章说过,代表主线程,所以现在会执行args的run方法。

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

        if (ActivityThread.DEBUG_BROADCAST) {
            int seq = mCurIntent.getIntExtra("seq", -1);
            Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
                    + " seq=" + seq + " to " + mReceiver);
            Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
                    + " mOrderedHint=" + ordered);
        }

        final IActivityManager mgr = ActivityManagerNative.getDefault();
        final Intent intent = mCurIntent;
        if (intent == null) {
            Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);
        }

        ......
        try {
            ClassLoader cl =  mReceiver.getClass().getClassLoader();
            intent.setExtrasClassLoader(cl);
            intent.prepareToEnterProcess();
            setExtrasClassLoader(cl);
            receiver.setPendingResult(this);
        //onReceive方法回调
            receiver.onReceive(mContext, intent);
        } catch (Exception e) {
            .....
    }

到此,deliverToRegisteredReceiverLocked是怎么处理动态广播就分析完毕了。总结一下主要流程

——|-BroadcastQueue.performReceiveLocked()
——|——-|-ActivityThread.ApplicationThread.scheduleRegisteredReceiver()
——|——-|——-|- ReceiverDispatcher.InnerReceiver.performReceive()
——|——-|——-|——-|-Handler.post(args)
——|——-|——-|——-|——-|-Args.run()
——|——-|——-|——-|——-|——-|-BroadcastReceiver.onReceive()

5、静态广播receiver处理

刚刚说了静态广播是processCurBroadcastLocked处理的

    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);
        //更新adj
        mService.updateOomAdjLocked();

        // Tell the application to launch this receiver.告诉客户端启动这个receiver
        r.intent.setComponent(r.curComponent);

        boolean started = false;
        try {
              .....
            //走到了ActivityThread中的ApplicationThread中对应的方法。
            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);
            if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                    "Process cur broadcast " + r + " DELIVERED for app " + app);
            started = true;
        } finally {
            .....
            }
         }
     }

此时正式由SystemServer进程进入了客户端进程了

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

一样的套路,发送一个消息给主线程,进入对应的case,执行 handleReceiver((ReceiverData)msg.obj);

    private void handleReceiver(ReceiverData data) {

       // 这个最初就是在processNextBroadcast处理静态注册的ResolveInfo时,new的ComponentName。
        String component = data.intent.getComponent().getClassName();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);

        IActivityManager mgr = ActivityManagerNative.getDefault();

        BroadcastReceiver receiver;
        try {
        //反射出BroadcastReceiver
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            data.intent.setExtrasClassLoader(cl);
            data.intent.prepareToEnterProcess();
            data.setExtrasClassLoader(cl);
            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
        } catch (Exception e) {
            if (DEBUG_BROADCAST) Slog.i(TAG,
                    "Finishing failed broadcast to " + data.intent.getComponent());
            data.sendFinished(mgr);
            throw new RuntimeException(
                "Unable to instantiate receiver " + component
                + ": " + e.toString(), e);
        }

        try {
            Application app = packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(
                TAG, "Performing receive of " + data.intent
                + ": app=" + app
                + ", appName=" + app.getPackageName()
                + ", pkg=" + packageInfo.getPackageName()
                + ", comp=" + data.intent.getComponent().toShortString()
                + ", dir=" + packageInfo.getAppDir());

            ContextImpl context = (ContextImpl)app.getBaseContext();
            sCurrentBroadcastIntent.set(data.intent);
            receiver.setPendingResult(data);
        //这个和动态的不一样,静态的广播onReceive方法中的context是RestrictedContext
            receiver.onReceive(context.getReceiverRestrictedContext(),
                    data.intent);
        } catch (Exception e) {
            if (DEBUG_BROADCAST) Slog.i(TAG,
                    "Finishing failed broadcast to " + data.intent.getComponent());
            data.sendFinished(mgr);
            if (!mInstrumentation.onException(receiver, e)) {
                throw new RuntimeException(
                    "Unable to start receiver " + component
                    + ": " + e.toString(), e);
            }
        } finally {
            sCurrentBroadcastIntent.set(null);
        }

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

到这总结一下静态广播接收者的处理流程,如下:
如果应用程序已经启动(app.thread != null)
——|-ActivityThread.ApplicationThread.scheduleReceiver()
——|——|- ActivityThread.handleReceiver()
——|——-|——-|- BroadcastReceiver.onReceive()
否则
——|-LoadedApk.ReceiverDispatcher.IntentReceiver.performReceive()
——|——-|-LoadedApk.ReceiverDispatcher.performReceiver()
——|——-|——-|- LoadedApk.ReceiverDispatcher.Args.run()
——|——-|——-|——-|-BroadcastReceiver.onReceive()

至此广播的处理过程就结束了,下篇写一下广播细节,加深理解,比如广播有序是怎么保证的?怎么实现广播拦截处理的?广播超时是怎么处理的?onReceive方法中可以在发送广播吗?registerReceiver方法发返回值有什么用?粘性广播等等

0
0
查看评论

Android源码解析四大组件系列(五)---广播的注册过程

广播这个篇幅打算用四篇文章来写,分别为广播注册、广播处理、广播的发送,广播深入细节理解,如果都写到一篇文章会比较长,所以拆分成四篇来写。第一篇 Android源码解析—广播的注册过程 第二篇 Android源码解析—广播的处理过程 第三篇 Android源码解析—广播的发送过...
  • u013263323
  • u013263323
  • 2017-07-20 19:17
  • 595

Android源码解析四大组件系列(六)---广播的处理过程

这篇文章紧接着上篇分析广播的发送过程,发送广播都是调用ContextImpl的接口去实现的,总共有二十多个,最终都是调用到AMS的broadcastIntent。主要分成下面九小节来说明。 1、设置Flag 2、检查BroadcastOptions 3、当前是否有权力发出广播 4、处...
  • u013263323
  • u013263323
  • 2017-07-24 11:48
  • 604

Android源码解析四大组件系列(八)---广播几个问题的深入理解

接上篇文章,这篇文章主要是总结前面知识,并且了解一些细节问题,加深对广播机制的理解,比如有播有序是怎么保证有序的?广播拦截机制是怎么实现的?广播发送超时了是怎么处理的?registerReceiver方法发返回值有什么用?粘性广播等等。Android源码解析四大组件系列(五)—广播的注册过程Andr...
  • u013263323
  • u013263323
  • 2017-07-24 15:29
  • 334

Android Broadcast广播注册和发布方式以及机制流程

Broadcast大致机制流程: 1. 广播接受者BroadcastReceiver通过Binder机制向AMS(AndroidManagerService)进行注册; 2. 广播发送者通过Binder机制向AMS发送广播; 3. AMS查找符合条件(IntentFilter/Permi...
  • liu_3262296
  • liu_3262296
  • 2016-07-17 23:06
  • 1892

从源码的角度理解四大组件的工作过程——Android开发艺术探索笔记

系统对四大组件的过程进行了很大程度的封装,日常开发中并不需要了解底层的工作原理,那么研究这些原理的意义在哪里呢? 如果你想在技术上更进一步,那么了解一些系统的工作原理是十分必要的,也是开发人员日后成长为高级工程师所必备的技术能力。 Android作为一个优秀的基于Linux操作系统,其内部一定
  • L664675249
  • L664675249
  • 2016-03-15 10:26
  • 2135

MySQL系列之七:主从复制

一:实验环境 IP 操作系统 mysql版本号 master 192.168.25.11 CentOS7 5.6.35 slave 192.168.25.10 win10 5.7.18 slave版本需要大于等于master,否则master上的一些操...
  • ydyang1126
  • ydyang1126
  • 2017-04-14 17:09
  • 350

UDP收/发广播包原理及步骤

UDP收/发广播包原理及步骤   如果网络中两个主机上的应用程序要相互通信,其一要知道彼此的IP,其二要知道程序可监听的端口。因为同一主机上的程序使用网络是通过端口号来区分的。 UDP Socket的使用过程: 1. 初始化网络库 2. 创建SOCK_DGRA...
  • agonie201218
  • agonie201218
  • 2016-03-31 15:56
  • 2235

【Android技巧】通过am完成发送开机广播等操作

作者:Yogi前言:许多应用都有接收开机广播,进行一些操作的功能,每次调试这些功能总是要重启机器很麻烦,庆幸的是,我们可以在终端通过安卓自带的am命令来发送开机广播,省去了等待的时间。发送开机广播的命令如下am broadcast -a android.intent.action.BOOT_COMP...
  • Q316510202
  • Q316510202
  • 2016-03-17 17:14
  • 1785

解析短信发送和接收流程

MMS 应用主要源码汇总及简要说明 主动发生短信流程分析 进入短信回话列表界面: 短信应用包路径:packages/app/Mms 打开AndroidMainfest.xml 配置文件,入口就是ConversationList.java "新建短信"按钮,调用create...
  • hongkang218
  • hongkang218
  • 2016-09-18 19:08
  • 329

发送广播的两种方式

自定义广播 发送广播sendBroadcast(intent)发送的无序广播 sendOrderedBroadcast(intent,null)发一条有序的广播,优先级高的先接受到 清单文件中指定优先级priority=“1000” 1000是最大的 高优先级的广播接受者可...
  • yushanfenghailin
  • yushanfenghailin
  • 2014-03-02 15:07
  • 1321
    个人资料
    • 访问:78700次
    • 积分:1666
    • 等级:
    • 排名:千里之外
    • 原创:87篇
    • 转载:0篇
    • 译文:0篇
    • 评论:18条
    博客专栏