目錄
- 1. 前言
- 2. 正文
- 2.1 廣播接收者的動態注冊
- 2.1.1 ContextWrapper.registerReceiver() 方法
- 2.1.2 ContextImpl.registerReceiver() 方法
- 2.1.3 ContextImpl.registerReceiverInternal() 方法
- 2.1.3.1 LoadedApk.getReceiverDispatcher() 方法
- 2.1.3.2 new LoadedApk.ReceiverDispatcher() 方法
- 2.1.3.3 ActivityManagerNative.getDefault() 方法
- 2.1.4 ActivityManagerProxy.registerReceiver() 方法
- 2.1.5 ActivityManagerNative.onTransact() 方法
- 2.1.6 ActivityManagerService.registerReceiver() 方法
- 2.1.6.1 IntentResolver.addFilter()方法
- 2.2 發送普通廣播
- 2.2.1 ContextWrapper.sendBroadcast() 方法
- 2.2.2 ContextImpl.sendBroadcast() 方法
- 2.2.3 ActivityManagerProxy.broadcastIntent() 方法
- 2.2.4 ActivityManagerNative.onTransact() 方法
- 2.2.5 ActivityManagerService.broadcastIntent() 方法
- 2.2.6 ActivityManagerService.broadcastIntentLocked() 方法
- 2.2.6.1 ActivityManagerService.collectReceiverComponents() 方法
- 2.2.6.2 IntentResolver.queryIntent() 方法
- 2.2.6.3 IntentResolver.buildResolveList() 方法
- 2.2.6.4 new BroadcastRecord() 方法
- 2.2.6.5 BroadcastQueue.enqueueParallelBroadcastLocked() 方法
- 2.3 接收普通廣播
- 2.3.1 BroadcastQueue.scheduleBroadcastsLocked() 方法
- 2.3.2 BroadcastHandler.handleMessage() 方法
- 2.3.3 BroadcastQueue.processNextBroadcast() 方法
- 2.3.4 BroadcastQueue.deliverToRegisteredReceiverLocked() 方法
- 2.3.5 BroadcastQueue.performReceiveLocked() 方法
- 2.3.6 ApplicationThreadProxy.scheduleRegisteredReceiver() 方法
- 2.3.7 ApplicationThreadNative.onTransact() 方法
- 2.3.8 ApplicationThread.scheduleRegisteredReceiver() 方法
- 2.3.9 InnerReceiver.performReceive() 方法
- 2.3.10 ReceiverDispatcher.performReceive() 方法
- 2.3.11 Args.run() 方法
- 2.3.12 MyDynamicReceiver.onReceive() 方法
- 3.最后
- 4. 參考
1. 前言
BroadcastReceiver 的作業程序主要包括兩個方面的內容:
- 廣播接收者的注冊程序(靜態注冊和動態注冊);
- 廣播的發送(包括發送普通廣播、有序廣播和粘性廣播)和接收程序,
本文主要分析廣播接收者的動態注冊,普通廣播的發送和接收程序,
2. 正文
首先,看一下我們要分析的代碼:
-
定義廣播接收者,繼承
BroadcastReceiver抽象類并重寫它的onReceive()方法:public class MyDynamicReceiver extends BroadcastReceiver { private static final String TAG = "MyDynamicReceiver"; public static final String ACTION_LAUNCH_DYNAMIC = "com.wzc.receiver.LAUNCH_DYNAMIC"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); Log.d(TAG, "onReceive: receive action = " + action); if (ACTION_LAUNCH_DYNAMIC.equals(action)) { Log.d(TAG, "onReceive: do launch work..."); } } } -
點擊按鈕動態注冊以及動態注銷廣播接收者
private MyDynamicReceiver receiver; // 動態注冊廣播接收者 public void registerReceiver(View view) { if (null == receiver) { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION_LAUNCH_DYNAMIC); receiver = new MyDynamicReceiver(); registerReceiver(receiver, intentFilter); } } // 動態注銷廣播接收者 public void unregisterReceiver(View view) { if (null != receiver) { unregisterReceiver(receiver); receiver = null; } } -
點擊按鈕發送廣播
public void sendBroadcast(View view) { Intent intent = new Intent(); intent.setAction(ACTION_LAUNCH_DYNAMIC); sendBroadcast(intent); }
先點擊動態注冊廣播接收者按鈕,再點擊發送廣播按鈕,查看日志如下:
D/MyDynamicReceiver: onReceive: receive action = com.wzc.receiver.LAUNCH_DYNAMIC
D/MyDynamicReceiver: onReceive: do launch work...
如果不對廣播接收者進行動態注冊,直接點擊發送廣播按鈕,是看不到 onReceive 方法里的日志的,
現在我們開始查看相關的原始碼吧,
2.1 廣播接收者的動態注冊
2.1.1 ContextWrapper.registerReceiver() 方法
- BroadcastReceiver receiver, MyDynamicReceiver 物件
- IntentFilter filter, 添加了 action 的 IntentFilter 物件
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
這里的 ContextWrapper其實是裝飾器設計模式的應用了,類結構圖如下所示:

