简述:

继续Android Handler揭秘(二),这里来继续分析MessageQueue.java对应在Native层的android_os_MessageQueue。

相关代码:

/frameworks/base/core/jni/android_os_MessageQueue.cpp
/frameworks/base/core/java/android/os/MessageQueue.java
/system/core/libutils/Looper.cpp

正文:

先来看android_os_MessageQueue的JNI注册代码:

frameworks/base/core/jni/android_os_MessageQueue.cpp     //对应MessageQueue.java里面的native方法212  static const JNINativeMethod gMessageQueueMethods[] = {213      /* name, signature, funcPtr */214      { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit },215      { "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy },216      { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce },217      { "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake },218      { "nativeIsPolling", "(J)Z", (void*)android_os_MessageQueue_nativeIsPolling },219      { "nativeSetFileDescriptorEvents", "(JII)V",220              (void*)android_os_MessageQueue_nativeSetFileDescriptorEvents },221  };222  223  int register_android_os_MessageQueue(JNIEnv* env) {224      int res = RegisterMethodsOrDie(env, "android/os/MessageQueue", gMessageQueueMethods,225                                     NELEM(gMessageQueueMethods));226  227      jclass clazz = FindClassOrDie(env, "android/os/MessageQueue");228      gMessageQueueClassInfo.mPtr = GetFieldIDOrDie(env, clazz, "mPtr", "J");//Java层保存的指针229      gMessageQueueClassInfo.dispatchEvents = GetMethodIDOrDie(env, clazz,230              "dispatchEvents", "(II)I");//用来回调Java层的dispatchEvents方法231  232      return res;233  }

在MessageQueue.java的构造函数里面,就会调用nativeInit方法:

70      MessageQueue(boolean quitAllowed) {71          mQuitAllowed = quitAllowed;72          mPtr = nativeInit();//保存了NativeMessageQueue的指针73      }

对应android_os_MessageQueue_nativeInit:

172  static jlong android_os_MessageQueue_nativeInit(JNIEnv* env, jclass clazz) {173      NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();174      if (!nativeMessageQueue) {175          jniThrowRuntimeException(env, "Unable to allocate native queue");176          return 0;177      }178  179      nativeMessageQueue->incStrong(env);//强引用180      return reinterpret_cast(nativeMessageQueue);//返回指针181  }

再来继续看NativeMessageQueue的构造函数:

78  NativeMessageQueue::NativeMessageQueue() :79          mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {80      mLooper = Looper::getForThread();//确保单例,每个线程只会有一个Looper对象81      if (mLooper == NULL) {//如果这个线程没有绑定Looper对象,就new一个。82          mLooper = new Looper(false);83          Looper::setForThread(mLooper);84      }85  }

这里又有一个Looper,在前面文章里面提到过,Java层也有一个Looper,每个线程只有一个Looper对象。那这里的Looper是不是也是一样?来看看Looper::getForThread()函数:

system/core/libutils/Looper.cpp109  sp Looper::getForThread() {110      int result = pthread_once(& gTLSOnce, initTLSKey);111      LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");112  113      return (Looper*)pthread_getspecific(gTLSKey);114  }

这里又是一个TLS的应用,保证每个线程只有一个Looper对象。换一个说法就是:以线程为单位的单例模式。

在前一篇文章中,enqueueMessage方法里面,有调用一个nativeWake(mPtr),现在来继续分析这个nativeWake的流程。

nativeWake最终调用到Looper.cpp里面的wake函数:

/system/core/libutils/Looper.cpp398  void Looper::wake() {399  #if DEBUG_POLL_AND_WAKE400      ALOGD("%p ~ wake", this);401  #endif402  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  }

很简单,就是往mWakeEventFd里面写了一个1。mWakeEventFd是什么?谁又会监听这个mWakeEventFd。顺着mWakeEventFd的赋值的地方和使用的地方来分析。先看赋值的地方:

/system/core/libutils/Looper.cpp63  Looper::Looper(bool allowNonCallbacks) :64          mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false),65          mPolling(false), mEpollFd(-1), mEpollRebuildRequired(false),66          mNextRequestSeq(0), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) {67      mWakeEventFd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);//创建EventFd68      LOG_ALWAYS_FATAL_IF(mWakeEventFd < 0, "Could not make wake event fd: %s",69                          strerror(errno));70  71      AutoMutex _l(mLock);72      rebuildEpollLocked();//重点73  }

mWakeEventFd赋值很简单,在Looper构造函数里面建了一个eventfd。继续看用这个mWakeEventFd的地方:

134  void Looper::rebuildEpollLocked() {135      // Close old epoll instance if we have one.136      if (mEpollFd >= 0) {137  #if DEBUG_CALLBACKS138          ALOGD("%p ~ rebuildEpollLocked - rebuilding epoll set", this);139  #endif140          close(mEpollFd);141      }142  143      // Allocate the new epoll instance and register the wake pipe.144      mEpollFd = epoll_create(EPOLL_SIZE_HINT);145      LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));146           //封装唤醒mWakeEventFd,加入到mEpollFd。147      struct epoll_event eventItem;148      memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union149      eventItem.events = EPOLLIN;150      eventItem.data.fd = mWakeEventFd;151      int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, & eventItem);152      LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake event fd to epoll instance: %s",153                          strerror(errno));154           //封装mRequests成struct epoll_event,加入到mEpollFd里面。155      for (size_t i = 0; i < mRequests.size(); i++) {156          const Request& request = mRequests.valueAt(i);157          struct epoll_event eventItem;158          request.initEventItem(&eventItem);159  160          int epollResult = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, request.fd, & eventItem);161          if (epollResult < 0) {162              ALOGE("Error adding epoll events for fd %d while rebuilding epoll set: %s",163                    request.fd, strerror(errno));164          }165      }166  }

       新建了mWakeEventFd后,封装成struct epoll_event,通过EPOLL_CTL_ADD的方式,加入mEpollFd。这样,mEpollFd就可以知道mWakeEventFd有消息了。这里也同时把mRequests封装,加入了mEpollFd里面监听。

       到这里epoll终于露面了,先简单介绍epoll。epoll是linux平台上,最高效的I/O复用机制,可以在同一个地方监听多个文件句柄的I/O事件。

        

 

更多相关文章

  1. 箭头函数的基础使用
  2. Python技巧匿名函数、回调函数和高阶函数
  3. 调试android通过jni调用的C++代码
  4. gradle-xxx.jar下载地址和gradle-xxx.zip下载地址
  5. USB UMS MTP设置过程 (二) UsbDeviceManager.java
  6. android 5.1禁止休眠
  7. Android应用程序组件Content Provider的共享数据更新通知机制分
  8. Android平台开发-Android(安卓)keypad map-Android按键事件
  9. Android进程和线程(Android开发指南--译)

随机推荐

  1. 第四章 Android开发三大基石—Activity、
  2. Android中的观察者模式简单使用
  3. Android(安卓)Selector用法小记
  4. Android——使用ContentProvider在应用间
  5. Android的Drawable和Bitmap之间相关转换
  6. Android中的多线程机制
  7. React Native -1环境搭建(macOS--Android)
  8. Android之Menu选项菜单
  9. android 3D系列之光效篇
  10. View的刷新机制