您的位置:首页 > 移动开发 > Android开发

Android 广播内部机制详解(三)

2017-03-06 16:27 477 查看

4 广播的处理

广播的处理都会调用BroadcastQueue下的scheduleBroadcastsLocked(),接下我们来看看这个函数

4.1 scheduleBroadcastsLocked

文件:BroadcastQueue.java

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


mBroadcastsScheduled这个boolean的意思是如果当前真好有一个BROADCAST_INTENT_MSG在执行,那么mBroadcastsScheduled为true,否则为false

4.1.1 BroadcastHandler

文件:BroadcastQueue.java

private final class BroadcastHandler extends Handler {
......

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
// 见4.2
processNextBroadcast(true);
} break;

......

}
}
}


最重要的就是processNextBroadcast,广播处理会多次调用它

4.2 processNextBroadcast

文件:BroadcastQueue.java

这个函数有500多行,我们分开来讲

4.2.1 非串行广播的处理

// 如果是从BroadcastHandler中调用来的,则fromMsg为true,mBroadcastsScheduled为false
if (fromMsg) {
mBroadcastsScheduled = false;
}

// 首先,立即发送所有的非串行广播
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);
// 将广播发给BroadcastRecord所有的Receiver,见4.3
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
addBroadcastToHistoryLocked(r); //将广播添加历史统计
}


这部分主要是对非串行广播进行发送,通过两层循环来发送所有的Receiver,接下来看看串行发送的广播

4.2.2 串行广播的处理

if (mPendingBroadcast != null) {

boolean isDead;
synchronized (mService.mPidsSelfLocked) {
// 拿到正在处理广播的进程,并判断它是否死亡
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
if (!isDead) {
// 如果处理广播的进程保持活跃状态,则继续等待
return;
} else {
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}


判断处理广播的进程是否保持活跃状态,如果是,则继续等待其完成

boolean looped = false;

do {
if (mOrderedBroadcasts.size() == 0) {
// 所有串行广播执行完毕,则执行GC操作
mService.scheduleAppGcsLocked();
if (looped) {
mService.updateOomAdjLocked();
}
return;
}
// 拿串行广播中的第一个
r = mOrderedBroadcasts.get(0);
boolean forceReceive = false;

// 该ReceiverList中所有接收者的数量
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
// AMS已经注册启动完成,并且不是该r第一次进这个循环了
if (mService.mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis()
// 出现超时
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
broadcastTimeoutLocked(false); // 强制结束这个广播
forceReceive = true;
r.state = BroadcastRecord.IDLE;
}
}
if (r.state != BroadcastRecord.IDLE) {
return;
}


每次都会取mOrderedBroadcasts中的第一个元素,然后判断是否超时,如果超时,则强制结束这个广播,并且这个BroadcastRecord剩下的广播接收器也将收不到广播。超时的依据是:2*mTimeoutPeriod*numReceivers,其中mTimeoutPeriod为(前台广播为10s,后台广播为60s),numReceivers为接收器的数量;接着如果BroadcastRecord的state不等于BroadcastRecord.IDLE,就返回

// 要么是广播已经向所有的receiver发送完毕,要么是被强制停止
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
if (r.resultTo != null) {
try {
// 处理广播消息,调用onReceive(),见4.3.1
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;
}
}

// 取消BROADCAST_TIMEOUT_MSG消息,见4.2.3
cancelBroadcastTimeoutLocked();

addBroadcastToHistoryLocked(r);
if (r.intent.getComponent() == null && r.intent.getPackage() == null
&& (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,
r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);
}
mOrderedBroadcasts.remove(0);
r = null;
looped = true;
continue;
}
} while (r == null);


当Broadcasts中所有的receiver都收到了广播或者被强制结束了广播,都会调用performReceiveLocked;另外如果是取到BroadcastRecord第一次进来这个循环,将之前出来,因为不满足while (r == null)

// 获取下一个需要处理的Receiver的序号
int recIdx = r.nextReceiver++;
// 这个BroadcastRecord开始处理这个Receiver的时间
r.receiverTime = SystemClock.uptimeMillis();
// 如果是BroadcastRecord中第一个Receiver
if (recIdx == 0) {
r.dispatchTime = r.receiverTime;
r.dispatchClockTime = System.currentTimeMillis();
}
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
// 见4.2.4
setBroadcastTimeoutLocked(timeoutTime);
}


获取下一个要处理的Receiver

