Android Native层异步消息处理框架

一、前言

  在NuPlayer中,可以发现许多类似于下面的代码:

 1 //=======================================//
 2 NuPlayerDriver::NuPlayerDriver(pid_t pid)
 3     : ......
 4      mLooper(new ALooper)
 5       ......{
 6     mLooper->setName("NuPlayerDriver Looper");
 7     mLooper->start(
 8             false, /* runOnCallingThread */
 9             true,  /* canCallJava */
10             PRIORITY_AUDIO);
11
12     mPlayer = new NuPlayer(pid);
13     mLooper->registerHandler(mPlayer)
14 }
15
16 //=======================================//
17 sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
18 msg->setInt32("generation", ++mSeekGeneration);
19 msg->setInt64("timeUs", seekTimeUs);
20 status_t err = msg->postAndAwaitResponse(&response);
21
22 //=======================================//
23 void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
24     switch (what) {
25         case XXX:
26         case YYY:
27         ......
28         default:
29     }
30 }

  这就是android在native层实现的一个异步消息处理机制,在这个机制中所有的处理都是异步的。其基本的处理流程可概述如下:

  • 将变量封装到一个消息AMessage结构体中,然后放到消息队列中去,后台专门有一个线程会从这个队列中取出消息并发送给指定的AHandler处理,在handler的onMessageReceived函数中根据AMessage的mWhat字段转向对应的分支进行处理。

  在这里我们可能会产生这样的疑问:在很多类中都会有各种消息post出来,而后台的异步消息处理线程又是怎么知道将一个消息发送给哪个类的onMessageReceived函数处理呢?

  要搞明白这个问题,就需要分析android在native层的异步消息处理框架。

