android之基础学习攻克

ANR相关-Handler

2018-12-14  本文已影响0人  weiinter105

前言

要分析ANR问题,必须先了解Handler的基本原理;

常见的ANR原因包括
 A.主线程有耗时操作,如有复杂的layout布局,IO操作等。
 B.被Binder对端block
 C.被子线程同步锁block
 D.Binder被占满导致主线程无法和SystemServer通信
 E.得不到系统资源(CPU/RAM/IO)

就以Service处理超时为例,一般我们对Service执行一个操作时,都是通过AMS来对Service实例进行操作,每一个操作前都会执行bumpServiceExecutingLocked函数

2121 bumpServiceExecutingLocked(r, execInFg, "bind");
2558 bumpServiceExecutingLocked(r, execInFg, "create");
2682 bumpServiceExecutingLocked(r, execInFg, "start");
2808 bumpServiceExecutingLocked(r, false, "bring down unbind");
2908 bumpServiceExecutingLocked(r, false, "destroy");
3004 bumpServiceExecutingLocked(s, false, "unbind");

其中会调用scheduleServiceTimeoutLocked(r.app),其中会向AMS的ActivityManager线程handler发送一个消息

mHandler = new MainHandler(mHandlerThread.getLooper());
37574 msg.obj = proc;
3575 mAm.mHandler.sendMessageDelayed(msg,
3576                proc.execServicesFg ? SERVICE_TIMEOUT :  SERVICE_BACKGROUND_TIMEOUT);

Message中包含Service的宿主进程,也是将来可能发生ANR的进程,这个Message进入到system_server的主线程Handler中,什么时候取消呢?

当Service执行完AMS要求的操作时取消,以sendServiceArgsLocked为例:

ActiveServices#sendServiceArgsLocked

r.app.thread.scheduleServiceArgs(r, slice);

Service所在进程的一个binder线程响应scheduleServiceArgs接口

ActivityThread#scheduleServiceArgs

890        public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
891            List<ServiceStartArgs> list = args.getList();
892
893            for (int i = 0; i < list.size(); i++) {
894                ServiceStartArgs ssa = list.get(i);
895                ServiceArgsData s = new ServiceArgsData();
896                s.token = token;
897                s.taskRemoved = ssa.taskRemoved;
898                s.startId = ssa.startId;
899                s.flags = ssa.flags;
900                s.args = ssa.args;
901
902                sendMessage(H.SERVICE_ARGS, s);
903            }
904        }

Service宿主进程的binder线程向其主线程handler(ActivityThread$H)发送消息,消息执行完后,就会call binder AMS中的serviceDoneExecuting接口

ActivityThread#handleServiceArgs

3509                if (!data.taskRemoved) {
3510                    res = s.onStartCommand(data.args, data.flags, data.startId); //调用onStartCommand
3511                } else {
3512                    s.onTaskRemoved(data.args); //调用onTaskRemoved,用于最近任务中划掉进程的Task时被调用
3513                    res = Service.START_TASK_REMOVED_COMPLETE;
3514                }
           //在通知AMS消息处理完成前,现完成本地等待处理的任务
            //这里与启动BroadcastReceiver对应进程的情况相似
            //进程可能是由于创建Service才被启动的,Service处理完毕后,AMS可能进行进程管理
            //杀死Service对应进程,因此先确保工作做完
3516                if(!ActivityThreadInjector.isPersistent(mBoundApplication)) {
3517                    QueuedWork.waitToFinish();
3518                }
3519                // QueuedWork.waitToFinish(); //等待本地QueuedWork处理完成,再进行清理工作 //参考https://jira.n.xiaomi.com/browse/MIUI-860168 QueuedWork类似任务队列
3520                // END
3521                try {
3522                    ActivityManager.getService().serviceDoneExecuting(
3523                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); //通知AMS ServiceRecord相关结果,执行收尾工作,本次的type为SERVICE_DONE_EXECUTING_START,res为onStartCommand的返回值,描述了在系统的杀死事件中,系统应该如何继续这个服务的值,参考https://blog.csdn.net/taki_dsm/article/details/8865913 https://blog.csdn.net/zjws23786/article/details/51800929 return值由服务的需求自己指定
3524                } catch (RemoteException e) {
3525                    throw e.rethrowFromSystemServer();
3526                }

