Android Framework学习笔记(九)Broadcast的注册,移动APP开发框架盘点

本文详细解析了Android粘性广播的工作原理,包括如何通过actions列表和userIds获取粘性广播的intent,以及如何将BroadcastFilter添加到mReceiverResolver中以便AMS能够正确地找到对应的广播接收者。
摘要由CSDN通过智能技术生成

注释2处根据actions列表和userIds(userIds可以理解为应用程序的uid)得到所有的粘性广播的intent,并传入到stickyIntents中。

注释3处将这些粘性广播的intent存入到allSticky列表中,从这里可以看出粘性广播是存储在AMS中的。

注释4处获取ReceiverList列表,ReceiverList继承自ArrayList,用来存储广播接收者。

注释5处创建BroadcastFilter并传入此前创建的ReceiverList,BroadcastFilter用来描述注册的广播接收者。

注释6通过add方法将注释5创建的BroadcastFilter添加到ReceiverList中。

注释7处将BroadcastFilter添加到mReceiverResolver中,这样当AMS接收到广播时就可以从mReceiverResolver中找到对应的广播接收者了。

时序图:

image

广播的发送


广播有很多类型:无序广播(普通广播)、有序广播、粘性广播和APP内部广播,这里以普通广播为例,来讲解广播的发送过程。

要发送普通广播需要调用sendBroadcast方法,它的实现同样在ContextWrapper中:

frameworks/base/core/java/android/content/ContextWrapper.java

ContextWrapper#sendBroadcast()

@Override

public void sendBroadcast(Intent intent) {

mBase.sendBroadcast(intent);

}

frameworks/base/core/java/android/app/ContextImpl.java

ContextImpl#sendBroadcast()

@Override

public void sendBroadcast(Intent intent) {

warnIfCallingFromSystemProcess();

String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());

try {

intent.prepareToLeaveProcess(this);

//1

ActivityManagerNative.getDefault().broadcastIntent(

mMainThread.getApplicationThread(), intent, resolvedType, null,

Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,

getUserId());

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

注释1处最终会调用AMS的broadcastIntent方法。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService#broadcastIntent()

public final int broadcastIntent(IApplicationThread caller,

Intent intent, String resolvedType, IIntentReceiver resultTo,

int resultCode, String resultData, Bundle resultExtras,

String[] requiredPermissions, int appOp, Bundle bOptions,

boolean serialized, boolean sticky, int userId) {

synchronized(this) {

intent = verifyBroadcastLocked(intent); //1

final ProcessRecord callerApp = getRecordForAppLocked(caller);

final int callingPid = Binder.getCallingPid();

final int callingUid = Binder.getCallingUid();

final long origId = Binder.clearCallingIdentity();

//2

int res = broadcastIntentLocked(callerApp,

callerApp != null ? callerApp.info.packageName : null,

intent, resolvedType, resultTo, resultCode, resultData, resultExtras,

requiredPermissions, appOp, bOptions, serialized, sticky,

callingPid, callingUid, userId);

Binder.restoreCallingIdentity(origId);

return res;

}

}

注释1处通过verifyBroadcastLocked方法验证广播是否合法。

注释2处调用broadcastIntentLocked方法。

先看看注释1的verifyBroadcastLocked方法:

ActivityManagerService#verifyBroadcastLocked()

final Intent verifyBroadcastLocked(Intent intent) {

// Refuse possible leaked file descriptors

if (intent != null && intent.hasFileDescriptors() == true) { //1

throw new IllegalArgumentException(“File descriptors passed in Intent”);

}

int flags = intent.getFlags(); //2

if (!mProcessesReady) {

// if the caller really truly claims to know what they’re doing, go

// ahead and allow the broadcast without launching any receivers

if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) { //3

// This will be turned into a FLAG_RECEIVER_REGISTERED_ONLY later on if needed.

} else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { //4

Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent

  • " before boot completion");

throw new IllegalStateException(“Cannot broadcast before boot completed”);

}

}