获取当前处理这个Receiver的时间,用于处理ANR问题,如果是当前处理的是第一个Receiver,你们dispatchTime时间和receiverTime相等,用于处理整个BroadcastRecord的超时问题

mPendingBroadcastTimeoutMessage的初始值是false,然后设置针对该Receiver的超时处理,超时就会造成ANR;超时的时间为10s(前台广播)或者60s(后台广播)

final BroadcastOptions brOptions = r.options;
final Object nextReceiver = r.receivers.get(recIdx);
// 如果是动态注册的有序广播
if (nextReceiver instanceof BroadcastFilter) {
BroadcastFilter filter = (BroadcastFilter)nextReceiver;
// 发送该动态注册的有序广播,见4.3
deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
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;
}


判断当前这个接收器是不是动态注册的,如果是动态注册的,就用deliverToRegisteredReceiverLocked发送,最后return,结束processNextBroadcast这个函数

ResolveInfo info =
(ResolveInfo)nextReceiver;
ComponentName component = new ComponentName(
info.activityInfo.applicationInfo.packageName,
info.activityInfo.name);

......// 主要进行一些权限检查,如果不满足条件skip置为true,跳过这个receiver

if (skip) {
r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
scheduleBroadcastsLocked();
return;
}

r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;
r.state = BroadcastRecord.APP_RECEIVE;
r.curComponent = component;
r.curReceiver = info.activityInfo;

if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {
scheduleTempWhitelistLocked(receiverUid,
brOptions.getTemporaryAppWhitelistDuration(), r);
}

// 广播已经开始执行了,这个包不能被停止
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.curComponent.getPackageName() + ": " + e);
}

// 检查目标进程是否已经运行
if (app != null && app.thread != null) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
//将广播发送给目标进程,见4.2.5
processCurBroadcastLocked(r, app);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
+ r.curComponent, e);
} catch (RuntimeException e) {
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
// 如果启动receiver失败,需要重置state
r.state = BroadcastRecord.IDLE;
return;
}
}

// 如果目标进程没有启动,则需要将他启动,见4.2.6
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) {
// 这个接收器不能使用
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
r.state = BroadcastRecord.IDLE;
return;
}

mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;


处理静态注册下广播的发送,如果进程已经启动,则用processCurBroadcastLocked发送,然后返回,AMS等待广播接收的结果,以便进行下一个receiver发送广播,如果超时,就会触发ANR;

如果没有启动,则AMS调用startProcessLocked来启动接收者进程,启动的时候,将当前这个BroadcastRecord放到mPendingBroadcast中保存,把receiver的序号放到mPendingBroadcastRecvIndex中保存,应用启动完毕后会通知AMS,然后在进行广播发送

4.2.3 cancelBroadcastTimeoutLocked 取消超时

文件:BroadcastQueue.java

final void cancelBroadcastTimeoutLocked() {
if (mPendingBroadcastTimeoutMessage) {
mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
mPendingBroadcastTimeoutMessage = false;
}
}


意思就是移除BROADCAST_TIMEOUT_MSG这个消息,不进行超时的处理了

4.2.4 setBroadcastTimeoutLocked 设置超时

final void setBroadcastTimeoutLocked(long timeoutTime) {
if (! mPendingBroadcastTimeoutMessage) {
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
mHandler.sendMessageAtTime(msg, timeoutTime);
mPendingBroadcastTimeoutMessage = true;
}
}


由mHandler.sendMessageAtTime(msg, timeoutTime)可以看出,如果超时了就会发送消息BROADCAST_TIMEOUT_MSG

4.2.5 processCurBroadcastLocked

文件:BroadcastQueue.java

private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
if (app.inFullBackup) {
skipReceiverLocked(r);
return;
}

r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceiver = r;
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app, false, null);
mService.updateOomAdjLocked();

// 告诉应用启动receiver.
r.intent.setComponent(r.curComponent);

boolean started = false;
try {
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
// 见4.4处理静态广播
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;
}
}
}


这里最重要的是scheduleReceiver

4.2.6 启动进程后通知AMS

流程如下:

ActivityThread.Main

ActivityThread.attach

AMS. attachApplication

AMS. attachApplicationLocked

到了attachApplicationLocked之后里面一行这样的代码:

didSomething |= sendPendingBroadcastsLocked(app);


我们继续看看sendPendingBroadcastsLocked

boolean sendPendingBroadcastsLocked(ProcessRecord app) {
boolean didSomething = false;
for (BroadcastQueue queue : mBroadcastQueues) {
didSomething |= queue.sendPendingBroadcastsLocked(app);
}
return didSomething;
}