当Service所在进程的主线程执行完相应的操作时,会调用AMS中的serviceDoneExecuting接口

3378                ActivityManager.getService().serviceDoneExecuting(
3379                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);

system_server找一个空闲的binder线程执行serviceDoneExecuting操作,最终会调用到

mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);

为system_server的主线程Handler移除这个Service超时消息,则不会发生ANR

Handler#removeMessages

748    /**
749     * Remove any pending posts of messages with code 'what' that are in the
750     * message queue.
751     */
752    public final void removeMessages(int what) {
753        mQueue.removeMessages(this, what, null);
754    }

MessageQueue#removeMessages

将MessageQueue中的所有what消息都移除

644    void removeMessages(Handler h, int what, Object object) {
645        if (h == null) {
646            return;
647        }
648
649        synchronized (this) {
650            Message p = mMessages;
                  //消息队列头消息
651
652            // Remove all messages at front.
                 //针对头结点就是what的情况,将前面的所有what都移除
653            while (p != null && p.target == h && p.what == what
654                   && (object == null || p.obj == object)) {
655                Message n = p.next;
656                mMessages = n;
657                p.recycleUnchecked();
658                p = n;
659            }
660
661            // Remove all messages after front.
                 //将中间的所有what都移除,适用于what消息夹杂在中间的情况
662            while (p != null) {
663                Message n = p.next;
664                if (n != null) {
665                    if (n.target == h && n.what == what
666                        && (object == null || n.obj == object)) {
667                        Message nn = n.next;
668                        n.recycleUnchecked();
669                        p.next = nn;
670                        continue;
671                    }
672                }
673                p = n;
674            }
675        }
676    }

Handler相关

从上面的说明可以发现,对于Service而言,如果Service所在进程的主线程没有执行完相应的Message,没有及时返回结果,那么system_server就会认为Service进程的主线程耗时过长,因此就会使Service所在进程发生ANR;
那么其实我这里就可以想到三种情况
1.确实是Service宿主进程主线程Handler执行这个Service相关操作的Message耗时过长
2.Service宿主进程主线程Handler执行前面的Message耗时过长,导致这个Service操作相关消息迟迟不能被取出执行
(注意,一个线程对应一个Looper,一个MessageQueue,但不止一个Handler,线程可以创建多个Handler可以共用一个Looper,Looper.loop不断取出MessageQueue中的消息,发送给对应的Handler进行执行)
3.执行完这个Message需要向AMS回调serviceDoneExecuting,那么
3.1 可能system_server找不到空闲的binder线程
3.2 找到了空闲binder线程,但其需要的AMS锁被其他binder线程持有

同时,可以发现ANR原理的分析需要Handler的相关知识,本文重点介绍下

Handler的构造


109    /**
110     * Default constructor associates this handler with the {@link Looper} for the
111     * current thread.
112     *
113     * If this thread does not have a looper, this handler won't be able to receive messages
114     * so an exception is thrown.
115     */
116    public Handler() {
117        this(null, false);
118    }

将当前线程中的looper赋给final Looper mLooper

一个线程只有一个looper,但不一定只有一个Handler,可以写多个Handler用来处理不同的Message,looper对决定将消息交给哪个Handler去处理;当一个消息处理完后处理下一个;

比如,一个进程的主线程Handler,除了ActivityThread$H之外,还可以自己定义,如:

6public class MainHandler {
7    private static final Handler sMainHandler = new Handler(Looper.getMainLooper()); //为进程的主线程创建一个MainHandler
8
9    private MainHandler() {}
10
11    public static Handler getMainHandler() {
12        return sMainHandler;
13    }
14}
22    public static void show(final String text) {
23        Handler handler = new Handler(Looper.getMainLooper());
          //MainHandler.post (包装成消息发送,执行)
24        handler.post(new Runnable() {
25            @Override
26            public void run() {
27                if (sToast == null) {
28                    sToast = Toast.makeText(FileExplorerApplication.getInstance().getApplicationContext(), text, Toast.LENGTH_SHORT);
29                } else {
30                    sToast.setText(text);
31                    sToast.setDuration(Toast.LENGTH_SHORT);
32                }
33
34                sToast.show();
35            }
36        });
37    }