呼叫裝飾類 ContextWrapper 的 registerReceiver 方法,內部真正呼叫的是核心實作類 ContextImpl 的 registerReceiver 方法,所以 mBase 實際上是一個 ContextImpl 型別的物件,
2.1.2 ContextImpl.registerReceiver() 方法
- BroadcastReceiver receiver, MyDynamicReceiver 物件
- IntentFilter filter, 添加了 action 的 IntentFilter 物件
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
內部呼叫多載的 registerReceiver 方法
- BroadcastReceiver receiver, MyDynamicReceiver 物件
- IntentFilter filter, 添加了 action 的 IntentFilter 物件
- String broadcastPermission, null
- Handler scheduler, null
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
這里的 getOuterContext() 方法獲取的是 mOuterContext 物件,是通過 setOuterContext 方法賦值的,
我們這里的 ContextImpl 物件是在創建 MainActivity 的時候被初始化的,具體來說是在 ActivityThread 的 performLaunchActivity 方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
...
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
// 創建 Activity 物件
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
// 創建 ContextImpl 物件
Context appContext = createBaseContextForActivity(r, activity);
// 把 ContextImpl 物件和 Activity 物件相關聯
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.voiceInteractor);
}
return activity;
}
在 createBaseContextForActivity 方法中,呼叫 setOuterContext 方法把 activity 物件賦值給 ContextImpl 物件,
private Context createBaseContextForActivity(ActivityClientRecord r,
final Activity activity) {
ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
appContext.setOuterContext(activity);
Context baseContext = appContext;
...
return baseContext;
}
所以,getOuterContext() 方法獲取的就是 MainActivity 物件,
2.1.3 ContextImpl.registerReceiverInternal() 方法
- BroadcastReceiver receiver, MyDynamicReceiver 物件
- int userId, 通過 UserHandle 物件的 getIdentifier() 方法獲得
- IntentFilter filter, 添加了 action 的 IntentFilter 物件
- String broadcastPermission, null
- Handler scheduler, null
- Context context, MainActivity 物件
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) { // 進入此分支
// mPackageInfo 是 LoadedApk 物件,是在創建 ContextImpl 的時候賦值的,不為 null
// context 是 MainActivity 物件,不為 null
if (mPackageInfo != null && context != null) { // 進入此分支
if (scheduler == null) { // 進入此分支,對 scheduler 進行賦值
// mMainThread 是 ActivityThread 物件,通過 getHandler() 方法獲取的是它的 H mH 物件,
scheduler = mMainThread.getHandler();
}
// 獲取 InnerReceiver 物件,見[2.1.3.1]
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else { // 不會進入這里
...
}
}
try {
// 呼叫到這里,通過 AMP 經過 binder 驅動,向 AMS 發起遠程呼叫,
// ActivityManagerNative.getDefault() 見[2.1.3.3]
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
在這里思考一下,為什么我們不直接把 BroadcastReceiver 物件傳遞給 AMS,而是把通過 getReceiverDispatcher() 方法獲取的 InnerReceiver 物件傳遞給 AMS?
這是因為 BroadcastReceiver 僅僅是一個普通的 java 類而已:
public abstract class BroadcastReceiver {
public abstract void onReceive(Context context, Intent intent);
}
而廣播接收者的注冊程序是一個行程間通信的程序, BroadcastReceiver 作為一個普通的 java 類,不具備跨行程通信的能力,所以 Android 封裝了具有跨行程傳輸能力的 InnerReciver 來完成 BroadcastReceiver 不能完成的作業,
當 InnerReciver 接收到廣播時,會再呼叫到 BroadcastReceiver 的 onReceive() 方法,也就是說,InnerReciver 起到了一個中轉作用,
2.1.3.1 LoadedApk.getReceiverDispatcher() 方法
- BroadcastReceiver r, MyDynamicReceiver 物件
- Context context, MainActivity 物件
- Handler handler, ActivityThread 里的 mH 物件
- Instrumentation instrumentation, Instrumentation 物件,是在 ActivityThread 的 handleBindApplication 方法中創建的
- boolean registered, true
public final class LoadedApk {
// mReceivers 是一個 ArrayMap 集合,以 Context 為鍵,以 ArrayMap<BroadcastReceiver, ReceiverDispatcher> 為值
// 其中值又是一個 ArrayMap 集合,以 BroadcastReceiver 為鍵,以 ReceiverDispatcher 為值
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
// 獲取一個 ReceiverDispatcher 物件
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
if (registered) { // registered 為 true,進入此分支
// 根據 context 物件,從 mReceivers 里面取出 map 物件
map = mReceivers.get(context);
if (map != null) {
// 如果 map 不為 null,再根據 r 物件,取出 ReceiverDispatcher rd 物件
rd = map.get(r);
}
}
if (rd == null) {
// 創建 ReceiverDispatcher 物件,見[2.1.3.2]
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) { // 進入此分支
// 把 rd 存到 mReceivers 這個資料結構中
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
// 通過 ReceiverDispatcher 物件,獲取 InnerReceiver 物件,
return rd.getIIntentReceiver();
}
}
}
2.1.3.2 new LoadedApk.ReceiverDispatcher() 方法
- BroadcastReceiver r, MyDynamicReceiver 物件
- Context context, MainActivity 物件
- Handler activityThread, ActivityThread 里的 mH 物件
- Instrumentation instrumentation, Instrumentation 物件,是在 ActivityThread 的 handleBindApplication 方法中創建的
- boolean registered, true
public final class LoadedApk {
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;
}
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);
}
...
}
}
final IIntentReceiver.Stub mIIntentReceiver;
final BroadcastReceiver mReceiver;
final Context mContext;
final Handler mActivityThread;
final Instrumentation mInstrumentation;
final boolean mRegistered;
boolean mForgotten;
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
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);
mCurIntent = intent;
mOrdered = ordered;
}
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;
}
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
if (receiver.getPendingResult() != null) {
finish();
}
}
}
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
mIIntentReceiver = new InnerReceiver(this, !registered);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
}
IIntentReceiver getIIntentReceiver() {
return mIIntentReceiver;
}
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)) {
...
}
}
}
}
IIntentReceiver.aidl 檔案如下:
oneway interface IIntentReceiver {
void performReceive(in Intent intent, int resultCode, String data,
in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
}
類結構圖如下:

從類結構圖可以看到,
LoadedApk.ReceiverDispatcher分別持有InnerReceiver物件 和BroadcastReceiver物件,這樣LoadedApk.ReceiverDispatcher可以獲取到BroadcastReceiver物件;InnerReceiver通過弱參考持有LoadedApk.ReceiverDispatcher物件,所以InnerReceiver可以找到LoadedApk.ReceiverDispatcher物件;InnerReceiver可以獲取LoadedApk.ReceiverDispatcher物件,且LoadedApk.ReceiverDispatcher可以獲取到BroadcastReceiver物件,因此InnerReceiver可以通過LoadedApk.ReceiverDispatcher獲取BroadcastReceiver物件(這樣我們可以說LoadedApk.ReceiverDispatcher起到了連接InnerReceiver和BroadcastReceiver的作用);InnerReceiver是一個繼承于IIntentReceiver.Stub的類,所以它是一個 binder 通信的服務端類,
2.1.3.3 ActivityManagerNative.getDefault() 方法
// ActivityManagerNative 類:
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
// 因為這里客戶端和服務端不處于同一個行程,所以這個方法回傳的是 ActivityManagerProxy 物件,
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
這里采用的是區域單例技術,保證獲取到的 IActivityManager 物件總是一個物件,實際上是 ActivityManagerProxy 物件,
2.1.4 ActivityManagerProxy.registerReceiver() 方法
- IApplicationThread caller, ApplicationThread 物件,作為 binder 服務端,用于 AMS 行程向客戶端行程發起通信
- String packageName, 包名,即 “com.wzc.chapter_9”
- IIntentReceiver receiver, InnerReceiver 物件
- IntentFilter filter, 添加了 action 的 IntentFilter 物件
- String perm, null
- int userId, 通過 UserHandle 物件的 getIdentifier() 方法獲得
class ActivityManagerProxy implements IActivityManager
{
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(packageName);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
data.writeInt(userId);
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
int haveIntent = reply.readInt();
if (haveIntent != 0) {
intent = Intent.CREATOR.createFromParcel(reply);
}
reply.recycle();
data.recycle();
return intent;
}
}
這個方法仍是在客戶端行程呼叫的,
mRemote.transact() 是客戶端行程發起 binder 通信的方法,經過 binder 驅動,最后會到 binder 服務端 ActivityManagerNative的 onTransact() 方法,
2.1.5 ActivityManagerNative.onTransact() 方法
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
case REGISTER_RECEIVER_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
// 這里獲取的是 ApplicationThreadProxy 物件,是 binder 客戶端物件,
IApplicationThread app =
b != null ? ApplicationThreadNative.asInterface(b) : null;
String packageName = data.readString();
b = data.readStrongBinder();
// 這里獲取的是 IIntentReceiver.Stub.Proxy 物件,是 binder 客戶端物件,
IIntentReceiver rec
= b != null ? IIntentReceiver.Stub.asInterface(b) : null;
IntentFilter filter = IntentFilter.CREATOR.createFromParcel(data);
String perm = data.readString();
int userId = data.readInt();
// 呼叫到這里,進入 AMS,見[2.1.6]
Intent intent = registerReceiver(app, packageName, rec, filter, perm, userId);
reply.writeNoException();
if (intent != null) {
reply.writeInt(1);
intent.writeToParcel(reply, 0);
} else {
reply.writeInt(0);
}
return true;
}
}
}
ActivityManagerNative 是抽象類,registerReceiver() 是它的一個抽象方法,
ActivityManagerService 繼承了 ActivityManagerNative,實作了 registerReceiver() 這個抽象方法,
2.1.6 ActivityManagerService.registerReceiver() 方法
- IApplicationThread caller, ApplicationThreadProxy物件,作為 binder 客戶端
- String packageName, 包名,即 “com.wzc.chapter_9”
- IIntentReceiver receiver, InnerReceiver.Stub.Proxy物件
- IntentFilter filter, 添加了 action 的 IntentFilter 物件
- String perm, null
- int userId, 通過 UserHandle 物件的 getIdentifier() 方法獲得
// mRegisteredReceivers 用于記錄所有已經被注冊給廣播的 IIntentReceiver
// 鍵為 InnerReceiver.Stub.Proxy 對應的 BinderProxy 物件
// 值為 ReceiverList 物件
final HashMap<IBinder, ReceiverList> mRegisteredReceivers =
new HashMap<IBinder, ReceiverList>();
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {}
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
int callingUid;
int callingPid;
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) { // 進入此分支
// 獲取發起方的行程記錄物件
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) { // 不為 null
throw new SecurityException();
}
// 本次分析 callerApp.pkgList.containsKey(callerPackage) 為 true,所以不會進入此分支,
if (callerApp.info.uid != Process.SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
throw new SecurityException();
}
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else { // 不會進入此分支
...
}
userId = this.handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
List allSticky = null;
// Look for any matching sticky broadcasts...
Iterator actions = filter.actionsIterator();
if (actions != null) { // 進入此分支
while (actions.hasNext()) {
String action = (String)actions.next();
// 獲取 sticky intent 的串列,本次分析沒有 sticky intent,所以 allSticky 為 null,
allSticky = getStickiesLocked(action, filter, allSticky,
UserHandle.USER_ALL);
allSticky = getStickiesLocked(action, filter, allSticky,
UserHandle.getUserId(callingUid));
}
} else {
...
}
Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null; // 回傳 null
if (receiver == null) { // 不為 null
return sticky;
}
// 從 mRegisteredReceivers 獲取對應 InnerReceiver.Stub.Proxy 對應的 BinderProxy 物件 的 ReceiverList 集合
// 因為我們是首次注冊,所以這里獲取到的 rl 是 null
ReceiverList rl
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) { // 進入此分支
// 創建一個 ReceiverList 物件,
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) { // r1.app 就是 callerApp,不為 null,進入此分支
rl.app.receivers.add(rl); // 把 rl 添加到 ProcessRecord 的 receivers 串列里面保存,
} else {
...
}
// 把新建的 rl 添加到 mRegisteredReceivers 集合里面保存,
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
// 創建 BroadcastFilter 物件,BroadcastFilter 是 IntentFilter 的子類
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
// 保存在 rl 里面
rl.add(bf);
// BroadcastFilter 物件添加到 mReceiverResolver 里面,
mReceiverResolver.addFilter(bf);
if (allSticky != null) { // allSticky 為 null,不會進入此分支
...
}
return sticky;
}
}
該方法的作用:
- 創建
ReceiverList物件,它封裝了InnerReceiver.Stub.Proxy物件,并保存在mRegisteredReceivers集合里面; - 創建
BroadcastFilter物件,封裝了IntentFilter物件,ReceiverList物件,并保存在mReceiverResolver和ReceiverList集合物件里面,
類結構圖如下:

這樣,廣播接收者的注冊就完成了,
2.1.6.1 IntentResolver.addFilter()方法
- F f, BroadcastFilter 物件
public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
// 以 BroadcastFilter 為元素的串列
private final HashSet<F> mFilters = new HashSet<F>();
// 以 action 為鍵,以 BroadcastFilter[] 為值的集合
private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();
public void addFilter(F f) {
mFilters.add(f);
int numS = register_intent_filter(f, f.schemesIterator(),
mSchemeToFilter, " Scheme: "); // 沒有設定 schema,所以回傳 0
int numT = register_mime_types(f, " Type: "); // 沒有設定 type,所以回傳 0
if (numS == 0 && numT == 0) { // 進入此分支,把 F f 存放到 mActionToFilter 集合里面,
register_intent_filter(f, f.actionsIterator(),
mActionToFilter, " Action: ");
}
...
}
2.2 發送普通廣播
2.2.1 ContextWrapper.sendBroadcast() 方法
- Intent intent, 添加了 action 的 Intent 物件
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
同 2.1.1, mBase 實際上是一個 ContextImpl 型別的物件,
2.2.2 ContextImpl.sendBroadcast() 方法
- Intent intent, 添加了 action 的 Intent 物件
@Override
public void sendBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
// 呼叫到這里,見[2.2.3]
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false,
getUserId());
} catch (RemoteException e) {
}
}
由 2.1.3.3,ActivityManagerNative.getDefault() 獲取的是一個ActivityManagerProxy 物件,
2.2.3 ActivityManagerProxy.broadcastIntent() 方法
- IApplicationThread caller, ApplicationThread 物件,作為 binder 服務端,用于 AMS 行程向客戶端行程發起通信
- Intent intent, 添加了 action 的 Intent 物件
- String resolvedType, 由 intent.resolveTypeIfNeeded 得到
- IIntentReceiver resultTo, null
- int resultCode, Activity.RESULT_OK,值為 -1
- String resultData, null
- Bundle map, null
- String requiredPermission, null
- int appOp, AppOpsManager.OP_NONE,值為 -1
- boolean serialized, false,表示不是有序廣播
- boolean sticky, false,表示不是粘性廣播
- int userId, mUser.getIdentifier() 得到
class ActivityManagerProxy implements IActivityManager
{
public int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, int appOp, boolean serialized,
boolean sticky, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
data.writeInt(resultCode);
data.writeString(resultData);
data.writeBundle(map);
data.writeString(requiredPermission);
data.writeInt(appOp);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(userId);
// 呼叫到這里,見[2.2.4]
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
}
}
這個方法仍是在客戶端行程呼叫的,
mRemote.transact() 是客戶端行程發起 binder 通信的方法,經過 binder 驅動,最后會到 binder 服務端 ActivityManagerNative的 onTransact() 方法,
2.2.4 ActivityManagerNative.onTransact() 方法
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...
case BROADCAST_INTENT_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
// 這里獲取的是 ApplicationThreadProxy 物件,是 binder 客戶端物件,
IApplicationThread app =
b != null ? ApplicationThreadNative.asInterface(b) : null;
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
// 這里 resultTo 為 null,因為 b 為 null,
IIntentReceiver resultTo =
b != null ? IIntentReceiver.Stub.asInterface(b) : null;
int resultCode = data.readInt();
String resultData = data.readString();
Bundle resultExtras = data.readBundle();
String perm = data.readString();
int appOp = data.readInt();
boolean serialized = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
int userId = data.readInt();
// 呼叫到這里,見[2.2.5]
int res = broadcastIntent(app, intent, resolvedType, resultTo,
resultCode, resultData, resultExtras, perm, appOp,
serialized, sticky, userId);
reply.writeNoException();
reply.writeInt(res);
return true;
}
}
}
這里已經在 system_server 行程了,
2.2.5 ActivityManagerService.broadcastIntent() 方法
- IApplicationThread caller, ApplicationThreadProxy 物件,作為 binder 客戶端
- Intent intent, 添加了 action 的 Intent 物件
- String resolvedType, 由 intent.resolveTypeIfNeeded 得到
- IIntentReceiver resultTo, null
- int resultCode, Activity.RESULT_OK,值為 -1
- String resultData, null
- Bundle map, null
- String requiredPermission, null
- int appOp, AppOpsManager.OP_NONE,值為 -1
- boolean serialized, false,表示不是有序廣播
- boolean sticky, false,表示不是粘性廣播
- int userId, mUser.getIdentifier() 得到
public final int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, int appOp, boolean serialized, boolean sticky, int userId) {
synchronized(this) {
intent = verifyBroadcastLocked(intent);
// 獲取發起方的行程記錄物件
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(callerApp,
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo,
resultCode, resultData, map, requiredPermission, appOp, serialized, sticky,
callingPid, callingUid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
2.2.6 ActivityManagerService.broadcastIntentLocked() 方法
- ProcessRecord callerApp, 發起方的行程記錄物件
- String callerPackage, 發起方的包名
- Intent intent, 添加了 action 的 Intent 物件
- String resolvedType, 由 intent.resolveTypeIfNeeded 得到,為 null
- IIntentReceiver resultTo, null
- int resultCode, Activity.RESULT_OK,值為 -1
- String resultData, null
- Bundle map, null
- String requiredPermission, null
- int appOp, AppOpsManager.OP_NONE,值為 -1
- boolean ordered, false,表示不是有序廣播
- boolean sticky, false,表示不是粘性廣播
- int callingPid,
- int callingUid,
- int userId, mUser.getIdentifier() 得到,值為 0
// 記錄處于開啟狀態的 user
final SparseArray<UserStartedState> mStartedUsers = new SparseArray<UserStartedState>();
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {...};
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle map, String requiredPermission, int appOp,
boolean ordered, boolean sticky, int callingPid, int callingUid,
int userId) {
// ====> 1,設定廣播 flag
intent = new Intent(intent);
// Intent.FLAG_EXCLUDE_STOPPED_PACKAGES 用來控制廣播不對停止狀態的應用起作用
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
userId = handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_NON_FULL, "broadcast", callerPackage);
// 確保正在接收廣播的用戶已經開啟了;否則,跳過本次廣播發送,
// 本次分析不會進入此分支,
if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
if (callingUid != Process.SYSTEM_UID || (intent.getFlags()
& Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
return ActivityManager.BROADCAST_SUCCESS;
}
}
// ====> 2,廣播權限的驗證
// 阻止非系統代碼去發送受保護的廣播,
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID
|| callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID
|| callingAppId == Process.NFC_UID || callingUid == 0) {
// Always okay.
} else if (callerApp == null || !callerApp.persistent) { // callerApp.persistent 為 false,進入此分支
try {
if (AppGlobals.getPackageManager().isProtectedBroadcast(
intent.getAction())) { // 判斷 action 是不是受保護的,本次不會進入此分支
throw new SecurityException(msg);
} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) { // 不會進入此分支
...
}
} catch (RemoteException e) {
return ActivityManager.BROADCAST_SUCCESS;
}
}
// ====> 3,處理系統相關廣播
// 處理特殊廣播,如包移除廣播
final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
intent.getAction());
if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
|| Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
|| Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
|| Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())
|| uidRemoved) { // 本次分析沒有移除包,不會進入此分支
...
// 本次分析沒有安裝包,不會進入此分支
} else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
...
}
// 本次分析沒有時區改變,不會進入此分支
if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
}
// 如果是時間改變廣播,通知所有運行的行程,本次分析不會進入此分支,
if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
...
}
if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
}
if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
}
// ====> 4,是 sticky 廣播,就添加 sticky 廣播
if (sticky) { // sticky 為 false,不會進入此分支
...
}
int[] users;
if (userId == UserHandle.USER_ALL) {
users = mStartedUserArray;
} else { // 我們不考慮多用戶,進入此分支
users = new int[] {userId};
}
// ====> 5,查詢 receivers 和 registeredReceivers
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// Intent.FLAG_RECEIVER_REGISTERED_ONLY 表示僅僅動態注冊的廣播接收者才會被呼叫
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) { // 成立,進入此分支
// 收集靜態注冊的廣播接收者,回傳的是 List<ResolveInfo>,見[2.2.6.1]
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) { // 進入此分支
if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
...
} else { // 進入此分支
// 收集動態注冊的廣播接收者,見[2.2.6.2]
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
}
}
final boolean replacePending = // 沒有設定此 flag,所以回傳 false,
(intent.getFlags()&Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// ====> 6. 處理并行廣播
if (!ordered && NR > 0) { // 進入此分支
// 獲取到的是 BroadcastQueue mBgBroadcastQueue,它是在 AMS 構造方法中初始化的,
final BroadcastQueue queue = broadcastQueueForIntent(intent);
// 創建 BroadcastRecord 物件,見[2.2.6.4]
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
appOp, registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false, userId);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r); // false
if (!replaced) { // 進入此分支
// 將 BroadcastRecord 物件添加到并行廣播佇列,見[2.2.6.5 ]
queue.enqueueParallelBroadcastLocked(r);
// 處理廣播,見[2.3.1]
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
NR = 0;
}
// Merge into one list.
int ir = 0;
if (receivers != null) { // receivers 為 null,不會進入此分支
...
}
while (ir < NR) { // ir = 0,NR = 0,不會進入此回圈
...
}
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) { // receivers 為 null,且 resultTo 為 null,不會進入此分支
...
}
return ActivityManager.BROADCAST_SUCCESS;
}
該方法的作用:
- 設定廣播 flag;
- 廣播權限的驗證;
- 處理系統相關廣播;
- 是 sticky 廣播,就添加 sticky 廣播;
- 查詢 receivers 和 registeredReceivers;
在 2.1.6 中,通過mReceiverResolver.addFilter(bf);添加了BroadcastFiilter物件,這里通過mReceiverResolver.queryIntent獲取之前添加的BroadcastFiilter物件串列,賦值給registeredReceivers, - 處理并行廣播,
需要再次說明的是,我們本次分析的場景是發送普通廣播,所以不用關心有序廣播和粘性廣播的情況,我們有意限定了分析的范圍,這樣才不會迷失在原始碼里面,
2.2.6.1 ActivityManagerService.collectReceiverComponents() 方法
- Intent intent, 添加了 action 的 Intent 物件
- String resolvedType, 由 intent.resolveTypeIfNeeded 得到,為 null
- int callingUid,
- int[] users, 只包含了當前的用戶id的陣列,這里的用戶id的值是0
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
int callingUid, int[] users) {
List<ResolveInfo> receivers = null;
try {
HashSet<ComponentName> singleUserReceivers = null;
boolean scannedFirstReceivers = false;
for (int user : users) { // users 里只有一個元素,所以只會回圈一次,
...
// 決議清單檔案中靜態注冊的 receiver,回傳可能為 null,
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user);
if (user != 0 && newReceivers != null) { // user 為 0,不會進入此分支
...
}
if (newReceivers != null && newReceivers.size() == 0) { // 不會進入此分支
newReceivers = null;
}
if (receivers == null) { // 進入此分支
receivers = newReceivers;
} else if (newReceivers != null) { // 走第一個 if 了,不會再進入 else if
...
}
}
} catch (RemoteException ex) {
}
return receivers;
}
該方法的作用:收集靜態注冊的廣播接收者,回傳的是 List<ResolveInfo>,
本次分析沒有靜態注冊廣播接收者,所以這個方法會回傳 null,
2.2.6.2 IntentResolver.queryIntent() 方法
- Intent intent, 添加了 action 的 Intent 物件
- String resolvedType, null
- boolean defaultOnly, false
- int userId, 0
public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
// 以 action 為鍵,以 BroadcastFilter[] 為值的集合
private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
int userId) {
String scheme = intent.getScheme(); // 回傳 null
ArrayList<R> finalList = new ArrayList<R>();
F[] firstTypeCut = null;
F[] secondTypeCut = null;
F[] thirdTypeCut = null;
F[] schemeCut = null;
if (resolvedType != null) { // resolvedType 為 null,不會進入此分支
...
}
if (scheme != null) { // scheme 為 null,不會進入此分支
...
}
if (resolvedType == null && scheme == null && intent.getAction() != null) {
firstTypeCut = mActionToFilter.get(intent.getAction());
}
FastImmutableArraySet<String> categories = getFastIntentCategories(intent); // 回傳 null
if (firstTypeCut != null) {
// 見[2.2.6.3]
buildResolveList(intent, categories, debug, defaultOnly,
resolvedType, scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) { // 進不去
...
}
if (thirdTypeCut != null) { // 進不去
...
}
if (schemeCut != null) { // 進不去
...
}
sortResults(finalList);
return finalList;
}
}
該方法的作用:從 mActionToFilter 獲取 BroadcastFiilter 物件串列,
2.2.6.3 IntentResolver.buildResolveList() 方法
- Intent intent, 添加了 action 的 Intent 物件
- FastImmutableArraySet categories, null
- boolean debug, false
- boolean defaultOnly, false
- String resolvedType, null
- String scheme, null
- F[] src, BroadcastFilter[] 物件
- List dest, 容器引數 List 物件
- int userId, 0
public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
// 以 action 為鍵,以 BroadcastFilter[] 為值的集合
private final ArrayMap<String, F[]> mActionToFilter = new ArrayMap<String, F[]>();
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
boolean debug, boolean defaultOnly,
String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
final String action = intent.getAction(); // "com.wzc.receiver.LAUNCH_DYNAMIC"
final Uri data = intent.getData(); // null
final String packageName = intent.getPackage(); // null
final boolean excludingStopped = intent.isExcludingStopped(); // true
final Printer logPrinter;
final PrintWriter logPrintWriter;
final int N = src != null ? src.length : 0;
boolean hasNonDefaults = false;
int i;
F filter;
for (i=0; i<N && (filter=src[i]) != null; i++) {
int match;
if (excludingStopped && isFilterStopped(filter, userId)) {
continue;
}
if (packageName != null && !isPackageForFilter(packageName, filter)) {
continue;
}
match = filter.match(action, resolvedType, scheme, data, categories, TAG);
if (match >= 0) {
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
final R oneResult = newResult(filter, match, userId);
if (oneResult != null) {
dest.add(oneResult);
}
} else {
hasNonDefaults = true;
}
} else {
...
}
}
}
}
該方法的作用是:對 BroadcastFilter 物件陣列進行一些過濾,通過容器引數回傳符合條件的 BroadcastFilter 物件,
2.2.6.4 new BroadcastRecord() 方法
final class BroadcastRecord extends Binder {
final Intent intent; // 產生廣播的原始 Intent
final ComponentName targetComp; // 設定在 Intent 上的原始的組件名物件
final ProcessRecord callerApp; // 發送廣播的行程
final String callerPackage; // 發送方的包名
final int callingPid; // 發起方的pid
final int callingUid; // 發起方的uid
final boolean ordered; // 是否是有序廣播
final boolean sticky; // 是否是粘性廣播
final boolean initialSticky;
final int userId;
final String resolvedType; // mime type
final String requiredPermission; // 廣播權限
final int appOp;
final List receivers; // 廣播接收器,包括動態注冊(BroadcastFilter)和靜態注冊(ResolveInfo)
IIntentReceiver resultTo; // null
long dispatchTime; // 廣播分發時間點
long dispatchClockTime; // the clock time the dispatch started
long receiverTime; // 當前 receiver 開始處理時間點
long finishTime; // 廣播處理完成時間點.
int resultCode; // current result code value.
String resultData; // current result data value.
Bundle resultExtras; // current result extra data values.
boolean resultAbort; // current result abortBroadcast value.
int nextReceiver; // next receiver to be executed.
IBinder receiver; // who is currently running, null if none.
int state;
int anrCount; // has this broadcast record hit any ANRs?
BroadcastQueue queue; // 處理廣播的佇列
static final int IDLE = 0;
static final int APP_RECEIVE = 1;
static final int CALL_IN_RECEIVE = 2;
static final int CALL_DONE_RECEIVE = 3;
static final int WAITING_SERVICES = 4;
BroadcastFilter curFilter;
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.
BroadcastRecord(BroadcastQueue _queue,
Intent _intent, ProcessRecord _callerApp, String _callerPackage,
int _callingPid, int _callingUid, String _resolvedType, String _requiredPermission,
int _appOp, List _receivers, IIntentReceiver _resultTo, int _resultCode,
String _resultData, Bundle _resultExtras, boolean _serialized,
boolean _sticky, boolean _initialSticky,
int _userId) {
queue = _queue;
intent = _intent;
targetComp = _intent.getComponent();
callerApp = _callerApp;
callerPackage = _callerPackage;
callingPid = _callingPid;
callingUid = _callingUid;
resolvedType = _resolvedType;
requiredPermission = _requiredPermission;
appOp = _appOp;
receivers = _receivers;
resultTo = _resultTo;
resultCode = _resultCode;
resultData = _resultData;
resultExtras = _resultExtras;
ordered = _serialized;
sticky = _sticky;
initialSticky = _initialSticky;
userId = _userId;
nextReceiver = 0;
state = IDLE;
}
}
可以看到,BroadcastRecord 是繼承于 Binder 類的,
2.2.6.5 BroadcastQueue.enqueueParallelBroadcastLocked() 方法
public final class BroadcastQueue {
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
}
}
該方法的作用:把 BroadcastRecord r 物件添加到 mParallelBroadcasts 串列而已,
2.3 接收普通廣播
2.3.1 BroadcastQueue.scheduleBroadcastsLocked() 方法
public final class BroadcastQueue {
boolean mBroadcastsScheduled = false;
final BroadcastHandler mHandler;
BroadcastQueue(ActivityManagerService service, Handler handler,
String name, long timeoutPeriod, boolean allowDelayBehindServices) {
mService = service;
mHandler = new BroadcastHandler(handler.getLooper());
...
}
public void scheduleBroadcastsLocked() {
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
}
該方法的作用是:通過 mHandler 發送一個 what 為 BROADCAST_INTENT_MSG ,object 為 BroadcastQueue 物件的訊息,
mHandler 是在 BroadcastQueue 的構造方法中初始化的:mHandler = new BroadcastHandler(handler.getLooper()),需要特別說明的是,這里的 hanlder.getLooper() 是一個名字 "ActivityManager" 為子執行緒的 Looper 物件,因為這個 Looper 物件來自于 ActivityManagerService 的 mHandlerThread.getLooper(),
public final class ActivityManagerService extends ActivityManagerNative {
static final String TAG = "ActivityManager";
final ServiceThread mHandlerThread;
final MainHandler mHandler;
BroadcastQueue mFgBroadcastQueue;
BroadcastQueue mBgBroadcastQueue;
public ActivityManagerService(Context systemContext) {
mContext = systemContext;
mSystemThread = ActivityThread.currentActivityThread();
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
mHandler = new MainHandler(mHandlerThread.getLooper());
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", BROADCAST_FG_TIMEOUT, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", BROADCAST_BG_TIMEOUT, true);
}
}
所以,發送訊息是在 system_server 行程的主執行緒,接收訊息的地方是在 system_server 行程的子執行緒里面了,
2.3.2 BroadcastHandler.handleMessage() 方法
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: {
// 見[2.3.3]
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
}
}
};
2.3.3 BroadcastQueue.processNextBroadcast() 方法
- boolean fromMsg, true
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
if (fromMsg) {
// 重置 mBroadcastsScheduled 標記,
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);
// 呼叫到這里,見[2.3.4]
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false);
}
addBroadcastToHistoryLocked(r);
}
// 當正在等待一個行程被拉起來處理下一個廣播,mPendingBroadcast 就不為 null,
// 本次分析不涉及跨行程,所以 mPendingBroadcast 為 null,
if (mPendingBroadcast != null) { // 本次分析不進入此分支
...
}
boolean looped = false;
do {
if (mOrderedBroadcasts.size() == 0) { // 本次分析沒有有序廣播,所以進入此分支,
mService.scheduleAppGcsLocked();
if (looped) {
mService.updateOomAdjLocked();
}
return; // 結束本方法了,
}
...
} while (r == null);
// ... 省略與本次分析無關的代碼,
}
}
該方法的作用:取出廣播佇列中的元素,傳遞給注冊的廣播接收者,
2.3.4 BroadcastQueue.deliverToRegisteredReceiverLocked() 方法
- BroadcastRecord r, BroadcastRecord 物件
- BroadcastFilter filter, BroadcastFilter 物件,存盤了廣播接收者的資訊
- boolean ordered, false,表示不是有序廣播
private final void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered) {
boolean skip = false;
if (filter.requiredPermission != null) { // 不進入此分支
...
}
if (!skip && r.requiredPermission != null) { // 不進入此分支
...
}
if (r.appOp != AppOpsManager.OP_NONE) { // 不進入此分支
...
}
if (!skip) {
skip = !mService.mIntentFirewall.checkBroadcast(r.intent, r.callingUid,
r.callingPid, r.resolvedType, filter.receiverList.uid);
}
if (filter.receiverList.app == null || filter.receiverList.app.crashing) {
skip = true;
}
if (!skip) {
...
try {
// 呼叫到這里,見[2.3.5]
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
} catch (RemoteException e) {
}
}
}
該方法的作用:進行必要的權限驗證,然后執行廣播接收程序,
這里為了弄清楚 performReceiveLocked 方法的引數,我們再次查看一下類結構圖:

2.3.5 BroadcastQueue.performReceiveLocked() 方法
- ProcessRecord app, filter.receiverList.app = 發起方的行程記錄物件
- IIntentReceiver receiver, filter.receiverList.receiver = InnerReceiver.Stub.Proxy物件
- Intent intent, new Intent(r.intent) = 添加了 action 的 Intent 物件
- int resultCode, r.resultCode = Activity.RESULT_OK,值為 -1
- String data, r.resultData = null
- Bundle extras, r.resultExtras = null
- boolean ordered, r.ordered = false
- boolean sticky, r.initialSticky = false
- int sendingUser, r.userId = 0
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) {
// app.thread 是 IApplicationThread 物件,實際上是 ApplicationThreadProxy 物件,是 binder 客戶端物件,
if (app.thread != null) {
// 開始向 IApplicationThread binder 服務端物件發起請求服務,見[2.3.6]
app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
data, extras, ordered, sticky, sendingUser, app.repProcState);
} else {
...
}
} else {
...
}
}
2.3.6 ApplicationThreadProxy.scheduleRegisteredReceiver() 方法
class ApplicationThreadProxy implements IApplicationThread {
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(receiver.asBinder());
intent.writeToParcel(data, 0);
data.writeInt(resultCode);
data.writeString(dataStr);
data.writeBundle(extras);
data.writeInt(ordered ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(sendingUser);
data.writeInt(processState);
mRemote.transact(SCHEDULE_REGISTERED_RECEIVER_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
}
這個方法是運行在 system_server 行程的,
mRemote.transact() 是 system_server 行程發起 binder 通信的方法,經過 binder 驅動,最后會到 binder 服務端 ApplicationThreadNative的 onTransact() 方法,
2.3.7 ApplicationThreadNative.onTransact() 方法
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
case SCHEDULE_REGISTERED_RECEIVER_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
// 這里獲取的是 IIntentReceiver.Stub.Proxy 物件,是 binder 客戶端物件
IIntentReceiver receiver = IIntentReceiver.Stub.asInterface(
data.readStrongBinder());
Intent intent = Intent.CREATOR.createFromParcel(data);
int resultCode = data.readInt();
String dataStr = data.readString();
Bundle extras = data.readBundle();
boolean ordered = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
int sendingUser = data.readInt();
int processState = data.readInt();
scheduleRegisteredReceiver(receiver, intent,
resultCode, dataStr, extras, ordered, sticky, sendingUser, processState);
return true;
}
}
}
ApplicationThreadNative 是一個抽象類,scheduleRegisteredReceiver 是它的一個抽象方法,所以要尋找 scheduleRegisteredReceiver 的實作,實作實在 ApplicationThread 類里面,
ApplicationThread 是 ActivityThread 類的私有內部類,
2.3.8 ApplicationThread.scheduleRegisteredReceiver() 方法
- IIntentReceiver receiver, IIntentReceiver.Stub.Proxy 物件,是 binder 客戶端物件
- Intent intent, 添加了 action 的 Intent 物件
- int resultCode, Activity.RESULT_OK,值為 -1
- String dataStr, null
- Bundle extras, null
- boolean ordered, false
- boolean sticky, false
- int sendingUser, 0
- int processState
public final class ActivityThread {
private class ApplicationThread extends ApplicationThreadNative {
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
}
}
這個方法是運行在客戶端行程的 binder 執行緒池里面,
receiver 是 IIntentReceiver.Stub.Proxy 物件,是 binder 客戶端物件,
呼叫 receiver.performReceive 方法,會經過 binder 驅動,呼叫到發起方行程的 IIntentReceiver.Stub 物件,即 InnerReceiver物件的 performReceive 方法,可以查看注冊程序的 2.1.3 部分,并且在 2.1.3.2 部分繪制了 InnerReceiver,BroadcastReceiver以及ReceiverDispatcher的類結構圖,
2.3.9 InnerReceiver.performReceive() 方法
- Intent intent, 添加了 action 的 Intent 物件
- int resultCode, Activity.RESULT_OK,值為 -1
- String data, null
- Bundle extras, null
- boolean ordered, false
- boolean sticky, false
- int sendingUser, 0
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;
}
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) {
// 呼叫到這里,見[2.3.10]
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
...
}
}
}
2.3.10 ReceiverDispatcher.performReceive() 方法
- Intent intent, 添加了 action 的 Intent 物件
- int resultCode, Activity.RESULT_OK,值為 -1
- String data, null
- Bundle extras, null
- boolean ordered, false
- boolean sticky, false
- int sendingUser, 0
public final class LoadedApk {
static final class ReceiverDispatcher {
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
// 把一系列引數封裝在 Args 物件里面,是一個 Runnable 物件,
Args args = new Args(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
// mActivityThread 就是 ActivityThread 類的 mH 物件,
if (!mActivityThread.post(args)) {
...
}
}
}
}
mActivityThread.post 方法把訊息在主執行緒執行,
2.3.11 Args.run() 方法
Args 是 ReceiverDispatcher 的內部類,因此它可以獲取到 ReceiverDispatcher 的成員,
static final class ReceiverDispatcher {
final BroadcastReceiver mReceiver;
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
}
final class Args extends BroadcastReceiver.PendingResult implements Runnable {
private Intent mCurIntent;
private final boolean mOrdered;
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);
mCurIntent = intent;
mOrdered = ordered;
}
public void run() {
// mReceiver 就是 MyDynamicReceiver 物件
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
final Intent intent = mCurIntent;
mCurIntent = null;
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
// 呼叫 MyDynamicReceiver 物件的 onReceive 方法
receiver.onReceive(mContext, intent);
} catch (Exception e) {
...
}
...
}
}
}
2.3.12 MyDynamicReceiver.onReceive() 方法
public class MyDynamicReceiver extends BroadcastReceiver {
private static final String TAG = "MyDynamicReceiver";
public static final String ACTION_LAUNCH_DYNAMIC = "com.wzc.receiver.LAUNCH_DYNAMIC";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "onRecei
ve: receive action = " + action);
if (ACTION_LAUNCH_DYNAMIC.equals(action)) {
Log.d(TAG, "onReceive: do launch work...");
}
}
}
到這里,就收到了廣播了,
3.最后
本文到這里就結束了,希望可以幫助到大家,
4. 參考
-
Android Broadcast廣播機制分析-袁輝輝
-
觀察者模式深入探討
Android 里的廣播和廣播接收者對應于被觀察者和觀察者角色,是觀察者模式的典型應用,
-
Android:多用戶的UserHandle的東東記錄
這篇文章解決了對 UerHandle 類中的 uid,userid,appid 不清楚的問題, -
四大組件之BroadcastRecord-袁輝輝
-
品茗論道說廣播(Broadcast內部機制講解)(上)
-
品茗論道說廣播(Broadcast內部機制講解)(下)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/392153.html
標籤:其他