主要是这行didSomething |= queue.sendPendingBroadcastsLocked(app),我们继续追

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;
// 发送广播,见4.2.5
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception 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;
}


从mPendingBroadcast取出正在等待的BroadcastRecord,然后将mPendingBroadcast置为null,接着用processCurBroadcastLocked发送广播

4.3 deliverToRegisteredReceiverLocked 用来发送所有动态注册的广播

文件:BroadcastQueue.java

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
boolean skip = false;
if (filter.requiredPermission != null) {
int perm = mService.checkComponentPermission(filter.requiredPermission,
r.callingPid, r.callingUid, -1, true);
// 如果接收者没有权限,skip为true
if (perm != PackageManager.PERMISSION_GRANTED) {
skip = true;
}
......
}

...... //中间这很长一大串代码都是用来检查权限,如果不符合要求skip会置为true

if (skip) {
// 将状态改为DELIVERY_SKIPPED
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}

// 复查一下权限
if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
filter.owningUserId)) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
return;
}
}

r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;

// 如果是有序的动态广播
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) {
r.curApp = filter.receiverList.app;
filter.receiverList.app.curReceiver = r;
mService.updateOomAdjLocked(r.curApp);
}
}
try {
if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
if (ordered) {
skipReceiverLocked(r);
}
} else {
// 发送动态注册的广播,见4.3.1
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;
}
}
......
}


进来时首先检查权限,不满足的将skip设置为true,并将对应的receiver的状态设置为DELIVERY_DELIVERED

如果是有序的动态广播,以一种同步的方式发送广播,并且在BroadcastRecord中保存receiver,curFilter和state,其中state为CALL_IN_RECEIVE

通过performReceiveLocked发送动态注册的广播

如果有序的动态广播,state改为CALL_DONE_RECEIVE

4.3.1 performReceiveLocked

文件:BroadcastQueue.java

void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
Intent intent, int resultCode, String data, Bundle extras,
boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
// 进程已经启动的情况,用binder异步机制向receiver发送数据
if (app != null) {
if (app.thread != null) {
try {
// 见4.3.2
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} catch (RemoteException ex) {
synchronized (mService) {
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} else {
// 应用已经死亡,Receiver不存在
throw new RemoteException("app.thread must not be null");
}
} else {
// 调用进程为null时,则走这个分支
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}


这里分为两种情况:

调用进程和app.thread都不为null,这时通过binder方式向注册进程发起调用,其中Binder调用里会加上IBinder.FLAG_ONEWAY标记

调用流程为:

调用进程为null,这时执行receiver.performReceive(intent, resultCode, data, extras, ordered,sticky, sendingUser);

其中app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState)的调用流程为:

ApplicationThreadNative.ApplicationThreadProxy. scheduleRegisteredReceiver(system_server进程)

Binder驱动(Binder驱动进程,ONEWAY)

ApplicationThreadNative. scheduleRegisteredReceiver(应用进程,Binder线程向主线程发送消息)

Binder驱动返回 (Binder驱动进程)

ActivityThread. scheduleRegisteredReceiver(应用进程,处理消息)

4.3.2 scheduleRegisteredReceiver

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);
// 见4.3.3
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}


4.3.3 performReceive

这是LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive

public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;

......

if (rd != null) {
// 见4.3.4
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
}

......

}


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


4.3.5 Args

final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;

public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,
boolean ordered, boolean sticky, int sendingUser) {
super(resultCode, resultData, resultExtras,
mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,
sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());
mCurIntent = intent;
mOrdered = ordered;
}

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

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

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

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl =  mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
// 调用接收者BroadcastReceiver.onReceive()
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
sendFinished(mgr);
}
if (mInstrumentation == null ||
!mInstrumentation.onException(mReceiver, e)) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw new RuntimeException(
"Error receiving broadcast " + intent
+ " in " + mReceiver, e);
}
}

if (receiver.getPendingResult() != null) {
// 见4.3.6
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}


这里主要调用的是receiver.onReceive(mContext, intent),至此非串行的动态注册的广播已经接收完毕,值得一提的是下面那个finish()函数,作用是结束这个广播,并将结果发送给下一个广播

4.3.6 sendFinished

文件: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) {
// 见4.3.7
am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
mAbortBroadcast, mFlags);
} else {
// 什么都不干,目的是告诉ActivityManager,这个广播我处理我完了
am.finishReceiver(mToken, 0, null, null, false, mFlags);
}
} catch (RemoteException ex) {
}
}
}


