Android Service、 BroadcastReceiver、ContentProvider ANR 原理詳解

Service ANR:

啓動Service 的時候,會調用到ActiveServices 類的 realStartServiceLocked方法。

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
		//發送延遲消息
        bumpServiceExecutingLocked(r, execInFg, "create");
       }

    private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
              boolean timeoutNeeded = true;
             long now = SystemClock.uptimeMillis();
                    if (r.app != null) {
                r.app.executingServices.add(r);
                r.app.execServicesFg |= fg;
                if (timeoutNeeded && r.app.executingServices.size() == 1) {
                    scheduleServiceTimeoutLocked(r.app);
                }
            }
        } else if (r.app != null && fg && !r.app.execServicesFg) {
            r.app.execServicesFg = true;
            if (timeoutNeeded) {
                scheduleServiceTimeoutLocked(r.app);
            }
        }
        r.executeFg |= fg;
        r.executeNesting++;
        r.executingStart = now;
    }

繼續調用scheduleServiceTimeoutLocked

    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
        if (proc.executingServices.size() == 0 || proc.thread == null) {
            return;
        }
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
        mAm.mHandler.sendMessageDelayed(msg,
                proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
    }

可以看到,裏面拿到AtivityManagerService 的 Mainhandler 發送一個延期消息。

當Service 啓動之後,就會移除掉消息。(ActiveServices)見下面:


    private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying,
            boolean finishing) {      
        if (r.executeNesting <= 0) {
            if (r.app != null) {     
                if (r.app.executingServices.size() == 0) {                  
                    mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);

BroadcastReceiver ANR:

當處理廣播的時候,會走到下面的processNextBroadcastLocked 方法:

    final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
        BroadcastRecord r;
        // First, deliver any non-serialized broadcasts right away.
        while (mParallelBroadcasts.size() > 0) {
            if (mService.mProcessesReady && r.dispatchTime > 0) {
                long now = SystemClock.uptimeMillis();
                if ((numReceivers > 0) &&
                        (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
                   broadcastTimeoutLocked(false); // forcibly finish this broadcast
                    forceReceive = true;
                    r.state = BroadcastRecord.IDLE;
	                cancelBroadcastTimeoutLocked();

                }
            }

broadcastTimeoutLocked 裏面會調用setBroadcastTimeoutLocked 方法,設置超時時間。

setBroadcastTimeoutLocked:

    final void setBroadcastTimeoutLocked(long timeoutTime) {
        if (! mPendingBroadcastTimeoutMessage) {
            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);
            mHandler.sendMessageAtTime(msg, timeoutTime);
            mPendingBroadcastTimeoutMessage = true;
        }
    }

BroadcastHandler 是自己的Handler,但是Looper 是ActivityManagerService 的 MainHandler 的Looper.


    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");
                    processNextBroadcast(true);
                } break;
                case BROADCAST_TIMEOUT_MSG: {
                    synchronized (mService) {
                        broadcastTimeoutLocked(true);
                    }
                } break;
            }
        }
    }

處理ANR:

    final void broadcastTimeoutLocked(boolean fromMsg) {
        if (!debugging && 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:

    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.mAppErrors.appNotResponding(mApp, null, null, false, mAnnotation);
        }
    }

ContentProvider ANR:

ContentProvider Timeout是位於”ActivityManager”線程中的AMS.MainHandler收到CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息時觸發。
ContentProvider 超時爲CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s. 這個跟前面的Service和BroadcastQueue完全不同, 由Provider進程啓動過程相關.

ContentProvider 是在app 啓動的時候,初始化的。初始話的時候,會發一條延遲消息,CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG


        if (providers != null && checkAppInLaunchingProvidersLocked(app)) {
            Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG);
            msg.obj = app;
            mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);
        }

當發佈成功之後,就會移除掉這條消息。

    public final void publishContentProviders(IApplicationThread caller,
            List<ContentProviderHolder> providers) {
                    if (wasInLaunchingProviders) {
                        mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
                    }
            }
        }
    }

https://www.jianshu.com/p/1c827675f457

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章