ANDROID从版本4.2开始提供了一个显示管理服务DisplayManagerService,支持多种显示类型的多个显示器的镜像显示,包括内建的显示类型(本地)、HDMI显示类型以及支持WIFI Display 协议( MIRACAST),实现本地设备在远程显示器上的镜像显示。

整个架构类图如下:

显示管理服务通过DisplayManager提供对外接口,提供的接口包括如下几个:

1 、public Display getDisplay(int displayId)

根据displayId参数获得一个逻辑显示器的信息

2、  public Display[] getDisplays()

获得当前所有有效的逻辑显示器列表

3、public void registerDisplayListener(DisplayListener listener, Handler handler)

登记一个显示监听对象,用来监听显示器的新增、去除或改变通知事件。

4、public void unregisterDisplayListener(DisplayListener listener)

取消先前登记的一个显示监听对象

5、scanWifiDisplays()

启动WIFI显示器的扫描。

6、    public void connectWifiDisplay(String deviceAddress)

根据设备地址连接WIFI显示器

7、public void disconnectWifiDisplay()

断开WIFI显示器

8、    public void renameWifiDisplay(String deviceAddress, String alias)

为WIFI显示器命名

9、public void forgetWifiDisplay(String deviceAddress)

取消先前记忆的WIFI显示器

10、public WifiDisplayStatus getWifiDisplayStatus()

得到当前的WIFI显示器的状态

显示管理系统还与其它系统交互,实现WIFI显示器的发现、WIFI显示器在窗口系统中的登记、窗口内容在WIFI显示器的显示(源端镜像数据的获取、加密、编码,SINK端接收的镜像数据的解码和播放等)等功能。

通过WifiP2pManager接口与WifiP2pService交互,通过WIFI-DIRECT来实现WIFI显示器的自动发现。

窗口管理服务是显示管理服务的监听对象,窗口管理服务通过DisplayManager接口向DisplayManagerService进行登记,当WIFI显示器被发现和连接成功后以及WIFI显示器断开和状态改变后,都会通过回调向窗口管理服务发送事件,窗口管理服务的相应回调函数onDisplayAdded、onDisplayChanged、onDisplayRemoved被调用,用来在窗口系统中进行WIFI显示器的登记以及取消登记、状态改变等处理。

另外DisplayManagerService服务还通过WindowManagerFuncs窗口管理功能接口直接调用窗口管理服务(WindowManagerService是该接口的实现)的函数,实现窗口内容的刷新。同样DisplayManagerService服务还通过InputManagerFuncs接口直接调用输入管理服务的函数setDisplayViewports,用来设置输入系统需要的显示器的显示视图信息。

显示管理系统还通过IMediaPlayerService接口与MediaPlayerService服务交互。

如调用MediaPlayerService服务的listenForRemoteDisplay函数,用来在媒体服务中实例化一个远端显示器的本地代理对象RemoteDisplay,显示系统通过IRemoteDisplay接口调用媒体服务,目前IRemoteDisplay接口只有dispose一个接口函数,用来断开远端显示器,停止监听新的连接。

显示管理系统的WifiDisplaySource对象还调用MediaPlayerService服务的makeHDCP函数来实例化一个HDCP对象并返回给显示系统一个IHDCP接口,用来实现HDCP加密服务。

显示系统的SINK端的TunnelRenderer对象在其initPlayer中还调用MediaPlayerService服务的create函数来创建一个MediaPlayer对象,并返回一个IMediaPlayer接口给显示系统使用,用来实现SINK端接收的镜像数据的播放。

显示管理系统源端获取的镜像数据经过音视频编码(H264),然后进行HDCP加密和PES packetization及TS流化(转换为TS流)后 ,最后打包成RTP包经过UDP通道发送到SINK端,SINK端要经过相反的处理过程,从UDP通道接收RTP包,然后进行TS解析和PES去packetization化和HDCP解密,最后送给解码器进行解码。解码后的数据送给播放器的呈现器进行呈现。

源端和SINK端的音视频编解码都通过IOMX接口与底层的多媒体框架交互,实现音视频编解码功能。IOMX接口对应的对象OMX也是在MediaPlayerService服务端实例化的,在客户端对象OMXClient的connect函数中通过调用MediaPlayerService服务的getOMX函数返回OMX对应的IOMX接口。OMX对象是对多媒体框架OPENOMX的封装。