通过前面的分析,我们知道,动态广播如果是无序,在执行finish的时候,因为mType等于TYPE_REGISTERED,ordered为false,所以什么都不执行;只有有序的动态广播最终调用sendFinished,走mOrderedHint为true的那条线路,这里面mAbortBroadcast值得注意,如果为true,级别高的接收器收到广播后,级别低的就收不到广播了,好了,我们来看看finishReceiver,看这里函数你能知道动态的广播为什么可以循环起来

4.3.7 finishReceiver

文件:ActivityManagerService.java

public void finishReceiver(IBinder who, int resultCode, String resultData,
Bundle resultExtras, boolean resultAbort, int flags) {

// Refuse possible leaked file descriptors
if (resultExtras != null && resultExtras.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Bundle");
}

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


首先判断是不是是前台广播还是后台广播,如果是后台广播则开始执行下一条广播,值得一提的是resultAbort和mAbortBroadcast上面的一致,最终的影响是这行代码:

if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {


4.4 scheduleReceiver处理静态广播

我们还是一步步来看,首先:

文件: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;
// 见4.4.1
sendMessage(H.RECEIVER, r);
}


4.4.1 H

文件:ActivityThread.java

public void handleMessage(Message msg) {
switch (msg.what) {
......
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
// 见4.4.2
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
......


4.4.2 handleReceiver

文件:ActivityThread.java

private void handleReceiver(ReceiverData data) {
unscheduleGcIdler();

String component = data.intent.getComponent().getClassName();

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

IActivityManager mgr = ActivityManagerNative.getDefault();

BroadcastReceiver receiver;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
data.intent.setExtrasClassLoader(cl);
data.intent.prepareToEnterProcess();
data.setExtrasClassLoader(cl);
// 用反射的方式生成BroadcastReceiver
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
data.sendFinished(mgr);
throw new RuntimeException(
"Unable to instantiate receiver " + component
+ ": " + e.toString(), e);
}

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

ContextImpl context = (ContextImpl)app.getBaseContext();
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
// 调用目标Receiver的onReceive()
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
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();
}
}


用反射的方法获得类,然后生成BroadcastReceiver,接着调用onReceive()方法

5 总结与建议

5.1 并行广播和串行广播的发送特点



这是发广播给动态注册接收器时的特点,采用异步的形式,广播之间不会互相干扰



这是采用串行发送广播的方式,采用的是同步的机制,根据优先级来发送,优先级高的receiver可以停止广播想优先级低的发送;静态注册的Receiver和有序的动态注册的Receiver均采用这个方式

5.2 广播处理的流程图



这张图展示了有序和无序广播的处理流程

5.3 广播处理的时序图



5.4 建议

判断自己的所需要获取的广播是否能够动态注册获取,因为Google基于优化考虑,比如SCREEN_OFF或SCREEN_OFF已经不能通过静态注册来获取了

不要在onReceiver中进行耗时的操作,如果必须要这样做,可以发送Intent启动一个service来做

如果需要一直对广播保持监听,建议使用静态注册,因为静态注册就算是目标进程不在了也可以重启,而动态注册的Receiver的生命周期会受应用的影响,应用销毁了,Receiver也就收不到广播了

如果只在同一APP内部发送和接收广播,将exported属性设置成false,或者可以使用LocalBroadcastManager类(本地广播)

广播发送和接收建议带上权限

如果在onReceive()中开了一个子线程来执行工作,会碰上onReceive()已经返回,而子线程还没有做完工作的情况,这时候如果AMS结束了进程,这时子线程也会挂掉,但是工作却没有做完,可以利用要PendingResult来规避这个问题,一般finish()方法一般都是PendingResult不等于null的时候调用(参考4.3.6),使用方法如下:

public void onReceive(final Context context, final Intent intent) {
//得到PendingResult
final PendingResult result = goAsync();

//放到异步线程中执行
AsyncHandler.post(new Runnable() {
@Override
public void run() {
handleIntent(context, intent);//可进行一些耗时操作
result.finish();
}
});
}


一旦调用goAsync(),那么BroadcastReceiver中的PendingResult将为null,这时finish方法得不到执行,AMS就收不到onReceive()执行完的消息,一直要到子线程调用result.finish()才会知道,这个目的只是为了不阻塞主线程,操作还是要在规定时间内完成
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android broadcast