getMainLooper的实现如下:

123    /**
124     * Returns the application's main looper, which lives in the main thread of the application.
125     */
126    public static Looper getMainLooper() {
127        synchronized (Looper.class) {
128            return sMainLooper;
129        }
130    }

sMainLooper在Looper.java中的prepareMainLooper中被赋值

103    /**
104     * Initialize the current thread as a looper, marking it as an
105     * application's main looper. The main looper for your application
106     * is created by the Android environment, so you should never need
107     * to call this function yourself.  See also: {@link #prepare()}
108     */
109    public static void prepareMainLooper() {
110        prepare(false);
111        synchronized (Looper.class) {
112            if (sMainLooper != null) {
113                throw new IllegalStateException("The main Looper has already been prepared.");
114            }
115            sMainLooper = myLooper();
120        }
121    }

在ActivityThread中被调用

6760    public static void main(String[] args) {
              ...
6778
6779        Looper.prepareMainLooper();
             ...
6809    }

Handler传递消息

343    /**
344     * Causes the Runnable r to be added to the message queue.
345     * The runnable will be run on the thread to which this handler is
346     * attached.
347     *
348     * @param r The Runnable that will be executed.
349     *
350     * @return Returns true if the Runnable was successfully placed in to the
351     *         message queue.  Returns false on failure, usually because the
352     *         looper processing the message queue is exiting.
353     */
354    public final boolean post(Runnable r)
355    {
356       return  sendMessageDelayed(getPostMessage(r), 0);
357    }
778    private static Message getPostMessage(Runnable r) {
779        Message m = Message.obtain();
780        m.callback = r; //post(Runnable r) 相当于也是创建消息,将消息的Callback赋值
781        return m;
782    }

消息入队的操作

frameworks/base/core/java/android/os/Handler.java
689    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
690        MessageQueue queue = mQueue;
691        if (queue == null) {
692            RuntimeException e = new RuntimeException(
693                    this + " sendMessageAtTime() called with no mQueue");
694            Log.w("Looper", e.getMessage(), e);
695            return false;
696        }
697        return enqueueMessage(queue, msg, uptimeMillis);
698    }
 
 
740    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
741        msg.target = this;
742        if (mAsynchronous) {
743            msg.setAsynchronous(true);
744        }
745        return queue.enqueueMessage(msg, uptimeMillis);
746    }

frameworks/base/core/java/android/os/MessageQueue.java
    boolean enqueueMessage(Message msg, long when) {
537        if (msg.target == null) {
538            throw new IllegalArgumentException("Message must have a target.");
539        }
540        if (msg.isInUse()) {
541            throw new IllegalStateException(msg + " This message is already in use.");
542        }
543
544        synchronized (this) {
545            if (mQuitting) {
546                IllegalStateException e = new IllegalStateException(
547                        msg.target + " sending message to a Handler on a dead thread");
548                Log.w(TAG, e.getMessage(), e);
549                msg.recycle();
550                return false;
551            }
552
553            msg.markInUse();
554            msg.when = when;
555            Message p = mMessages; //mMessages这个值代表MessageQueue的队头,可以为null,为null时代表当前队列为空
556            boolean needWake;
557            if (p == null || when == 0 || when < p.when) {
558                // New head, wake up the event queue if blocked.
                   //1.当前队列为空 2.或者Message需要立即执行 3.Message的执行时间比当前队列的头Message的执行时间还要前
559                msg.next = p; 
560                mMessages = msg; //将入队Message置为头节点
561                needWake = mBlocked; //如果入队前队列为空,或者入队Message为队头,可能需要唤醒queue,根据mBlocked属性决定
562            } else {
563                // Inserted within the middle of the queue.  Usually we don't have to wake
564                // up the event queue unless there is a barrier at the head of the queue
565                // and the message is the earliest asynchronous message in the queue.
566                needWake = mBlocked && p.target == null && msg.isAsynchronous(); //如果当前队列卡住,队头为屏障消息,则只有异步消息能唤醒队列
567                Message prev;
568                for (;;) {
569                    prev = p; //prev保存队头
570                    p = p.next;
571                    if (p == null || when < p.when) {
                           //找到了Message合适的插入位置就停下来
572                        break;
573                    }
574                    if (needWake && p.isAsynchronous()) {
575                        needWake = false;
576                    }
577                }
578                msg.next = p; // invariant: p == prev.next
579                prev.next = msg; //插入到适当位置
                   //将msg插入到prev和p之间
580            }
581
582            // We can assume mPtr != 0 because mQuitting is false.
583            if (needWake) {
584                nativeWake(mPtr); //唤醒队列
585            }
586        }
587        return true;
588    }