源端的音视频编码、TS流化、HDCP加密、RTP打包发送的流程都有PlaybackSession线程类管理和调度,PlaybackSession类初始化时实例化一个SurfaceMediaSource对象,SurfaceMediaSource对象内部实例化一个BufferQueue对象(BufferQueue从ISurfaceTexure中派生)。在与SINK端建立连接后,通过IRemoteDisplayClient接口的回调函数onDisplayConnected把BufferQueue对象传给JAVA层,JAVA层的WifiDisplayAdapter对象收到onDisplayConnected事件后调用Surface类的createDisplay函数在SurfaceFlinger服务中登记一个虚拟显示器,并调用Surface类的setDisplaySurface函数把BufferQueue传给SurfaceFlinger服务虚拟显示器对应的DisplayDeviceState变量中.。因此PlaybackSession可以使用BufferQueue对象从SurfaceFlinger服务读取要镜像的数据。

SINK端WifiDisplaySink对象接收的数据经RTP解码(由RTPSink对象负责)后,送给TunnelRenderer对象进进行呈现, TunnelRenderer对象在initPlayer函数中实例化一个PlayerClient播放客户端,并通过IMediaPlayerService接口调用MediaPlayerService服务的create函数创建一个MediaPlayer对象并返回TunnelRenderer对象IMediaPlayer接口, TunnelRenderer对象使用IMediaPlayer接口对接收到的镜像数据进行播放和呈现, TunnelRenderer对象还在initPlayer函数中通过SurfaceComposerClient对象实例化和获得一个Surface对象,并调用其getSurfaceTexture函数获得Surface对象对应的ISurfaceTexture,并调用IMediaPlayer接口的setVideoSurfaceTexture函数把ISurfaceTexture赋值给播放器,从而实现播放器解码后的显示数据送给SurfaceFlinger显示服务进行显示.

SINK端的WifiDisplaySink对象和源端WifiDisplaySource的对象负责WIFI Display 交互协议的处理,两个对象都包含一个ANetworkSession对象负责两者之间的网络交互会话过程。

如下是WIFI Display 协议的框架图。

ANDROID4.2的开源代码提供了WIFI Display 协议的具体实现,但对SINK端只是作为一个本地测试命令来执行,并且没有提供图中的用户输入功能,而对于WFD Source端则提供了完整的实现代码,这主要是ANDROID系统主要是作为手机平板操作系统使用的缘故。

ANDROID4.2的WIFIDisplay的实现包括JAVA部分和C++部分。JAVA部分的功能主要对应DisplayManagerService服务,DisplayManagerService服务对于WIFIDisplay实例化和登记一个WifiDisplayAdapter对象(派生自DisplayAdapter),用来与对应的显示设备建立连接,每个DisplayAdapter与一个显示设备DisplayDevice类一一对应 。每个显示设备在DisplayManagerService服务中 对应一个LogicalDisplay对象。

DisplayManager发起的对WIFI Display的请求都由DisplayManagerService服务转发给WifiDisplayAdapter对象处理,为了实现异步交互和避免死锁,WifiDisplayAdapter对象对于每个请求都启动一个线程来实际完成请求处理,并实例化一个WifiDisplayController对象来封装这些请求的调用。WifiDisplayAdapter对象内部也实例化一个WifiDisplayController.Listener对象用来监听请求的状态。 WifiDisplayController对象内部实例化一个WifiP2pManager对象用来通过其接口向WifiP2pService服务发起WI-FI DIRECT请求。在与WIFI Display连接时通过实例化一个RemoteDisplay 对象来启动监听底层WIFI Display的连接事件。

C++ 部分位于媒体框架层,处于libstagefright目录的wifi-display目录下,wifi-display目录包含两个sink和source两个子目录(分别对应wifi display的sink和source 对应的程序),wifi-display目录还包含source和SINK公用的程序。

主要包含如下文件:

Sink目录主要包含WifiDisplaySink.cpp、RTPSink.cpp、TunnelRenderer.cpp等C++类文件和相应的头文件,分别负责SINK端的协议协议,RTP接收和镜像数据的呈现过程。而TS解析和PES去packetization化及解码过程都有播放器NuPlayer完成,由于Sink端只是一个测试例程,因此暂没有提供HDCP解码流程。

Source目录主要包括WifiDisplaySource.cpp、PlaybackSession.cpp、MediaPuller.cpp、Converter.cpp、TSPacketizer.cpp、Sender.cpp等C++类文件和相应的头文件,分别负责Source端的协议交互,会话过程管理、镜像媒体读取、编码、TS打包及RTP打包发送等过程。Converter 对象中包括一个MediaCodec对象具体负责编码过程,MediaCodec对象实际通过ACodec对象调用IOMX接口使用OPENOMX媒体框架完成镜像数据的编码。