二、基础类分析

  在android native层的异步消息处理框架中涉及到的类主要有:ALooper、AHandler、AMessage、ALooperRoster、LooperThread等。

  在android开源代码中,这些类的声明头文件位于:/frameworks/av/include/media/stagefright/foundation/ ,实现功能的源代码位于:/frameworks/av/media/libstagefright/foundation/ ,下面就分别对这些类进行分析。

  1、AMessage -- 消息的载体

  结构体AMessage是消息的载体,在传递消息的过程中可以携带各种信息。

 1 //AMessage类简析
 2 struct AMessage : public RefBase {
 3     //构造函数,在其中会对AMessage的两个重要数据成员mWhat和mTarget进行初始化设置。
 4     AMessage();
 5     AMessage(uint32_t what, const sp<const AHandler> &handler);
 6     void setWhat(uint32_t what);//设置mWhat
 7     uint32_t what() const;//返回mWhat
 8     void setTarget(const sp<const AHandler> &handler);//设置mTarget
 9     //一系列的set和find函数,用于在传递消息的过程中携带各种信息
10     void setInt32(const char *name, int32_t value);
11     void setInt64(const char *name, int64_t value);
12     //....
13     bool findInt32(const char *name, int32_t *value) const;
14     bool findInt64(const char *name, int64_t *value) const;
15     //投递消息到消息队列中
16     status_t post(int64_t delayUs = 0);
17     // Posts the message to its target and waits for a response (or error) before returning.
18     status_t postAndAwaitResponse(sp<AMessage> *response);
19 protected:
20     virtual ~AMessage();//析构函数
21 private:
22     friend struct ALooper; // deliver()
23     //两个重要的私有数据成员:
24     //mWhat指明这是一个什么消息,用于在onMessageReceived处理分支中进行匹配。
25     //mTarget用于后台线程在处理这个消息时判断发送给哪一个类处理。
26     uint32_t mWhat;
27     ALooper::handler_id mTarget;
28
29     wp<AHandler> mHandler;
30     wp<ALooper> mLooper;

  进一步分析AMessage对象的构造函数,首先我们查看AMessage的source code,如下:

 1 AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
 2     : mWhat(what),
 3       mNumItems(0) {
 4     setTarget(handler);
 5 }
 6
 7 void AMessage::setTarget(const sp<const AHandler> &handler) {
 8     if (handler == NULL) {
 9         mTarget = 0;
10         mHandler.clear();
11         mLooper.clear();
12     } else {
13         mTarget = handler->id();
14         mHandler = handler->getHandler();
15         mLooper = handler->getLooper();
16     }
17 }

  在构造函数中设置mWhat的值为指定的what值,用于指明这是一个什么消息,以便在onMessageReceived函数中找到匹配的分支进行处理。然后会调用setTarget函数,来设置mTarget为指定handler的mID值,mHandler为指定的handler,mLooper为与handler相关的ALooper,这样后台处理线程就可以据此判断将该消息发送给哪一个类(handler)进行处理了。

  构造消息并投递出去的过程,如下示例:

1 void NuPlayer::start() {
2     (new AMessage(kWhatStart, this))->post();
3 }

  2、ALooper类

  这个类定义了消息循环和后台处理线程。

 1 //ALooper类简析
 2 struct ALooper : public RefBase {
 3     //定义的两个整型变量类型
 4     typedef int32_t event_id;//event id
 5     typedef int32_t handler_id;//handler id
 6
 7     ALooper();//构造函数
 8
 9     // Takes effect in a subsequent call to start().
10     void setName(const char *name);
11
12     handler_id registerHandler(const sp<AHandler> &handler);//注册handler
13     void unregisterHandler(handler_id handlerID);//注销handler
14     //启动后台处理线程处理事件
15     status_t start(
16             bool runOnCallingThread = false,
17             bool canCallJava = false,
18             int32_t priority = PRIORITY_DEFAULT
19             );
20 protected:
21     virtual ~ALooper();
22 private:
23     friend struct AMessage;       // post()
24     //事件的结构体封装
25     struct Event {
26         int64_t mWhenUs;
27         sp<AMessage> mMessage;
28     };
29     AString mName;
30     List<Event> mEventQueue;
31     struct LooperThread;
32     sp<LooperThread> mThread;//后台处理线程
33     // posts a message on this looper with the given timeout
34     void post(const sp<AMessage> &msg, int64_t delayUs);
35     bool loop();
36 }

  3、LooperThread

  4、AHandler -- 消息处理类的父类

  AHandler类用于对接收到的消息进行对应的处理。下面我们结合source code进行分析如下:

 1 struct AHandler : public RefBase {
 2     AHandler()    //构造函数
 3         : mID(0),    //初始化mID为0
 4           mVerboseStats(false),
 5           mMessageCounter(0) {
 6     }
 7
 8     ALooper::handler_id id() const {//这个函数用于返回内部变量mID的值,其初始值为0,但是可以通过setID()设置
 9         return mID;
10     }
11
12
13 protected:
14     virtual void onMessageReceived(const sp<AMessage> &msg) = 0;
15
16 private:
17     friend struct AMessage;      // deliverMessage()
18     friend struct ALooperRoster; // setID()
19
20     ALooper::handler_id mID;
21     wp<ALooper> mLooper;
22     //setID()在其友元类ALooperRoster的registerHandler()函数中调用。
23     inline void setID(ALooper::handler_id id, wp<ALooper> looper) {
24         mID = id;
25         mLooper = looper;
26     }
27
28 };

  5、ALooperRoster类

  ALooperRoster可以看做是ALooper的一个辅助类,主要用于完成消息handler的注册与注销工作。下面结合source code分析如下:

三、异步消息处理框架

  首先我们先copy一段代码来看一看异步消息处理框架的搭建过程:

1 sp<ALooper> mLooper;
2 mLooper(new ALooper)//构造函数的初始化列表中
3 mLooper->setName("NuPlayerDriver Looper");
4 mLooper->start(false, true, PRIORITY_AUDIO);
5 mPlayer = new NuPlayer;// struct NuPlayer : public AHandler
6 mLooper->registerHandler(mPlayer);

  搭建框架1

  调用ALooper的构造函数,实例化一个新的ALooper对象:

1 ALooper::ALooper()
2     : mRunningLocally(false) {
3     // clean up stale AHandlers. Doing it here instead of in the destructor avoids
4     // the side effect of objects being deleted from the unregister function recursively.
5     gLooperRoster.unregisterStaleHandlers();
6 }

  搭建框架2

  调用ALooper::setName(const char *name)设置ALooper的名字:

1 void ALooper::setName(const char *name) {
2     mName = name;
3 }

  搭建框架3

  调用ALooper::start()启动异步消息处理后台线程:

 1 status_t ALooper::start(
 2         bool runOnCallingThread, bool canCallJava, int32_t priority) {
 3     // ......
 4
 5     if (mThread != NULL || mRunningLocally) {
 6         return INVALID_OPERATION;
 7     }
 8     mThread = new LooperThread(this, canCallJava);//构造LooperThread对象
 9     status_t err = mThread->run( //run()之后就会执行LooperThread::threadLooper()函数,在threadlooper()函数中又会调用ALooper::loop()函数
10             mName.empty() ? "ALooper" : mName.c_str(), priority);
11     if (err != OK) {
12         mThread.clear();
13     }
14     return err;
15 }

  搭建框架4

  调用ALooper::registerHandler()注册消息处理器类AHandler:

1 ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
2     return gLooperRoster.registerHandler(this, handler);
3 }

  从这个函数的定义可以看出,能作为handler进行注册的类都必须继承自AHandler这个类,注册的过程也是交给了gLooperRoster处理的。