Handler执行消息
Looper.loop 线程的loop循环执行

Looper.loop
137    public static void loop() {
138        final Looper me = myLooper();
          ...
142        final MessageQueue queue = me.mQueue;
143
           ...
158
159        for (;;) {
160            Message msg = queue.next(); // might block //从队列中取出消息
               ...
192            try {
193                msg.target.dispatchMessage(msg); //找到消息后,调用消息对应的Handler的dispatchMessage
194                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
195            } finally {
196                if (traceTag != 0) {
197                    Trace.traceEnd(traceTag);
198                }
199            }
               ...
233            msg.recycleUnchecked(); //消息回收
234        }
235    }

首先看取出的消息如何处理

96    public void dispatchMessage(Message msg) {
97        if (msg.callback != null) {
98            handleCallback(msg);
99        } else {
100            if (mCallback != null) {
101                if (mCallback.handleMessage(msg)) {
102                    return;
103                }
104            }
105            handleMessage(msg);
106        }
107    }

dispatch Message处理消息也有3种情况

情况1:消息中含有Callback,一般是通过post传递的Runnable对象被封装成的消息;

相当于只要Runnable被当作消息取出来了,就会执行其run方法

791    private static void handleCallback(Message message) {
792        message.callback.run();
793    }

情况2:Handler初始化时赋值了一个Callback

130    public Handler(Callback callback) {
131        this(callback, false);
132    }

示例:

68        @TargetApi(Build.VERSION_CODES.CUPCAKE)
69        public void execute() {
70            mHandler = new Handler(new Handler.Callback(){
71                @Override
72                public boolean handleMessage(Message msg) {
73                    switch (msg.what) {
74                        case REQUEST_DATA_CACHEED: {
75                            if (mListener != null) mListener.onCacheGot(mResponse);
76                            break;
77                        }
78                        case REQUEST_DATA_LOADED: {
79                            if (mListener != null) mListener.onDataStatusChanged(mResponse);
80                            break;
81                        }
82                        default:
83                            break;
84                    }
85                    return true;
86                }
87            });
88            ThreadDispatcher.getInstance().runInBackgroud(this);
89        }

则消息被从队列中取出时,会执行Handler中的mCallback的handleMessage方法

情况3:消息和Handler都没有被赋值Callback,因此就需要调用Handler重载的handleMessage方法

示例:

111    private class MainHandler extends Handler {
112        private static final int MSG_INFO_UPDATED = 1;
113
114        @Override
115        public void handleMessage(Message msg) {
116            switch (msg.what) {
117                case MSG_INFO_UPDATED:
118                    mCallback.onExtraInfoUpdated();
119                    break;
120            }
121        }
122    }

Looper取出MessageQueue中的消息

最后看一下Message如何从消息队列中取出:

315    Message next() {
316        // Return here if the message loop has already quit and been disposed.
317        // This can happen if the application tries to restart a looper after quit
318        // which is not supported.
319        final long ptr = mPtr;
320        if (ptr == 0) {
321            return null;
322        }
323
324        int pendingIdleHandlerCount = -1; // -1 only during first iteration
325        int nextPollTimeoutMillis = 0;
326        for (;;) {
327            if (nextPollTimeoutMillis != 0) {
328                Binder.flushPendingCommands();
329            }
330
331            nativePollOnce(ptr, nextPollTimeoutMillis);
                 //nextPollTimeoutMillis 队列为空时一直等待,直到被唤醒(下一个Message入队)
332
333            synchronized (this) {
334                // Try to retrieve the next message.  Return if found.
335                final long now = SystemClock.uptimeMillis();
336                Message prevMsg = null;
337                Message msg = mMessages; //链表头
338                if (msg != null && msg.target == null) {
                          //如果链表头是一个屏障消息
339                    // Stalled by a barrier.  Find the next asynchronous message in the queue. //消息屏障(对于非异步消息而言,当有消息屏障时,岂不到唤醒队列的作用)
340                    do {
                             //那么msg只能找到异步消息
341                        prevMsg = msg;
342                        msg = msg.next;
343                    } while (msg != null && !msg.isAsynchronous());
344                }
                     //如果没有屏障消息,此时msg还是队头Message
345                if (msg != null) {
346                    if (now < msg.when) {
                              //当前时间小于队头Message需要执行的时间,还需要再等一段时间
347                        // Next message is not ready.  Set a timeout to wake up when it is ready.
348                        nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
349                    } else {
350                        // Got a message.
                              //返回队头Message
351                        mBlocked = false; //当可以得到一个Message返回时,将mBlocked置为false,表明此时队列不再阻塞了
352                        if (prevMsg != null) {
                                  //针对有屏障的情况,重新组织MessageQueue队列
353                            prevMsg.next = msg.next;
354                        } else {
                                 //将 mMessages 设为msg.next,这样就可以把队头Message返回
355                            mMessages = msg.next;
356                        }
                              //返回要执行的Message
357                        msg.next = null;
358                        if (DEBUG) Log.v(TAG, "Returning message: " + msg);
359                        msg.markInUse();
360                        return msg;
361                    }
362                } else {
363                    // No more messages.
364                    nextPollTimeoutMillis = -1;
365                }
366
367                // Process the quit message now that all pending messages have been handled.
368                if (mQuitting) {
369                    dispose();
370                    return null;
371                }
372
373                // If first time idle, then get the number of idlers to run.
374                // Idle handles only run if the queue is empty or if the first message
375                // in the queue (possibly a barrier) is due to be handled in the future.
376                if (pendingIdleHandlerCount < 0
377                        && (mMessages == null || now < mMessages.when)) {
378                    pendingIdleHandlerCount = mIdleHandlers.size();
379                }
380                if (pendingIdleHandlerCount <= 0) {
381                    // No idle handlers to run.  Loop and wait some more.
                          //除非顺利返回了Message,否则 nextPollTimeoutMillis >0或-1,分别代表首个Message没到时间或队列为空,此时队列阻塞,并进入下一个等待
382                    mBlocked = true; 
383                    continue;
384                }
385
386                if (mPendingIdleHandlers == null) {
387                    mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
388                }
389                mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
390            }
391
392            // Run the idle handlers.
393            // We only ever reach this code block during the first iteration.
394            for (int i = 0; i < pendingIdleHandlerCount; i++) {
395                final IdleHandler idler = mPendingIdleHandlers[i];
396                mPendingIdleHandlers[i] = null; // release the reference to the handler
397
398                boolean keep = false;
399                try {
400                    keep = idler.queueIdle();
401                } catch (Throwable t) {
402                    Log.wtf(TAG, "IdleHandler threw exception", t);
403                }
404
405                if (!keep) {
406                    synchronized (this) {
407                        mIdleHandlers.remove(idler);
408                    }
409                }
410            }
411
412            // Reset the idle handler count to 0 so we do not run them again.
413            pendingIdleHandlerCount = 0;
414
415            // While calling an idle handler, a new message could have been delivered
416            // so go back and look again for a pending message without waiting.
417            nextPollTimeoutMillis = 0;
418        }
419    }

nativePollOnce

frameworks/base/core/jni/android_os_MessageQueue.cpp
212static const JNINativeMethod gMessageQueueMethods[] = {
213    /* name, signature, funcPtr */
       ...
216    { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce },
217    { "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake },
       ...
221};
 
 
188static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
189        jlong ptr, jint timeoutMillis) {
190    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
191    nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
192}
 
 
107void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
108    mPollEnv = env;
109    mPollObj = pollObj;
110    mLooper->pollOnce(timeoutMillis);
111    mPollObj = NULL;
112    mPollEnv = NULL;
    ...