sink和source使用的公共类文件主要是ANetworkSession.cpp和对应头文件以及一个 启动WifiDisplaySink的主程序wfd.cpp,用来 生成命令wfd。

整个协议主要的流程包括WIFI Display显示设备的连接过程和镜像数据的打包发送和接收流程,具体流程在下一篇博文中阐述。

转载于:https://www.cnblogs.com/senior-engineer/p/4971309.html

第十七篇 --ANDROID DisplayManager 服务解析一相关推荐

  1. Android源码解析(一)动画篇-- Animator属性动画系统

    Android源码解析-动画篇 Android源码解析(一)动画篇-- Animator属性动画系统 Android源码解析(二)动画篇-- ObjectAnimator Android在3.0版本中 ...

  2. Android 5.0+ 解析(三)Palette类

    1.Palette简单介绍 Palette中文翻译:调色板,android系统允许我们动态的获取图片或者控件的颜色,来为布局控件提供颜色,保持统一的外观颜色值. 使用Palette需要到sdk\ext ...

  3. Android Service完全解析,关于服务你所需知道的一切(下)

    转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要 ...

  4. Android Service完全解析,关于服务你所需知道的一切(上)

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11952435 相信大多数朋友对Service这个名词都不会陌生,没错,一个老练的A ...

  5. android从服务端获取json解析显示在客户端上面,Android服务端获取json解析显示在客户端上面.doc...

    Android服务端获取json解析显示在客户端上面 Android从服务端获取json解析显示在客户端上面 首先说一下Json数据的最基本的特点,Json数据是一系列的键值对的集合,和XML数据来比 ...

  6. Android笔记(四十七) Android中的数据存储——XML(三)SAX解析

    SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备. SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SA ...

  7. Android汽车服务篇(一) CarService

    一. 简介 Android Automotive OS作为车载操作系统, 需要与车辆上其他的子系统互联互通. Android Automotive OS 定义了标准的硬件抽象层HAL(Hardware ...

  8. Android OkHttp完全解析 是时候来了解OkHttp了

    Android OkHttp完全解析 是时候来了解OkHttp了 标签: AndroidOkHttp 2015-08-24 15:36 316254人阅读 评论(306) 收藏 举报  分类: [an ...

  9. 第46篇 Android Studio实现生命数字游戏(一)数据分析

    第46篇 Android Studio实现生命数字游戏(一)数据分析 1.数据 1.1.生日 1.2.生日数 1.3.天赋数 1.4.命数 1.5.星座数 2.数字对应的解析 1.数据 数据是在生命数 ...

最新文章

  1. Linux imooc learning
  2. Ajax操作的四个步骤
  3. CentOS下MySQL的彻底卸载
  4. PhD representive Punting and Dinner Plan
  5. myBatis xml if、where、if-else?、foreach 心得
  6. 使用OClint进行iOS项目的静态代码扫描
  7. Top Secret Task(dp+滚动数组)
  8. matlab解带参数的积分方程组,方程组求解问题:方程组中有带参数的积分函数,求参数...
  9. [JavaWeb基础] 015.Struts2 表单验证框架
  10. ArcGIS:ArcToolBox工具使用——提取DEM/DSM中的高程点
  11. Java并发编程实战——并发编程的优缺点
  12. 并行计算 SLIC超像素算法(二) 代码分析
  13. 中文顿号怎么输入_顿号如何在键盘中打出来 保准你一看即会
  14. 下载文件进度显示--小小Demo——桃先森
  15. 如何建立一个网站?规划、设计、目的、原则、宣传(一)
  16. 模拟CMOS集成电路设计入门学习(13)
  17. SEM URL标记生成和解码工具发布
  18. opencv-膨胀 dilate()
  19. 通过vs读取mysql数据
  20. 索引忽然失效Oracle,Oracle索引失效原因及解决方法

热门文章

  1. 面向对象真的需要继承吗?
  2. CVTE【嵌入式应用开发】【软件技术支持】面经【已拿offer】
  3. Tracking 的SimTrack 以及 4D seg
  4. 卷积,特征图,转置卷积和空洞卷积的计算细节
  5. 梯度下降法快速教程 | 第一章:Python简易实现以及对学习率的探讨
  6. 机器学习之分类性能度量指标 : ROC曲线、AUC值、正确率、召回率
  7. python 开发框架_python的web开发框架有哪些
  8. 晶振两端的谐振电容有特殊要求吗_干货 | 晶振电路设计诀窍
  9. RedisTemplate设置过期时间
  10. pg函数同步数据到mysql_将数据从PostgreSQL复制到MySQL