本文關(guān)注11、19、21裳仆、24、34
11 設(shè)置超時(shí)
// setBroadcastTimeoutLocked()把mPendingBroadcastTimeoutMessage設(shè)置為true
// 所以只會(huì)進(jìn)入一次
if (! mPendingBroadcastTimeoutMessage) {
long timeoutTime = r.receiverTime + mTimeoutPeriod;
setBroadcastTimeoutLocked(timeoutTime);
}
final void setBroadcastTimeoutLocked(long timeoutTime) {
if (! mPendingBroadcastTimeoutMessage) {
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
// 延遲timeoutTime給BroadcastHandler發(fā)送一條BROADCAST_TIMEOUT_MSG消息
mHandler.sendMessageAtTime(msg, timeoutTime);
mPendingBroadcastTimeoutMessage = true;
}
}
34 取消超時(shí)
final void cancelBroadcastTimeoutLocked() {
if (mPendingBroadcastTimeoutMessage) {
mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);
// 還原mPendingBroadcastTimeoutMessage
mPendingBroadcastTimeoutMessage = false;
}
}
19
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: {
processNextBroadcast(true);
} break;
case BROADCAST_TIMEOUT_MSG: {
synchronized (mService) {
broadcastTimeoutLocked(true);
}
} break;
...
}
}
};
上面說(shuō)只有第一個(gè)receiver會(huì)設(shè)置超時(shí)孤钦,最后一個(gè)receiver執(zhí)行完才會(huì)取消超時(shí)歧斟。那么假如有ABC3個(gè)靜態(tài)注冊(cè)的receiver,它們耗時(shí)都是6s偏形,然后發(fā)送一個(gè)前臺(tái)廣播静袖,那么要執(zhí)行完B就需要12s,我們知道前臺(tái)廣播是10s超時(shí),所以就會(huì)進(jìn)入broadcastTimeoutLocked(),那么會(huì)彈出ANR么鸿摇?接著看
21或24
final void broadcastTimeoutLocked(boolean fromMsg) {
if (fromMsg) {
// 不管怎樣剩岳,先還原mPendingBroadcastTimeoutMessage
mPendingBroadcastTimeoutMessage = false;
}
if (mOrderedBroadcasts.size() == 0) {
return;
}
long now = SystemClock.uptimeMillis();
BroadcastRecord r = mOrderedBroadcasts.get(0);
if (fromMsg) {
if (mService.mDidDexOpt) {
// Delay timeouts until dexopt finishes.
mService.mDidDexOpt = false;
long timeoutTime = SystemClock.uptimeMillis() + mTimeoutPeriod;
setBroadcastTimeoutLocked(timeoutTime);
return;
}
if (!mService.mProcessesReady) {
// Only process broadcast timeouts if the system is ready. That way
// PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
// to do heavy lifting for system up.
return;
}
long timeoutTime = r.receiverTime + mTimeoutPeriod;
// 所以重點(diǎn)是這個(gè)判斷喘帚,雖然會(huì)進(jìn)入這個(gè)broadcastTimeoutLocked()
// 但是每個(gè)receiver的receiverTime是在processNextBroadcast分配的
// r.receiverTime = SystemClock.uptimeMillis()
// 我還是不明白為什么不在通知receiver前先去掉超時(shí)畅姊,然后重新設(shè)置超時(shí)
if (timeoutTime > now) {
// We can observe premature timeouts because we do not cancel and reset the
// broadcast timeout message after each receiver finishes. Instead, we set up
// an initial timeout then kick it down the road a little further as needed
// when it expires.
// 設(shè)置超時(shí)
setBroadcastTimeoutLocked(timeoutTime);
return;
}
}
BroadcastRecord br = mOrderedBroadcasts.get(0);
if (br.state == BroadcastRecord.WAITING_SERVICES) {
// In this case the broadcast had already finished, but we had decided to wait
// for started services to finish as well before going on. So if we have actually
// waited long enough time timeout the broadcast, let's give up on the whole thing
// and just move on to the next.
br.curComponent = null;
br.state = BroadcastRecord.IDLE;
processNextBroadcast(false);
return;
}
r.receiverTime = now;
r.anrCount++;
// Current receiver has passed its expiration date.
if (r.nextReceiver <= 0) {
return;
}
ProcessRecord app = null;
String anrMessage = null;
Object curReceiver = r.receivers.get(r.nextReceiver-1);
logBroadcastReceiverDiscardLocked(r);
if (curReceiver instanceof BroadcastFilter) {
BroadcastFilter bf = (BroadcastFilter)curReceiver;
if (bf.receiverList.pid != 0
&& bf.receiverList.pid != ActivityManagerService.MY_PID) {
synchronized (mService.mPidsSelfLocked) {
app = mService.mPidsSelfLocked.get(
bf.receiverList.pid);
}
}
} else {
app = r.curApp;
}
if (app != null) {
anrMessage = "Broadcast of " + r.intent.toString();
}
if (mPendingBroadcast == r) {
mPendingBroadcast = null;
}
// 超時(shí)了,不繼續(xù)等待app通知吹由,直接繼續(xù)下一個(gè)receiver
// Move on to the next receiver.
finishReceiverLocked(r, r.resultCode, r.resultData,
r.resultExtras, r.resultAbort, false);
scheduleBroadcastsLocked();
// ANR
if (anrMessage != null) {
// Post the ANR to the handler since we do not want to process ANRs while
// potentially holding our lock.
mHandler.post(new AppNotResponding(app, anrMessage));
}
}
ANR
final ActivityManagerService mService;
private final class AppNotResponding implements Runnable {
private final ProcessRecord mApp;
private final String mAnnotation;
public AppNotResponding(ProcessRecord app, String annotation) {
mApp = app;
mAnnotation = annotation;
}
@Override
public void run() {
mService.appNotResponding(mApp, null, null, false, mAnnotation);
}
}
進(jìn)入AMS.appNotResponding()若未,參考[Service(二)ANR]