119}
 
 
/system/core/libutils/Looper.cpp
178int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
179    int result = 0;
180    for (;;) {
181        while (mResponseIndex < mResponses.size()) {
182            const Response& response = mResponses.itemAt(mResponseIndex++);
183            int ident = response.request.ident;
184            if (ident >= 0) {
185                int fd = response.request.fd;
186                int events = response.events;
187                void* data = response.request.data;
188#if DEBUG_POLL_AND_WAKE
189                ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
190                        "fd=%d, events=0x%x, data=%p",
191                        this, ident, fd, events, data);
192#endif
193                if (outFd != NULL) *outFd = fd;
194                if (outEvents != NULL) *outEvents = events;
195                if (outData != NULL) *outData = data;
196                return ident;  //针对回调函数为空的情况,ident值必为一个大于等于0的值
197            }
198        }
199
200        if (result != 0) {
201#if DEBUG_POLL_AND_WAKE
202            ALOGD("%p ~ pollOnce - returning result %d", this, result);
203#endif
204            if (outFd != NULL) *outFd = 0;
205            if (outEvents != NULL) *outEvents = 0;
206            if (outData != NULL) *outData = NULL;
207            return result; //根据pollInner的结果进行处理,实际上是针对设置了回调函数的情况,因为设置了回调函数,所以已经对发生的事件做了处理了,所以,不需要将发生事件的相关信息再返回给调用者了
208        }
209
210        result = pollInner(timeoutMillis);
211    }
212}
 
 
214int Looper::pollInner(int timeoutMillis) {
215#if DEBUG_POLL_AND_WAKE
216    ALOGD("%p ~ pollOnce - waiting: timeoutMillis=%d", this, timeoutMillis);
217#endif
218
219    // Adjust the timeout based on when the next message is due.
220    if (timeoutMillis != 0 && mNextMessageUptime != LLONG_MAX) {
221        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
222        int messageTimeoutMillis = toMillisecondTimeoutDelay(now, mNextMessageUptime);
223        if (messageTimeoutMillis >= 0
224                && (timeoutMillis < 0 || messageTimeoutMillis < timeoutMillis)) {
225            timeoutMillis = messageTimeoutMillis; //重新计算超时时间
226        }
227#if DEBUG_POLL_AND_WAKE
228        ALOGD("%p ~ pollOnce - next message in %" PRId64 "ns, adjusted timeout: timeoutMillis=%d",
229                this, mNextMessageUptime - now, timeoutMillis);
230#endif
231    }
232
233    // Poll.
234    int result = POLL_WAKE;
235    mResponses.clear();
236    mResponseIndex = 0;
237
238    // We are about to idle.
239    mPolling = true;
240
241    struct epoll_event eventItems[EPOLL_MAX_EVENTS];
242    int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
243
244    // No longer idling.
245    mPolling = false;
246
247    // Acquire lock.
248    mLock.lock();
249
250    // Rebuild epoll set if needed.
251    if (mEpollRebuildRequired) {
252        mEpollRebuildRequired = false;
253        rebuildEpollLocked();
254        goto Done;
255    }
256
257    // Check for poll error.
258    if (eventCount < 0) { //返回值小于零,表示发生错误
259        if (errno == EINTR) {
260            goto Done;
261        }
262        ALOGW("Poll failed with an unexpected error: %s", strerror(errno));
263        result = POLL_ERROR;
264        goto Done;
265    }
266
267    // Check for poll timeout.
268    if (eventCount == 0) { //eventCount为零,表示发生超时,因此直接跳转到Done
269#if DEBUG_POLL_AND_WAKE
270        ALOGD("%p ~ pollOnce - timeout", this);
271#endif
272        result = POLL_TIMEOUT;
273        goto Done;
274    }
275
276    // Handle all events.
277#if DEBUG_POLL_AND_WAKE
278    ALOGD("%p ~ pollOnce - handling events from %d fds", this, eventCount);
279#endif
280
281    for (int i = 0; i < eventCount; i++) {
282        int fd = eventItems[i].data.fd;
283        uint32_t epollEvents = eventItems[i].events;
284        if (fd == mWakeEventFd) {
285            if (epollEvents & EPOLLIN) {
                   //通过wake唤醒队列
286                awoken();
287            } else {
288                ALOGW("Ignoring unexpected epoll events 0x%x on wake event fd.", epollEvents);
289            }
290        } else {
291            ssize_t requestIndex = mRequests.indexOfKey(fd);
292            if (requestIndex >= 0) {
293                int events = 0;
294                if (epollEvents & EPOLLIN) events |= EVENT_INPUT;
295                if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT;
296                if (epollEvents & EPOLLERR) events |= EVENT_ERROR;
297                if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP;
298                pushResponse(events, mRequests.valueAt(requestIndex)); //如果是其他FD发生事件,则根据Request构造Response,并push到Response数组
                   //当某个监控fd上发生事件后,就会把对应的Request取出来调用。
299            } else {
300                ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is "
301                        "no longer registered.", epollEvents, fd);
302            }
303        }
304    }
305Done: ;
306
307    // Invoke pending message callbacks.
308    mNextMessageUptime = LLONG_MAX;
309    while (mMessageEnvelopes.size() != 0) {
310        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
311        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
312        if (messageEnvelope.uptime <= now) {
313            // Remove the envelope from the list.
314            // We keep a strong reference to the handler until the call to handleMessage
315            // finishes.  Then we drop it so that the handler can be deleted *before*
316            // we reacquire our lock.
317            { // obtain handler
318                sp<MessageHandler> handler = messageEnvelope.handler;
319                Message message = messageEnvelope.message;
320                mMessageEnvelopes.removeAt(0);
321                mSendingMessage = true;
322                mLock.unlock();
323
324#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
325                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
326                        this, handler.get(), message.what);
327#endif
328                handler->handleMessage(message);
329            } // release handler
330
331            mLock.lock();
332            mSendingMessage = false;
333            result = POLL_CALLBACK;
334        } else {
335            // The last message left at the head of the queue determines the next wakeup time.
336            mNextMessageUptime = messageEnvelope.uptime;
337            break;
338        }
339    }
340
341    // Release lock.
342    mLock.unlock();
343
344    // Invoke all response callbacks.
345    for (size_t i = 0; i < mResponses.size(); i++) {
346        Response& response = mResponses.editItemAt(i);
347        if (response.request.ident == POLL_CALLBACK) {
348            int fd = response.request.fd;
349            int events = response.events;
350            void* data = response.request.data;
351#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
352            ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p",
353                    this, response.request.callback.get(), fd, events, data);
354#endif
355            // Invoke the callback.  Note that the file descriptor may be closed by
356            // the callback (and potentially even reused) before the function returns so
357            // we need to be a little careful when removing the file descriptor afterwards.
358            int callbackResult = response.request.callback->handleEvent(fd, events, data);//回调其他fd定义的callback
359            if (callbackResult == 0) {
360                removeFd(fd, response.request.seq);
361            }
362
363            // Clear the callback reference in the response structure promptly because we
364            // will not clear the response vector itself until the next poll
365            response.request.callback.clear();
366            result = POLL_CALLBACK;
367        }
368    }
369    return result;
370}