if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {

throw new IllegalArgumentException(

“Can’t use FLAG_RECEIVER_BOOT_UPGRADE here”);

}

return intent;

}

注释1处验证intent是否不为null并且有文件描述符。

注释2处获得intent中的flag。

注释3处如果系统正在启动过程中,判断如果flag设置为FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT(启动检查时只接受动态注册的广播接收者)则不做处理,如果不是则在注释4处判断如果flag没有设置为FLAG_RECEIVER_REGISTERED_ONLY(只接受动态注册的广播接收者)则会抛出异常。

继续来看broadcastIntent的注释2。

ActivityManagerService#broadcastIntentLocked()

final int broadcastIntentLocked(ProcessRecord callerApp,

String callerPackage, Intent intent, String resolvedType,

IIntentReceiver resultTo, int resultCode, String resultData,

Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,

boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {

// Figure out who all will receive this broadcast.

List receivers = null;

if (intent.getComponent() == null) {

if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {

// Query one target user at a time, excluding shell-restricted users

for (int i = 0; i < users.length; i++) {

List registeredReceiversForUser =

mReceiverResolver.queryIntent(intent,

resolvedType, false, users[i]); //1

if (registeredReceivers == null) {

registeredReceivers = registeredReceiversForUser;

} else if (registeredReceiversForUser != null) {

registeredReceivers.addAll(registeredReceiversForUser);

}

}

} else {

registeredReceivers = mReceiverResolver.queryIntent(intent,

resolvedType, false, userId);

}

}

// Merge into one list.

int ir = 0;

if (receivers != null) {

int NT = receivers != null ? receivers.size() : 0;

int it = 0;

ResolveInfo curt = null;

BroadcastFilter curr = null;

//2

while (it < NT && ir < NR) {

if (curt == null) {

curt = (ResolveInfo)receivers.get(it);

}

if (curr == null) {

curr = registeredReceivers.get(ir);

}

if (curr.getPriority() >= curt.priority) {

// Insert this broadcast record into the final list.

receivers.add(it, curr);

ir++;

curr = null;

it++;

NT++;

} else {

// Skip to the next ResolveInfo in the final list.

it++;

curt = null;

}

}

}

while (ir < NR) {

if (receivers == null) {

receivers = new ArrayList();

}

receivers.add(registeredReceivers.get(ir));

ir++;

}

if ((receivers != null && receivers.size() > 0)

|| resultTo != null) {

BroadcastQueue queue = broadcastQueueForIntent(intent);

//3

BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,

callerPackage, callingPid, callingUid, resolvedType,

requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,

resultData, resultExtras, ordered, sticky, false, userId);

if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r

  • ": prev had " + queue.mOrderedBroadcasts.size());

if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,

"Enqueueing broadcast " + r.intent.getAction());

boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked®;

if (!replaced) {

queue.enqueueOrderedBroadcastLocked®;

queue.scheduleBroadcastsLocked(); //4

}

} else {

}

return ActivityManager.BROADCAST_SUCCESS;

}

代码很长,我们这里只捡重点看。

注释1通过mReceiverResolver查询到所有符合条件的广播接收器,这些接收器是在广播注册的时候放到mReceiverResolver中的,具体可以参考广播注册过程。

注释2将注释1获得的所有广播接收器按照优先级高低存储到receivers列表中,这样receivers列表包含了所有的广播接收者(无序广播和有序广播)。

注释3处创建BroadcastRecord对象并将receivers传进去。

注释4处调用BroadcastQueue的scheduleBroadcastsLocked方法。

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java

BroadcastQueue#scheduleBroadcastsLocked()

public void scheduleBroadcastsLocked() {

if (mBroadcastsScheduled) {

return;

}

mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this)); //1

mBroadcastsScheduled = true;

}

注释1处向BroadcastHandler类型的mHandler对象发送了BROADCAST_INTENT_MSG类型的消息,这个消息在BroadcastHandler的handleMessage方法中进行处理。

