Android R 廣播發送流程
阿新 • • 發佈:2020-12-27
Android R 廣播發送流程
本篇基於R版本原始碼11.0.0_r1分析廣播的傳送流程:通常我們傳送廣播是直接在Activity中呼叫sendBroadcast(Intent intent)(這裡以最簡單的廣播發送為例,當然還可以增加許可權引數,限定接受使用者,傳送有序廣播或者粘性廣播等),而Activity的繼承關係:Activity --> ContextThemeWrapper --> ContextWrapper --> Context,其中Context為抽象類,其實現類為ContextImpl(在Activity建立的時候ActivityThread會通過ContextImpl.createActivityContext建立Activity的ContextImpl),所以實際上是呼叫ContextImpl.sendBroadcast,接下來我們看具體的程式碼流程(由於篇幅有限,所以部分地方只貼關鍵流程和程式碼):
1.1 ContextImpl.java:sendBroadcast
@Override public void sendBroadcast(Intent intent) { warnIfCallingFromSystemProcess(); String resolvedType = intent.resolveTypeIfNeeded(getContentResolver()); try { intent.prepareToLeaveProcess(this); // 跨程序呼叫ActivityManagerService.broadcastIntentWithFeature, 注意這裡的mMainThread.getApplicationThread()即ApplicationThread,它是應用程序和system server程序之間溝通的橋樑 ActivityManager.getService().broadcastIntentWithFeature( mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType, null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false, getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
1.2 ActivityManagerService.java:broadcastIntentLocked(broadcastIntentWithFeature會直接呼叫broadcastIntentLocked,所以這裡省略broadcastIntentWithFeature程式碼)
final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, @Nullable String callerFeatureId, 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 realCallingUid, int realCallingPid, int userId, boolean allowBackgroundActivityStarts, @Nullable int[] broadcastWhitelist) { intent = new Intent(intent); // 預設情況下廣播不傳送給stopped狀態的應用 // By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES); // 如果system server還未ready而且未新增BOOT_UPGRADE Flag,則該廣播只有動態註冊的廣播接收器才能接受 // If we have not finished booting, don't allow this to launch new processes. if (!mProcessesReady && (intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } // 廣播的Action final String action = intent.getAction(); // Verify that protected broadcasts are only being sent by system code, // and that system code is only sending protected broadcasts. final boolean isProtectedBroadcast; try { // 通過PackageManager查詢所有受保護的廣播 isProtectedBroadcast = AppGlobals.getPackageManager().isProtectedBroadcast(action); } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); return ActivityManager.BROADCAST_SUCCESS; } final boolean isCallerSystem; // 特定UID或者persistent程序認為是系統程序 switch (UserHandle.getAppId(callingUid)) { case ROOT_UID: case SYSTEM_UID: case PHONE_UID: case BLUETOOTH_UID: case NFC_UID: case SE_UID: case NETWORK_STACK_UID: isCallerSystem = true; break; default: isCallerSystem = (callerApp != null) && callerApp.isPersistent(); break; } // First line security check before anything else: stop non-system apps from // sending protected broadcasts. if (!isCallerSystem) { if (isProtectedBroadcast) { // 非系統程序禁止傳送受保護的廣播 String msg = "Permission Denial: not allowed to send broadcast " + action + " from pid=" + callingPid + ", uid=" + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); } } if (action != null) { if (getBackgroundLaunchBroadcasts().contains(action)) { if (DEBUG_BACKGROUND_CHECK) { Slog.i(TAG, "Broadcast action " + action + " forcing include-background"); } // 隱式廣播白名單裡的廣播可以傳送給靜態廣播接收器(無論應用程序後臺是否存活) intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); } } // Add to the sticky list if requested. if (sticky) { // 粘性廣播不能新增許可權 if (requiredPermissions != null && requiredPermissions.length > 0) { Slog.w(TAG, "Can't broadcast sticky intent " + intent + " and enforce permissions " + Arrays.toString(requiredPermissions)); return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION; } // 粘性廣播不能指定Component if (intent.getComponent() != null) { throw new SecurityException( "Sticky broadcasts can't target a specific component"); } ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); // 查詢指定使用者的ArrayMap, 如果沒有就新建一個 if (stickies == null) { stickies = new ArrayMap<>(); mStickyBroadcasts.put(userId, stickies); } ArrayList<Intent> list = stickies.get(intent.getAction()); // 查詢指定action的Intent列表,如果沒有就建立一個 if (list == null) { list = new ArrayList<>(); stickies.put(intent.getAction(), list); } final int stickiesCount = list.size(); int i; for (i = 0; i < stickiesCount; i++) { if (intent.filterEquals(list.get(i))) { // 如果這個粘性廣播Intent已經存在,則更新為最新的 // This sticky already exists, replace it. list.set(i, new Intent(intent)); break; } } // 否則新增到列表最後 if (i >= stickiesCount) { list.add(new Intent(intent)); } } // 重點來了,查詢廣播接收器 // Figure out who all will receive this broadcast. // 靜態註冊的廣播接收器 List receivers = null; // 動態註冊的廣播接收器 List<BroadcastFilter> registeredReceivers = null; // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { // 如果未禁止僅傳送給動態接受器, 則收集靜態接受器1.2.1 receivers = collectReceiverComponents( intent, resolvedType, callingUid, users, broadcastWhitelist); } if (intent.getComponent() == null) { // 如果沒有指定Component, 則收集動態接收器1.2.2 registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId); }
1.2.1 ActivityManagerService.java:collectReceiverComponents
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
int callingUid, int[] users, int[] broadcastWhitelist) {
// TODO: come back and remove this assumption to triage all broadcasts
int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
List<ResolveInfo> receivers = null;
try {
HashSet<ComponentName> singleUserReceivers = null;
boolean scannedFirstReceivers = false;
for (int user : users) {
// 通過PackageManagerService查詢當前使用者下所有AndroidManifest.xml中的靜態廣播接收器
List<ResolveInfo> newReceivers = AppGlobals.getPackageManager()
.queryIntentReceivers(intent, resolvedType, pmFlags, user).getList();
if (user != UserHandle.USER_SYSTEM && newReceivers != null) {
// If this is not the system user, we need to check for
// any receivers that should be filtered out.
for (int i=0; i<newReceivers.size(); i++) {
ResolveInfo ri = newReceivers.get(i);
// 該應用只希望接受系統使用者下的廣播
if ((ri.activityInfo.flags&ActivityInfo.FLAG_SYSTEM_USER_ONLY) != 0) {
newReceivers.remove(i);
i--;
}
}
}
if (newReceivers != null && newReceivers.size() == 0) {
newReceivers = null;
}
if (receivers == null) {
receivers = newReceivers;
}
}
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
// 如果靜態廣播白名單裡找不到該應用程式,則禁止應用接受該靜態註冊的廣播接收器
if (receivers != null && broadcastWhitelist != null) {
for (int i = receivers.size() - 1; i >= 0; i--) {
final int receiverAppId = UserHandle.getAppId(
receivers.get(i).activityInfo.applicationInfo.uid);
if (receiverAppId >= Process.FIRST_APPLICATION_UID
&& Arrays.binarySearch(broadcastWhitelist, receiverAppId) < 0) {
receivers.remove(i);
}
}
}
return receivers;
}
1.2.2 IntentResolver.java:queryIntent
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
int userId) {
ArrayList<R> finalList = new ArrayList<R>();
F[] firstTypeCut = null;
F[] secondTypeCut = null;
F[] thirdTypeCut = null;
F[] schemeCut = null;
// If the intent does not specify any data -- either a MIME type or
// a URI -- then we will only be looking for matches against empty
// data.
// 如果廣播未指定MIME type或者URI則只用關注firstTypeCut的獲取,它是從mActionToFilter獲取的,而mActionToFilter是在動態註冊時新增的,具體新增過程我們會在廣播註冊流程中介紹
if (resolvedType == null && scheme == null && intent.getAction() != null) {
firstTypeCut = mActionToFilter.get(intent.getAction());
if (debug) Slog.v(TAG, "Action list: " + Arrays.toString(firstTypeCut));
}
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
if (firstTypeCut != null) {
// 構建動態廣播接收器列表的過程也留到廣播註冊流程中介紹
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly, resolvedType,
scheme, schemeCut, finalList, userId);
}
filterResults(finalList);
sortResults(finalList);
return finalList;
}
1.3 ActivityManagerService.java:broadcastIntentLocked(接1.2)
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
// 處理動態非有序廣播
if (!ordered && NR > 0) {
// 根據Intent查詢廣播佇列 1.3.1
final BroadcastQueue queue = broadcastQueueForIntent(intent);
// 根據廣播佇列和intent等引數構造BroadcastRecord 1.3.2
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage,
callerFeatureId, callingPid, callingUid, callerInstantApp, resolvedType,
requiredPermissions, appOp, brOptions, ***registeredReceivers***, resultTo,
resultCode, resultData, resultExtras, ordered, sticky, false, userId,
allowBackgroundActivityStarts, timeoutExempt);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending
&& (queue.replaceParallelBroadcastLocked(r) != null);
// Note: We assume resultTo is null for non-ordered broadcasts.
if (!replaced) {
// 入隊並行廣播列表mParallelBroadcasts,並記錄入隊時間
queue.enqueueParallelBroadcastLocked(r);
// 開始分發動態非有序廣播 1.4
queue.scheduleBroadcastsLocked();
}
registeredReceivers = null;
// 如果已處理完或者沒有動態接受者則NR為0
NR = 0;
}
1.3.1 ActivityManagerService.java:broadcastQueueForIntent
BroadcastQueue broadcastQueueForIntent(Intent intent) {
// Intent.ACTION_LOCKED_BOOT_COMPLETED和Intent.ACTION_BOOT_COMPLETED這種長週期廣播專屬佇列, 預設不支援
if (isOnOffloadQueue(intent.getFlags())) {
if (DEBUG_BROADCAST_BACKGROUND) {
Slog.i(TAG_BROADCAST,
"Broadcast intent " + intent + " on offload queue");
}
return mOffloadBroadcastQueue;
}
// 根據Flag來確定是走前臺廣播佇列還是後臺廣播佇列 1.3.1.1,二者在ActivityManagerService初始化時建立
final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
"Broadcast intent " + intent + " on "
+ (isFg ? "foreground" : "background") + " queue");
return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}
1.3.1.1 ActivityManagerService.java:建立mFgBroadcastQueue和mBgBroadcastQueue
// How long we allow a receiver to run before giving up on it.
// 前臺廣播超時時間為10s
static final int BROADCAST_FG_TIMEOUT = 10*1000;
// 後臺廣播超時時間為60s
static final int BROADCAST_BG_TIMEOUT = 60*1000;
// Note: This method is invoked on the main thread but may need to attach various
// handlers to other threads. So take care to be explicit about the looper.
public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
// Broadcast policy parameters
final BroadcastConstants foreConstants = new BroadcastConstants(
Settings.Global.BROADCAST_FG_CONSTANTS);
foreConstants.TIMEOUT = BROADCAST_FG_TIMEOUT;
final BroadcastConstants backConstants = new BroadcastConstants(
Settings.Global.BROADCAST_BG_CONSTANTS);
backConstants.TIMEOUT = BROADCAST_BG_TIMEOUT;
// 構造前臺佇列和後臺佇列 1.3.1.2
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", foreConstants, false);
mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
"background", backConstants, true);
1.3.1.2 BroadcastQueue.java:BroadcastQueue
/**
* Lists of all active broadcasts that are to be executed immediately
* (without waiting for another broadcast to finish). Currently this only
* contains broadcasts to registered receivers, to avoid spinning up
* a bunch of processes to execute IntentReceiver components. Background-
* and foreground-priority broadcasts are queued separately.
*/
// 並行廣播列表:用來記錄所有動態非有序廣播
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
BroadcastQueue(ActivityManagerService service, Handler handler,
String name, BroadcastConstants constants, boolean allowDelayBehindServices) {
mService = service;
mHandler = new BroadcastHandler(handler.getLooper());
mQueueName = name;
mDelayBehindServices = allowDelayBehindServices;
mConstants = constants;
// 建立BroadcastDispatcher記錄並處理有序廣播 1.3.1.3
mDispatcher = new BroadcastDispatcher(this, mConstants, mHandler, mService);
}
// 加入並行廣播接收器列表
public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
mParallelBroadcasts.add(r);
enqueueBroadcastHelper(r);
}
// 通過BroadcastDispatcher加入序列即有序廣播接收器列表
public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
mDispatcher.enqueueOrderedBroadcastLocked(r);
enqueueBroadcastHelper(r);
}
1.3.1.3 BroadcastDispatcher.java
/**
* Manages ordered broadcast delivery, applying policy to mitigate the effects of
* slow receivers.
*/
public class BroadcastDispatcher {
// Usual issuance-order outbound queue
// 有序廣播列表
private final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
// General deferrals not holding up alarms
private final ArrayList<Deferrals> mDeferredBroadcasts = new ArrayList<>();
// Deferrals that *are* holding up alarms; ordered by alarm dispatch time
private final ArrayList<Deferrals> mAlarmBroadcasts = new ArrayList<>();
// Next outbound broadcast, established by getNextBroadcastLocked()
private BroadcastRecord mCurrentBroadcast;
/**
* Constructed & sharing a lock with its associated BroadcastQueue instance
*/
public BroadcastDispatcher(BroadcastQueue queue, BroadcastConstants constants,
Handler handler, Object lock) {
mQueue = queue;
mConstants = constants;
mHandler = handler;
mLock = lock;
}
// 加入有序廣播列表
void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
mOrderedBroadcasts.add(r);
}
}
1.3.2 BroadcastRecord.java
final class BroadcastRecord extends Binder {
// 當前廣播的Intent
final Intent intent; // the original intent that generated us
// 根據Intent得到的目標Component
final ComponentName targetComp; // original component name set on the intent
// 傳送廣播的程序
final ProcessRecord callerApp; // process that sent this
// 是否為有序廣播
final boolean ordered; // serialize the send to receivers?
// 是否為sticky廣播
final boolean sticky; // originated from existing sticky data?
// 廣播接收者,包括靜態註冊和動態註冊的廣播接收器
final List receivers; // contains BroadcastFilter and ResolveInfo
// 記錄每個廣播接收器的接收情況
final int[] delivery; // delivery state of each receiver
// 記錄每個廣播接收器的處理時間
final long[] duration; // duration a receiver took to process broadcast
// 入列時間
long enqueueClockTime; // the clock time the broadcast was enqueued
// 開始分發的時間
long dispatchTime; // when dispatch started on this set of receivers
long dispatchClockTime; // the clock time the dispatch started
// 開始超時的時間
long receiverTime; // when current receiver started for timeouts.
// 結束的時間
long finishTime; // when we finished the broadcast.
// 下一個即將被處理的廣播接收器
int nextReceiver; // next receiver to be executed.
// 所屬的廣播佇列
BroadcastQueue queue; // the outbound queue handling this broadcast
1.4 BroadcastQueue.java:開始分發廣播
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
// 如果處理過了就直接返回
if (mBroadcastsScheduled) {
return;
}
// 通過Handler傳送處理廣播的訊息
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
private final class BroadcastHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT_MSG: {
// 處理廣播訊息
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
// 處理超時訊息
broadcastTimeoutLocked(true);
}
} break;
}
}
}
final void processNextBroadcast(boolean fromMsg) {
synchronized (mService) {
// 開始依次處理每個廣播接收器 1.4.1
processNextBroadcastLocked(fromMsg, false);
}
}
1.4.1 BroadcastQueue.java:processNextBroadcastLocked
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
BroadcastRecord r;
if (fromMsg) {
mBroadcastsScheduled = false;
}
// 先處理並行廣播
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
// 依次取出每條廣播,並記錄分發時間
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
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);
// 該並行廣播的接收器都是動態註冊的即BroadcastFilter,強轉之後傳遞給deliverToRegisteredReceiverLocked 1.4.2
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
// 廣播處理完之後記錄結束時間並將BroadcastRecord加入mBroadcastHistory列表
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
1.4.2 BroadcastQueue.java:deliverToRegisteredReceiverLocked
private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
BroadcastFilter filter, boolean ordered, int index) {
// 記錄傳遞狀態
r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;
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(r);
}
} else {
// 記錄廣播接收時間
r.receiverTime = SystemClock.uptimeMillis();
maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
// 準備切回廣播註冊者程序接收並處理廣播 1.4.3
performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
new Intent(r.intent), r.resultCode, r.resultData,
r.resultExtras, r.ordered, r.initialSticky, r.userId);
// parallel broadcasts are fire-and-forget, not bookended by a call to
// finishReceiverLocked(), so we manage their activity-start token here
if (r.allowBackgroundActivityStarts && !r.ordered) {
postActivityStartTokenRemoval(filter.receiverList.app, r);
}
}
}
1.4.3 BroadcastQueue.java:deliverToRegisteredReceiverLocked
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) {
// 如果動態接收者的ProcessRecord不為null而且其ApplicationThread不為null則切換到應用端處理 1.4.4
// 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.getReportedProcState());
} catch (RemoteException ex) {
// Failed to call into the process. It's either dying or wedged. Kill it gently.
synchronized (mService) {
Slog.w(TAG, "Can't deliver broadcast to " + app.processName
+ " (pid " + app.pid + "). Crashing it.");
app.scheduleCrash("can't deliver broadcast");
}
throw ex;
}
} else {
// Application has died. Receiver doesn't exist.
throw new RemoteException("app.thread must not be null");
}
} else {
// 否則直接回調IIntentReceiver.performReceive
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
1.4.4 ActivityThread.java:ApplicationThread.scheduleRegisteredReceiver
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
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);
}
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
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);
// 可以看到這裡實際上跟1.4.3 中 app為null的時候走的邏輯是一樣的 1.5
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
1.5 LoadedApk.java:ReceiverDispatcher.InnerReceiver
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
// 註冊廣播時建立的
rd = mDispatcher.get();
}
if (rd != null) {
// 呼叫ReceiverDispatcher.performReceive 1.5.1
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 = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false);
}
// 未註冊的廣播直接finish
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}
1.5.1 LoadedApk.java:ReceiverDispatcher
static final class ReceiverDispatcher {
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);
// post一個Runnale到主執行緒上執行,這個Runnable也是由ReceiverDispatcher的內部類提供的 1.5.2
if (intent == null || !mActivityThread.post(args.getRunnable())) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManager.getService();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
}
1.5.2 LoadedApk.java:ReceiverDispatcher.Args
final class Args extends BroadcastReceiver.PendingResult {
private Intent mCurIntent;
private final boolean mOrdered;
private boolean mDispatched;
private boolean mRunCalled;
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 final Runnable getRunnable() {
return () -> {
final BroadcastReceiver receiver = mReceiver;
final boolean ordered = mOrdered;
final IActivityManager mgr = ActivityManager.getService();
final Intent intent = mCurIntent;
if (intent == null) {
Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
+ (mRunCalled ? ", run() has already been called" : ""));
}
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也是在註冊廣播時賦予的
receiver.onReceive(mContext, intent);
}
if (receiver.getPendingResult() != null) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
};
}
}