Broadcast(五)ANR

本文關(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]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市倾鲫,隨后出現(xiàn)的幾起案子粗合,更是在濱河造成了極大的恐慌,老刑警劉巖乌昔,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件隙疚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡磕道,警方通過(guò)查閱死者的電腦和手機(jī)供屉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)溺蕉,“玉大人伶丐,你說(shuō)我怎么就攤上這事》杼兀” “怎么了哗魂?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)漓雅。 經(jīng)常有香客問(wèn)我录别,道長(zhǎng),這世上最難降的妖魔是什么邻吞? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任组题,我火速辦了婚禮,結(jié)果婚禮上抱冷,老公的妹妹穿的比我還像新娘崔列。我一直安慰自己,他們只是感情好徘层,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布峻呕。 她就那樣靜靜地躺著利职,像睡著了一般趣效。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猪贪,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天跷敬,我揣著相機(jī)與錄音,去河邊找鬼热押。 笑死西傀,一個(gè)胖子當(dāng)著我的面吹牛斤寇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拥褂,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼娘锁,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了饺鹃?” 一聲冷哼從身側(cè)響起莫秆,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悔详,沒(méi)想到半個(gè)月后镊屎,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茄螃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年缝驳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片归苍。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡用狱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出霜医,到底是詐尸還是另有隱情齿拂,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布肴敛,位于F島的核電站署海,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏医男。R本人自食惡果不足惜砸狞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望镀梭。 院中可真熱鬧刀森,春花似錦、人聲如沸报账。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)透罢。三九已至榜晦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間羽圃,已是汗流浹背乾胶。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人识窿。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓斩郎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親喻频。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缩宜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 什么是ANR ANR(Application Not Responding)就是應(yīng)用在規(guī)定的時(shí)間內(nèi)沒(méi)有響應(yīng)用戶輸入...
    lbtrace閱讀 3,370評(píng)論 3 9
  • 曾經(jīng)有一份美好的愛(ài)情放在我的面前我沒(méi)有珍惜窿侈。等到失去后才后悔莫及炼幔。如果可以再對(duì)小李說(shuō)。毛欣想說(shuō)史简。這輩子無(wú)緣再牽手乃秀。...
    毛欣與小李閱讀 2,565評(píng)論 0 13
  • 在實(shí)際情況中,當(dāng)Android項(xiàng)目的用戶量特別大時(shí)候圆兵,一些細(xì)小的問(wèn)題也會(huì)被放大跺讯,ANR問(wèn)題就是一個(gè)典型的例子。一些...
    Uprising閱讀 53,943評(píng)論 4 116
  • 本文將從介紹什么是ANR,給出anr產(chǎn)生的幾種觸發(fā)點(diǎn)殉农,分析這幾種情況下是怎么產(chǎn)生anr的刀脏,然后給出優(yōu)化的方法這幾個(gè)...
    田間小鹿閱讀 855評(píng)論 0 0
  • 一、ANR說(shuō)明和原因 1.1 簡(jiǎn)介 ANR全稱:Application Not Responding超凳,也就是應(yīng)用程...
    Marker_Sky閱讀 98,653評(píng)論 6 117