BroadcastQueue#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: {

if (DEBUG_BROADCAST) Slog.v(

TAG_BROADCAST, “Received BROADCAST_INTENT_MSG”);

processNextBroadc
ast(true);

} break;

}

}

}

注释1执行processNextBroadcast方法。processNextBroadcast方法对无序广播和有序广播分别进行处理,旨在将广播发送给广播接收者,下面给出processNextBroadcast方法中对无序广播的处理部分。

BroadcastQueue#processNextBroadcast()

final void processNextBroadcast(boolean fromMsg) {

if (fromMsg) {

mBroadcastsScheduled = false;//1

}

// First, deliver any non-serialized broadcasts right away.

while (mParallelBroadcasts.size() > 0) { //2

r = mParallelBroadcasts.remove(0); //3

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, (BroadcastFilter)target, false, i); //4

}

addBroadcastToHistoryLocked®;

if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, “Done with parallel broadcast [”

  • mQueueName + "] " + r);

}

}

从前面的代码我们得知fromMsg的值为true,因此注释1处会将mBroadcastsScheduled 设置为flase,表示对于此前发来的BROADCAST_INTENT_MSG类型的消息已经处理了。

注释2处的mParallelBroadcasts列表用来存储无序广播,通过while循环将mParallelBroadcasts列表中的无序广播发送给对应的广播接收者。

注释3处获取每一个mParallelBroadcasts列表中存储的BroadcastRecord类型的r对象。

注释4处将这些r对象描述的广播发送给对应的广播接收者。

BroadcastQueue#deliverToRegisteredReceiverLocked

private void deliverToRegisteredReceiverLocked(BroadcastRecord r,

BroadcastFilter filter, boolean ordered, int index) {

try {

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®;

}

} else {

performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,

new Intent(r.intent), r.resultCode, r.resultData,

r.resultExtras, r.ordered, r.initialSticky, r.userId); //1

}

if (ordered) {

r.state = BroadcastRecord.CALL_DONE_RECEIVE;

}

} catch (RemoteException e) {

}

}

省略了很多代码,这些代码是用来检查广播发送者和广播接收者的权限。如果通过了权限的检查,则会调用注释1处的performReceiveLocked方法。

BroadcastQueue#performReceiveLocked

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) { //1

if (app.thread != null) { //2

// If we have an app thread, do the call through that so it is

// correctly ordered with other one-way calls.

try {

app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,

data, extras, ordered, sticky, sendingUser, app.repProcState); //3

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

}

}

注释1和2处的代码表示如果广播接收者所在的应用程序进程存在并且正在运行。

注释3处的代码,表示用广播接收者所在的应用程序进程来接收广播,这里app.thread指的是ActivityThread的内部类ApplicationThread。

时序图:

image

广播的接收


frameworks/base/core/java/android/app/ActivityThread.java

ApplicationThread#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);

receiver.performReceive(intent, resultCode, dataStr, extras, ordered,

sticky, sendingUser); //1

}

注释1处调用了IIntentReceiver类型的对象receiver的performReceive方法,这里实现receiver的类为LoadedApk.ReceiverDispatcher.InnerReceiver。

frameworks/base/core/java/android/app/LoadedApk.java

ReceiverDispatcher

static final class ReceiverDispatcher {

final static class InnerReceiver extends IIntentReceiver.Stub {

final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;

final LoadedApk.ReceiverDispatcher mStrongRef;

InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {

mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);

mStrongRef = strong ? rd : null;

}

@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); //1

} else {

}

}

}

注释1处调用了ReceiverDispatcher类型的rd对象的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); //1

if (intent == null) {

Log.wtf(TAG, “Null intent received”);

} else {

mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);

mStrongRef = strong ? rd : null;

}

@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); //1

} else {

}

}

}

注释1处调用了ReceiverDispatcher类型的rd对象的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); //1

if (intent == null) {

Log.wtf(TAG, “Null intent received”);

} else {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值