上一篇文章已經(jīng)介紹了廣播的類型蘸吓,如何注冊(cè)廣播蔗候,如何發(fā)送廣播以及使用過程應(yīng)該注意的一些點(diǎn)洒琢。本文將從源碼的角度來分析注冊(cè)尝哆、發(fā)送仰禀、執(zhí)行廣播的過程。
一.靜態(tài)廣播注冊(cè)
靜態(tài)注冊(cè)指的是在AndroidManifest.xml中注冊(cè)的廣播秦叛,這些冊(cè)信息的維護(hù)主要有兩個(gè)過程:系統(tǒng)啟動(dòng)的時(shí)候掃描系統(tǒng)中安裝的apk的注冊(cè)信息晦溪,安裝、卸載的時(shí)候更新注冊(cè)信息挣跋。
當(dāng)系統(tǒng)啟動(dòng)的時(shí)候會(huì)啟動(dòng)PackageManagerService三圆,從其main方法開始。
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
//創(chuàng)建了一個(gè)PackageManagerService實(shí)例
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
//注冊(cè)這個(gè)Service
ServiceManager.addService("package", m);
return m;
}
它的main方法主要通過它的構(gòu)造方法創(chuàng)建了一個(gè)實(shí)例避咆,并注冊(cè)了這個(gè)Service舟肉,它的構(gòu)造方法實(shí)現(xiàn)如下:
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
......
synchronized (mPackages) {
......
File dataDir = Environment.getDataDirectory();
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
......
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//掃描其他路徑
}
構(gòu)造方法中的代碼比較多,這里只保留了部分關(guān)鍵代碼查库,從代碼中的掃描的路徑可以了解到Android系統(tǒng)中的應(yīng)用都安裝在哪路媚,這里只分析掃描系統(tǒng)應(yīng)用的過程,即/system/app這個(gè)目錄樊销,其他路徑類似整慎。這個(gè)過程涉及到的方法比較多,先上一張時(shí)序序圖:
構(gòu)造方法之后围苫,沿著路徑往下到 scanPackageLI 方法才有我們比較關(guān)心的代碼裤园。
/**
* Scans a package and returns the newly parsed package.
* Returns {@code null} in case of errors and the error code is stored in mLastScanError
*/
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
final PackageParser.Package pkg;
try {
//這里調(diào)用了PackageParser的parsePackage方法來解析apk文件
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
//最后又調(diào)用一個(gè)重載方法
return scanPackageLI(pkg, scanFile, parseFlags, scanFlags, currentTime, user);
}
這個(gè)方法里主要調(diào)用了兩個(gè)方法:PackageParser的parsePackage方法和一個(gè)重載的scanPackageLI方法,按照順序剂府,先看parsePackage方法拧揽。
public Package parsePackage(File packageFile, int flags) throws PackageParserException {
if (packageFile.isDirectory()) {
return parseClusterPackage(packageFile, flags);
} else {
return parseMonolithicPackage(packageFile, flags);
}
}
這個(gè)方法比較簡(jiǎn)單,區(qū)分文件和目錄來調(diào)用不同的方法,這里研究parseClusterPackage這條路徑(路徑參考上面的時(shí)序圖)淤袜,沿著這條路徑往下万俗,直到parseBaseApplication方法,這里有我們所關(guān)心的代碼饮怯。
/**
* Parse the {@code application} XML tree at the current parse location in a
* <em>base APK</em> manifest.
* <p>
* When adding new features, carefully consider if they should also be
* supported by split APKs.
*/
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);
//省略部分非關(guān)鍵代碼
....
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, flags, outError, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.activities.add(a);
//解析receiver節(jié)點(diǎn)并保存到owner.receivers
} else if (tagName.equals("receiver")) {
Activity a = parseActivity(owner, res, parser, flags, outError, true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.receivers.add(a);
}
//省略解析其他組件分支的代碼
......
}
}
可以看到闰歪,原來是解析各個(gè)apk文件的AndroidManifest.xml文件中所有注冊(cè)的receiver,并且其添加到Package的成員變量receivers中蓖墅,這樣我們?cè)赑MS中拿到Package對(duì)象就能得到這個(gè)應(yīng)用的所用靜態(tài)注冊(cè)的廣播库倘。接下來就回到了PMS中(通常跟蹤源碼到返回的時(shí)候意味著離目標(biāo)也已經(jīng)不遠(yuǎn)了)。
當(dāng)返回到PMS后论矾,又調(diào)用了一個(gè)重載的scanPackageLI方法教翩,沿著路徑往下,到scanPackageDirtyLI方法又出現(xiàn)關(guān)鍵代碼贪壳。
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
throws PackageManagerException {
....
//省略其他非關(guān)鍵代碼
//這個(gè)pkg就是剛才PackageParser中解析得到的
N = pkg.receivers.size();
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
//將所有靜態(tài)注冊(cè)的廣播添加到mReceivers集合中
mReceivers.addActivity(a, "receiver");
if ((policyFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
.....
}
看到這里終于松了一口氣饱亿,原來所有的靜態(tài)注冊(cè)的廣播最終是保存在PMS的成員變量mReceivers中,當(dāng)發(fā)送廣播時(shí)闰靴,AMS就會(huì)到這里來查詢所有匹配的靜態(tài)廣播接收者彪笼,進(jìn)而將廣播發(fā)送給它們。下面的就是AMS中查詢靜態(tài)廣播接收者的代碼蚂且。
二.動(dòng)態(tài)注冊(cè)廣播
動(dòng)態(tài)注冊(cè)廣播我們通常需要這么做
IntentFilter filter = new IntentFilter("jdqm.intent.action.TEST");
registerReceiver(receiver, filter);
從調(diào)用context.registerReceiver方法到注冊(cè)完成的大致的過程為:
從ContextWapper的registerReceiver方法開始
@Override
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
直接調(diào)用了mBase的registerReceiver方法配猫,這個(gè)mBase實(shí)際上是ContextImp的實(shí)例,ContextImp的registerReceiver方法也是將處理邏輯放到了該類的registerReceiverInternal方法中杏死,該方法的實(shí)現(xiàn)如下:
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
//使用IItentReceiver(這是一個(gè)Binder對(duì)象)來中轉(zhuǎn)實(shí)現(xiàn)跨進(jìn)程通信
IIntentReceiver rd = null;
if (receiver != null) {
//mPackageInfo是LoadedApk的實(shí)例
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
//這個(gè)Handler是主線程中mH
scheduler = mMainThread.getHandler();
}
//通過getReceiverDispatcher獲取對(duì)應(yīng)的IItentReceiver對(duì)象
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
//通過Binder機(jī)制泵肄,向AMS發(fā)起注冊(cè)請(qǐng)求,后續(xù)的邏輯就到AMS中了
final Intent intent = ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在這個(gè)方法中通過調(diào)用getReceiverDispatcher方法淑翼,將廣播記錄在LoadedApk的成員變量mReceivers中腐巢。另外 ActivityManagerNative.getDefault()得到的是ActivityManagerService在客戶端的一個(gè)代理對(duì)象,通過它我們就可以調(diào)用ActivityManagerService的registerReceiver方法:
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
......
//省略前面代碼
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
//動(dòng)態(tài)注冊(cè)的廣播都保存在這個(gè)集合中
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else if (rl.uid != callingUid) {
throw new IllegalArgumentException(
"Receiver requested to register for uid " + callingUid
+ " was previously registered for uid " + rl.uid);
} else if (rl.pid != callingPid) {
throw new IllegalArgumentException(
"Receiver requested to register for pid " + callingPid
+ " was previously registered for pid " + rl.pid);
} else if (rl.userId != userId) {
throw new IllegalArgumentException(
"Receiver requested to register for user " + userId
+ " was previously registered for user " + rl.userId);
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId);
//關(guān)聯(lián)IntentFilter
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadcast");
}
mReceiverResolver.addFilter(bf);
//省略后面代碼
......
}
}
到這里我們得出結(jié)論:動(dòng)態(tài)注冊(cè)的廣播存儲(chǔ)在AMS的成員變量mRegisteredReceivers中玄括。
三.發(fā)送廣播
發(fā)送廣播過程的時(shí)序圖如下:
首先從ContextWrapper#sendBroadcast(Intent)方法開始.
@Override
public void sendBroadcast(Intent intent) {
//ContextImp: mBase
mBase.sendBroadcast(intent);
}
ContextImp#sendBroadcast(Intent)
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
//這個(gè)resolvedType實(shí)際上是MIME類型
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
//通過Binder機(jī)制冯丙,向AMS發(fā)起請(qǐng)求
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();
}
}
前面提到過ActivityManagerNative.getDefault()返回的是AMS在客戶端的代理對(duì)象,通過它來調(diào)用AMS#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) {
enforceNotIsolatedCaller("broadcastIntent");
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();
//進(jìn)一步調(diào)用broadcastIntentLocked來處理
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;
}
}
可以看到在這個(gè)方法內(nèi)部又進(jìn)一步調(diào)用broadcastIntentLocked來處理银还,這個(gè)方法代碼很多,下面只列出部分:
//Android3.1之后洁墙,默認(rèn)情況下,Intent會(huì)添加了下面這個(gè)flag,所以默認(rèn)情況下不會(huì)啟動(dòng)處于停止?fàn)顟B(tài)的應(yīng)用戒财。
// By default broadcasts do not go to stopped apps.
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
......
// 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) {
//收集匹配靜態(tài)注冊(cè)的廣播接收者
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
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++) {
if (mUserController.hasUserRestriction(
UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) {
continue;
}
List<BroadcastFilter> registeredReceiversForUser =
mReceiverReHHsolver.queryIntent(intent,
resolvedType, false, users[i]);
if (registeredReceivers == null) {
registeredReceivers = registeredReceiversForUser;
} else if (registeredReceiversForUser != null) {
registeredReceivers.addAll(registeredReceiversForUser);
}
}
} else {
//收集匹配動(dòng)態(tài)注冊(cè)的廣播接受者
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
}
}
......
//動(dòng)態(tài)注冊(cè)的無序廣播
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermissions,
appOp, brOptions, registeredReceivers, resultTo, resultCode, resultData,
resultExtras, ordered, sticky, false, userId);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
if (!replaced) {
//將動(dòng)態(tài)注冊(cè)的無序廣播添加的無序廣播隊(duì)列
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
....
//receivers保存的是所有的靜態(tài)廣播热监,動(dòng)態(tài)注冊(cè)的有序廣播
if ((receivers != null && receivers.size() > 0)
|| resultTo != null) {
BroadcastQueue queue = broadcastQueueForIntent(intent);
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(r);
if (!replaced) {
//將構(gòu)造的BroadcastRecord添加的有序廣播的隊(duì)列
queue.enqueueOrderedBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
} else {
// There was nobody interested in the broadcast, but we still want to record
// that it happened.
if (intent.getComponent() == null && intent.getPackage() == null
&& (intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
// This was an implicit broadcast... let's record it for posterity.
addBroadcastStatLocked(intent.getAction(), callerPackage, 0, 0, 0);
}
}
從這方法的實(shí)現(xiàn)可以看到,首先收集了所有的符合的動(dòng)態(tài)注冊(cè)饮寞、靜態(tài)注冊(cè)的接收者孝扛,然后將動(dòng)態(tài)無序廣播列吼、所有靜態(tài)和動(dòng)態(tài)有序包裝成兩個(gè)BroadcastRecord對(duì)象,添加到BroadcastQueue的兩個(gè)集合中苦始,這兩個(gè)集合是:
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>();
final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>();
然后調(diào)用用BroadcastQueue的scheduleBroadcastsLocked方法進(jìn)處理這兩個(gè)集合寞钥。scheduleBroadcastsLocked方法的實(shí)現(xiàn)如下:
public void scheduleBroadcastsLocked() {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts ["
+ mQueueName + "]: current="
+ mBroadcastsScheduled);
if (mBroadcastsScheduled) {
return;
}
mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
mBroadcastsScheduled = true;
}
這里邏輯也很簡(jiǎn)單,通過mHandler發(fā)送了一條BROADCAST_INTENT_MSG消息陌选,這個(gè)Handler的實(shí)現(xiàn)如下:
final BroadcastHandler mHandler;
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");
//關(guān)鍵代碼
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
case SCHEDULE_TEMP_WHITELIST_MSG: {
DeviceIdleController.LocalService dic = mService.mLocalDeviceIdleController;
if (dic != null) {
dic.addPowerSaveTempWhitelistAppDirect(UserHandle.getAppId(msg.arg1),
msg.arg2, true, (String)msg.obj);
}
} break;
}
}
}
可以發(fā)現(xiàn)理郑,調(diào)用了processNextBroadcast方法來處理:
final void processNextBroadcast(boolean fromMsg) {
synchronized(mService) {
BroadcastRecord r;
mService.updateCpuStats();
if (fromMsg) {
mBroadcastsScheduled = false;
}
//首先處理mParallelBroadcasts這個(gè)集合,這意味著mParallelBroadcasts集合的廣播接受者比mOrderedBroadcasts集合的廣播接收者先收到廣播
// First, deliver any non-serialized broadcasts right away.
while (mParallelBroadcasts.size() > 0) {
//一個(gè)廣播對(duì)應(yīng)著一個(gè)BroadcastRecord實(shí)例
r = mParallelBroadcasts.remove(0);
r.dispatchTime = SystemClock.uptimeMillis();
r.dispatchClockTime = System.currentTimeMillis();
final int N = r.receivers.size();
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
+ mQueueName + "] " + r);
for (int i=0; i<N; i++) {
Object target = r.receivers.get(i);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Delivering non-ordered on [" + mQueueName + "] to registered "
+ target + ": " + r);
//動(dòng)態(tài)注冊(cè)的無序廣播
deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
}
//記錄廣播的歷史
addBroadcastToHistoryLocked(r);
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
+ mQueueName + "] " + r);
}
// Now take care of the next serialized one...
// If we are waiting for a process to come up to handle the next
// broadcast, then do nothing at this point. Just in case, we
// check that the process we're waiting for still exists.
if (mPendingBroadcast != null) {
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"processNextBroadcast [" + mQueueName + "]: waiting for "
+ mPendingBroadcast.curApp);
boolean isDead;
synchronized (mService.mPidsSelfLocked) {
ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);
isDead = proc == null || proc.crashing;
}
if (!isDead) {
// It's still alive, so keep waiting
return;
} else {
Slog.w(TAG, "pending app ["
+ mQueueName + "]" + mPendingBroadcast.curApp
+ " died before responding to broadcast");
mPendingBroadcast.state = BroadcastRecord.IDLE;
mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
boolean looped = false;
do {
if (mOrderedBroadcasts.size() == 0) {
......
} while (r == null);
.....
// Is this receiver's application already running?
if (app != null && app.thread != null) {
try {
app.addPackage(info.activityInfo.packageName,
info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);
//當(dāng)進(jìn)程跑起來后
processCurBroadcastLocked(r, app);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when sending broadcast to "
+ r.curComponent, e);
} catch (RuntimeException e) {
Slog.wtf(TAG, "Failed sending broadcast to "
+ r.curComponent + " with " + r.intent, e);
// If some unexpected exception happened, just skip
// this broadcast. At this point we are not in the call
// from a client, so throwing an exception out from here
// will crash the entire system instead of just whoever
// sent the broadcast.
logBroadcastReceiverDiscardLocked(r);
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
// We need to reset the state if we failed to start the receiver.
r.state = BroadcastRecord.IDLE;
return;
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
}
可以發(fā)現(xiàn)咨油,先處理了mParallelBroadcasts您炉,然后才處理mOrderedBroadcasts,這兩個(gè)集合的處理邏輯是有些差異的役电,按順序先看mParallelBroadcasts赚爵,這個(gè)集合是通過deliverToRegisteredReceiverLocked來處理,而這個(gè)方法又進(jìn)一步調(diào)用了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) {
if (app.thread != null) {
// 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);
// TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
// DeadObjectException when the process isn't actually dead.
//} catch (DeadObjectException ex) {
// Failed to call into the process. It's dying so just let it die and move on.
// throw ex;
} 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 {
receiver.performReceive(intent, resultCode, data, extras, ordered,
sticky, sendingUser);
}
}
app.thread就是ActivityThread的一個(gè)代理對(duì)象法瑟,通過它就可以調(diào)用ActivityThread的scheduleRegisteredReceiver方法:
// 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);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
繼續(xù)調(diào)用IIntentReceiver.performReceive方法來完成后續(xù)動(dòng)作冀膝,又將邏輯切回到了我們注冊(cè)廣播時(shí)的LoadedApk.ReceiverDispatcher的performReceive中,這就回到了注冊(cè)廣播的主線程了霎挟。
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
//創(chuàng)建了一個(gè)Args對(duì)象畸写,Args實(shí)現(xiàn)了Runable接口
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);
}
}
//mActivityThread是 ActivityThread#mH
if (intent == null || !mActivityThread.post(args)) {
if (mRegistered && ordered) {
IActivityManager mgr = ActivityManagerNative.getDefault();
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing sync broadcast to " + mReceiver);
args.sendFinished(mgr);
}
}
}
創(chuàng)建了一個(gè)Args對(duì)象,Args實(shí)現(xiàn)了Runnable接口氓扛,然后mActivityThread.post(args)將這個(gè)Runnable 拋給了mH枯芬,Args的run方法實(shí)現(xiàn)如下:
public void run() {
......
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
try {
ClassLoader cl = mReceiver.getClass().getClassLoader();
intent.setExtrasClassLoader(cl);
intent.prepareToEnterProcess();
setExtrasClassLoader(cl);
receiver.setPendingResult(this);
//直接通過注冊(cè)時(shí)的引用,調(diào)用其onReceive方法
receiver.onReceive(mContext, intent);
} catch (Exception e) {
if (mRegistered && ordered) {
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing failed broadcast to " + mReceiver);
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) {
finish();
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
到這里終于看到了廣播接受者的onReceive(mContext, intent)方法被執(zhí)行了采郎。mParallelBroadcasts的處理邏輯分析完了千所,接下來分析mOrderedBroadcasts的處理邏輯,從前面廣播注冊(cè)的邏輯得知蒜埋,mOrderedBroadcasts包含所有靜態(tài)注冊(cè)的廣播和動(dòng)態(tài)注冊(cè)的有序廣播淫痰,其中動(dòng)態(tài)注冊(cè)的有序廣播的處理邏輯與前面無序的處理過程類似。現(xiàn)在重點(diǎn)看下靜態(tài)注冊(cè)的廣播整份,從processNextBroadcast方法中可以看到是調(diào)用了processCurBroadcastLocked來處理mOrderedBroadcasts中靜態(tài)注冊(cè)的廣播待错。
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
r.receiver = app.thread.asBinder();
r.curApp = app;
app.curReceiver = r;
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
mService.updateLruProcessLocked(app, false, null);
mService.updateOomAdjLocked();
// Tell the application to launch this receiver.
r.intent.setComponent(r.curComponent);
boolean started = false;
try {
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
"Delivering to component " + r.curComponent
+ ": " + r);
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);
//關(guān)鍵代碼
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,
app.repProcState);
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST,
"Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
app.curReceiver = null;
}
}
}
通過ActivityThread的代理對(duì)象app.thread調(diào)用其scheduleReceiver方法,其實(shí)現(xiàn)如下:
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);
}
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
最終通過mH發(fā)送了一條H.RECEIVER消息烈评,對(duì)應(yīng)what為RECEIVER的處理:
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
緊接著調(diào)用handleReceiver來處理:
private void handleReceiver(ReceiverData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
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);
//創(chuàng)建了一個(gè)廣播接收者實(shí)例
receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
throw new RuntimeException(
"Unable to instantiate receiver " + component
+ ": " + e.toString(), e);
}
try {
Application app = packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(
TAG, "Performing receive of " + data.intent
+ ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + packageInfo.getPackageName()
+ ", comp=" + data.intent.getComponent().toShortString()
+ ", dir=" + packageInfo.getAppDir());
ContextImpl context = (ContextImpl)app.getBaseContext();
sCurrentBroadcastIntent.set(data.intent);
receiver.setPendingResult(data);
//廣播接收者的onReceive方法被執(zhí)行了
receiver.onReceive(context.getReceiverRestrictedContext(),
data.intent);
} catch (Exception e) {
if (DEBUG_BROADCAST) Slog.i(TAG,
"Finishing failed broadcast to " + data.intent.getComponent());
data.sendFinished(mgr);
if (!mInstrumentation.onException(receiver, e)) {
throw new RuntimeException(
"Unable to start receiver " + component
+ ": " + e.toString(), e);
}
} finally {
sCurrentBroadcastIntent.set(null);
}
if (receiver.getPendingResult() != null) {
data.finish();
}
}
靜態(tài)注冊(cè)的廣播接收者通常是沒有運(yùn)行的火俄,所以在這里先是創(chuàng)建了一個(gè)接收者的實(shí)例,然后調(diào)用它的onReceive方法讲冠。
三.總結(jié):
靜態(tài)注冊(cè)注冊(cè)的廣播瓜客,在PMS啟動(dòng)的時(shí)候掃描系統(tǒng)中安裝的apk文件,并解析它們的AndroidManifest.xml文件,將所有注冊(cè)的廣播保存在PMS的成員變量mReceivers中谱仪;
動(dòng)態(tài)注冊(cè)的廣播存儲(chǔ)在AMS的成員變量mRegisteredReceivers中玻熙;
發(fā)送廣播的處理邏輯在AMS中,AMS負(fù)責(zé)從mReceivers和mRegisteredReceivers這兩個(gè)集合查詢出與IntentFilter匹配的接收者疯攒,并將它們添加到BroadcastQueue的mParallelBroadcasts(動(dòng)態(tài)注冊(cè)的無序廣播)或者mOrderedBroadcasts(有序廣播和所有的靜態(tài)廣播)中;
在BroadcastQueue先處理mParallelBroadcasts嗦随,所以動(dòng)態(tài)注冊(cè)的無序廣播會(huì)先收到廣播;
當(dāng)有應(yīng)用安裝,卸載時(shí)(實(shí)際的邏輯在PMS中)敬尺,靜態(tài)注冊(cè)的廣播自然是在PMS中進(jìn)行更新注冊(cè)信息枚尼,接著再發(fā)送廣播到AMS中更新動(dòng)態(tài)注冊(cè)廣播;
動(dòng)態(tài)廣播的onReceive方法是在LoadedApk#ReceiverDispatcher#Args的run方法中被調(diào)用筷转;靜態(tài)廣播的onReceive是在ActivityThread的handleReceiver方法中被調(diào)用姑原,而它們都是跑在目標(biāo)進(jìn)程的主線程中。
以上源碼均來自 Android25呜舒。