有消息入队时的wake操作,唤醒队列,nativePollOnce不再等待,相当于提醒MessageQueue有消息入队了,但是否现在执行,需要根据消息中的信息,由MessageQueue.next()决定

唤醒操作如下:

enqueueMessage中
583            if (needWake) {
584                nativeWake(mPtr);
585            }
 
 
194static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
195    NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
196    nativeMessageQueue->wake();
197}
 
 
121void NativeMessageQueue::wake() {
122    mLooper->wake();
123}
 
398void Looper::wake() {
399#if DEBUG_POLL_AND_WAKE
400    ALOGD("%p ~ wake", this);
401#endif
402
403    uint64_t inc = 1;
404    ssize_t nWrite = TEMP_FAILURE_RETRY(write(mWakeEventFd, &inc, sizeof(uint64_t)));
405    if (nWrite != sizeof(uint64_t)) {
406        if (errno != EAGAIN) {
407            LOG_ALWAYS_FATAL("Could not write wake signal to fd %d: %s",
408                    mWakeEventFd, strerror(errno));
409        }
410    }
411}

Looper.loop()中是个for循环,必须等到一个Message执行完了,才有机会回到MessageQueue.next()来查找下一个待执行的Message;所以,前面的Message处理超时,也会造成ANR;关键要找到真正耗时的消息,以及其耗时的原因;

总结

本文主要介绍了android的Handler机制,这对我们理解ANR的原理很有帮助

上一篇下一篇

猜你喜欢

热点阅读