时间: 2024-07-31 09:17:12

Android Native层异步消息处理框架的相关文章

Android Native层Binder.transact()函数调用 Binder.onTransact() 函数失败分析

Q:Android Native层Binder.transact()函数调用 Binder.onTransact() 函数失败? 在Android Native层调用Camera.h中的api实现一个截屏功能的应用时,发现通过gCamera->setListener(new ScreenCaptureListener())设置到Camera的mListener的用于接收Camera预览数据的回调函数没有被调用,导致截屏失败? 注: Camera类文件汇总: libcamera_client.so

Android native层动态库注射

1.简介 本文讲解在Android native层,root权限下,注射动态库到目标进程,从而hook目标进程中动态库的函数的实现方式.文中的源码全部来源于网络,我只是稍微加以整理. 环境:Android4.2 源码下编译,模拟器中运行. 2.代码构成 包含三个模块的代码: 1.inject程序:把动态库libhookhelper注射到目标进程 2.libhookhelper:动态库代码.此部分代码用于修改目标进程中目标函数所在的got表的信息,从而替换掉目标函数.理解这部分需要一点点elf格式

Android开发之异步消息处理机制Handler

Android中的异步消息处理主要有四个部分组成,Message, Handler, MessageQueue和 Looper. 1.Message. 在线程之间传递的消息,可以内部携带少量的信息,用于在不同线程之间交换数据.可以使用what字段,arg1和arg2携带一些整型数据,obj字段携带一个object对象. 2.Handler. Handler,处理者的意思,它主要用于发送和处理消息的.发送消息一般使用Handler的sendMessage()方法,而发出的消息经过一系列地辗转处理后

Android线程之异步消息处理机制(二)——Message、Handler、MessageQueue和Looper

异步消息处理机制解析 Android中的异步消息处理主要有四个部分组成,Message.Handler.MessageQueue和Looper. 1.Message Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据.上个例子中就使用了Message的what字段,除此之外还可以使用arg1和arg2字段来携带一些整形数据,使用obj字段携带一个Object对象. 2.Handler Handler顾名思义也就是处理者的意思,它主要是用于发送和处理消息的

Android之Handler(异步消息处理)机制

1. 概述 Handler . Looper .Message 这三者都与Android异步消息处理线程相关的概念.那么什么叫异步消息处理线程呢?异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,然后回调相应的消息处理函数,执行完成一个消息后则继续循环.若消息队列为空,线程则会阻塞等待. 说了这一堆,那么和Handler . Looper .Message有啥关系?其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断

Android开发之异步消息处理机制AsyncTask

转自:Android AsyncTask完全解析,带你从源码的角度彻底理解 另外一篇比较详细的博文:http://blog.csdn.net/liuhe688/article/details/6532519 AsyncTask的基本用法 首先来看一下AsyncTask的基本用法,由于AsyncTask是一个抽象类,所以如果我们想使用它,就必须要创建一个子类去继承它.在继承时我们可以为AsyncTask类指定三个泛型参数,这三个参数的用途如下: 1. Params 在执行AsyncTask时需要传

Android笔记:异步消息处理

1. Message Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据.上一小节中我们使用到了Message 的what 字段,除此之外还可以使用arg1 和arg2 字段来携带一些整型数据,使用obj 字段携带一个Object 对象.2. Handler Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的.发送消息一般是使用Handler 的sendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Han

Android线程之异步消息处理机制(一)

Android不允许在子线程中进行UI操作,但是有些时候,我们必须在子线程里去执行一些耗时任务,然后根据任务的执行结果来更新相应的UI控件.对于这种情况,Android提供了一套异步消息处理机制,完美地解决了在子线程中进行UI操作的问题. 主线程: 1.新建Handler对象 2.重写父类handleMessage方法,在这里进行UI操作,此方法的代码在主线程中. 子线程: 1.创建Message对象 2.指定Message的what字段 3.调用handler的sendMessage方法,把m

Android 使用图片异步载入框架Universal Image Loader的问题

使用的Jar包 问题:        optionsm = new DisplayImageOptions.Builder() .displayer(new RoundedBitmapDisplayer(20)) .build();   这里.displayer(new RoundedBitmapDisplayer(20))的时候设置圆角报错,.displayer(new SimpleBitmapDisplayer())这样正常显示图片就不报错.