1. 前言


本文尝试从硬件认识开始介绍Android的显示系统是如何更新画面的,希望能就android系统是如何更新画面的问题,给读者带来一个感性认知。文中将尝试解释从App画出一帧画面到这帧画面是如何到达屏幕并最终被人眼看到的整个过程,这其中会涉及硬件的一些基础知识以及Android系统下一些重要的软件基础组件。本文将先分别介绍画面显示过程中所涉及到的重要组件及其工作原理,然后从Android app渲染第一帧画面开始逐步串联起各个组件,期望最终对于Android系统下画面是如何显示出来的给读者一个宏观的认识。本文适合对Android显示系统有过一定了解的同学阅读。

由于本文是通过阅读各种文章及代码,总结出来的,难免有些地方理解得不对,欢迎大家批评指正。

2. 显示硬件基础


无论软件的架构设计多么高端大气上档次,最终都离不开硬件的支持,软件的架构是建构在硬件的运行原理之上的,所以在讨论软件的各个设计之前我们有必要对显示硬件的原理做一个初步的了解。

2.1. 常见显示设备

LCD(Liquid Crystal Display)俗称液晶。

液晶是一种材料,液晶这种材料具有一种特点:可以在电信号的驱动下液晶分子进行旋转,旋转时会影响透光性,

因此我们可以在整个液晶面板后面用白光照(称为背光),可以通过不同电信号让液晶分子进行选择性的透光,此时在液晶面板前面看到的就是各种各样不同的颜色,这就是LCD显示画面的原理。

有些显示器(譬如LED显示器、CRT显示器)自己本身会发光称为主动发光,有些(LCD)本身不会发光只会透光,需要背光的协助才能看起来是发光的,称为被动发光。

其他一些主流的显示设备:

CRT:阴极摄像管显示器。 以前的那种大屁股电视机就是CRT显示,它曾是应用最广泛的显示器之一,不过现在基本没有在使用这种技术了。

OLED:有机发光二极管又称为有机电激光显示(Organic Light-Emitting Diode,OLED),OLED显示技术具有自发光的特性,采用非常薄的有机材料涂层

和玻璃基板,可以做得更轻更薄,可视角度更大,并且能够显著节省电能。目前未成为主流,但是很有市场潜力,将来很可能取代LCD。

LED:主要用在户外大屏幕

2.2. LCD的接口技术

VGA(Video Graphics Array)即视频图形阵列,具有分辨率高、显示速率快、颜色丰富等优点。VGA接口不但是CRT显示设备的标准接口,同样也是LcD液晶显示设备的标准接口,具有广泛的应用范围。相信很多朋友都不会陌生,因为这种接口是电脑显示器上最主要的接口,从块头巨大的CRT显示器时代开始,VGA接口就被使用,并且一直沿用至今。

HDMI(High Definition Multimedia Interface) 高清多媒体接口,是一种全数字化视频和声音发送接口,可以发送未压缩的音频及视频信号。HDMI可用于机顶盒,DVD播放机、个人计算机、电视、游戏主机、综合扩大机、数字音响与电视机等设备。HDMI可以同时发送音频和视频信号,由于音频和视频信号采用同一条线材,大大简化系统线路的安装难度。

DVI(Digital Visual Interface),即数字视频接口。它是1998年9月,在Intel开发者论坛上成立的,由Silicon Image、Intel(英特尔)、Compaq(康柏)、IBM(国际商业机器公司)、HP(惠普)、NEC(日本电气股份有限公司)、Fujitsu(富士通)等公司共同组成的DDWG(Digital Display Working Group,数字显示工作组)推出的接口标准

LVDS(Low Voltage Differential Signaling,即低电压差分信号)接口又称RS-644总线接口,是20世纪90年代才提出的一种数据传输和接口技术。LVDS接口是美国NS美国国家半导体公司为克服以TTL电平方式传输宽带高码率数据时功耗大,电磁干扰大等缺点而研制的一种数字视频信号传输方式。由于其采用低压和低电流驱动方式,因此,实现了低噪声和低功耗。LVDS技术具有低功耗、低误码率、低串扰和低辐射等特点,其传输介质可以是铜质的PCB连线,也可以是平衡电缆。LVDS在对信号完整性、低抖动及共模特性要求较高的系统中得到了越来越广泛的应用,常见于液晶电视中。

MIPI(Mobile Industry Processor Interface)是2003年由ARM, Nokia, ST ,TI等公司成立的一个联盟,目的是把手机内部的接口如摄像头、显示屏接口、射频/基带接口等标准化,从而减少手机设计的复杂程度和增加设计灵活性。MIPI联盟下面有不同的WorkGroup,分别定义了一系列的手机内部接口标准,比如摄像头接口CSI、显示接口DSI、射频接口DigRF、麦克风/喇叭接口SLIMbus等。统一接口标准的好处是手机厂商根据需要可以从市面上灵活选择不同的芯片和模组,更改设计和功能时更加快捷方便。

目前手机屏幕和SOC间多使用MIPI接口来传输屏幕数据,其实物如下图所示,图中的条状芯片就是负责更新显示屏的显示内容的芯片DDIC, 它一边通过mipi协议和SOC通信,一边把获取到的显示数据写入到显示存储器GRAM内, 屏幕(Panel)通过不停扫描GRAM来不停更新液晶显示点的颜色,实现画面的更新。

屏幕坐标系

显示屏幕采用如下图所示的二维坐标系,以屏幕左上角为原点,X方向向右,Y轴方向向下,屏幕上的显示单元(像素)以行列式整齐排列,如下图所示,如下图示中以六边形块来代表一个像素点,如无例外说明,本文中所有图示都将以该六边形块来代表屏幕上的一个像素点。

在一个典型的Android显示系统中,一般包括SOC、DDIC、Panel三个部分, SOC负责绘画与多图层的合成,把合成好的数据通过硬件接口按某种协议传输给DDIC,然后DDIC负责把buffer里的数据呈现到Panel上。如下图所示为高通平台上的画面更新简单示意图,首先CPU或GPU负责绘画,画出的多个layer交由MDP进行合成,合成的数据通过mipi协议和DSI总线传输给DDIC, DDIC将数据存到GRAM内(非video屏), Panel不断scanGRAM来显示内容。

那么对于DDIC来讲它的职责就是按mipi协议和SOC交互,获取到从SOC合成好的一帧画面的数据,然后将数据写入GRAM,对GRAM的写入要符合一定的时序。

2.3. LCD时序

  这个写入时序要首先从过去的 CRT 显示器原理说起。CRT 的电子枪按照从上到下一行行扫描,扫描完成后显示器就呈现一帧画面,随后电子枪回到初始位置继续下一次扫描。为了把显示器的显示过程和系统的视频控制器进行同步,显示器(或者其他硬件)会用硬件时钟产生一系列的定时信号。当电子枪换到新的一行,准备进行扫描时,显示器会发出一个水平同步信号(horizonal synchronization),简称 HSync;而当一帧画面绘制完成后,电子枪回复到原位,准备画下一帧前,显示器会发出一个垂直同步信号(vertical synchronization),简称 VSync。显示器通常以固定频率进行刷新,这个刷新率就是 VSync 信号产生的频率。尽管现在的设备大都是液晶显示屏了,但原理仍然没有变。

   CLK:像素时钟,像素数据只有在时钟上升或下降沿时才有效   ENB:是数据使能信号,当它为高时,CLK信号到达时输出有效数据。   HBP:行同步信号的前肩,水平同步信号的上升沿到ENABLE的上升沿的间隔。   HSW:水平同步信号的低电平(非有效电平)持续时间   HFP:行同步信号的后肩,ENABLE的下降沿到水平同步信号的下升沿的间隔

如下图所示

图中从HSYNC的下降沿开始,等待两个CLK产生一个上升沿,在等待一个HBP时间后开始传输一行的像素数据,像素数据只有在像素时钟和上升沿或下降沿时才会写入(这里我们只讨论原理,并不是某个特定平台的具体实现,所以HSW所对应的时钟数字并不是以图中所示为准,具体产品中都会有调整和变化),经过N个像素时钟后成功将一行像素数据写入D1-Dn

类似地,在两帧画面之间也存在一些间隔:

VSW: VSYNC信号下降沿到上升沿间的时间

VBP: 帧同步信号的前肩

VFP:帧同步信号的后肩

VPROCH: 被称为消隐区,它是指 VSW+VBP+VFP , 这个时间段内Panel不更新像素点的颜色

在一个Vsync周期内是由多个Hsync周期组成的,其个数就是屏幕在Y方向的像素点个数,也就是屏幕上有多少行像素点, 每个Hsync周期内传输一行内所有像素点的数据。通常屏厂给的spec文档还会给出类似下面这样的图,但都是表达一个意思,数据是以行为单位写入的,Hsync是协调行和行之间的同步信号,多个行依次写入构成一帧数据,帧和帧数据之间由Vsync信号来同步协调。

当多帧画面依次输出到屏幕的时候我们就可以看到运动的画面了,通常这个速度到达每秒60帧时人眼就已经感觉画面很流畅了。下图演示了在vsync和hsync同步下两帧画面间的切换时序,以及消隐区(VPorch)在其中的位置关系。在消隐区结束(或开始)时DDIC会向SOC发出一个中断信号,这个信号称为TE信号, SOC这边就是通过该中断信号来判断上一帧数据是否已被DDIC读走,进而决定是否可以将buffer写入下一帧数据。

2.4. LCD上的画面更新流程

让我们以下面这张图来说明从SOC到到DDIC再到Panel的画面更新过程,首先SOC准备画面A, DDIC上一帧画面更新完毕进入消隐区,同时向SOC侧发送TE信号,SOC收到TE信号后,A画面的数据开始通过DSI总线向DDIC传输(DSI Write),当消隐区时间结束时开始这一帧数据从数据变为像素点颜色的过程(Disp Scan), Disp Scan是以行为单位将GRAM内一行的数据内容通过改变电流电压等方式改变Panel上像素点的颜色。进而实现一行画面的更新,按下来Disp Scan将以一定速度逐行读取GRAM的内容,而于此同时DSI Write也还在进行中,由于DSI Write较Disp Scan早了一个Vporch的时间,所以Disp Scan扫描到的数据都是A画面的数据。那么人眼会看到画面“逐渐”出现到显示屏上,当A画面的所有行都经Disp Scan到达屏幕后,下一个Vporch开始,DDIC再次向SOC发出TE信号, 下帧B画面的数据开始经过DSI总线传输到DDIC, 如此循环往复可以将连续的A, B, C画面更新到屏幕上。

这里我们思考一个问题: 就像上图中所绘一样总会存在一段时间GRAM内的数据会出现一部分是新画面的数据,一部分是旧画面的数据,那么从上帝视角看GRAM里的画面是“撕裂”的,那Disp Scan会不会把这个“撕裂”的画面显示到Panel上呢? 用户有没有可能看到一个“撕裂”的画面呢?

答案是有可能会。

为讨论方便我们这里先把DSI write记作写, 把Disp Scan记作读, 正常情况下,我们会将读速度调到和写速度差不多,由于写是在进入vporch时就开始了,而读的动作是离开vproch时,所以在读和写的这场“百米跑”竞赛中总是写跑在前面,这样保证读始终读到的是同一帧画面的数据,这个过程如下面图1所示。

由于读和写的速度受到环境或各种电气因素影响并不是一成不变的,在实际运行过程中会有波动,当读和写两条线离的较近时由于速度波动的存在会出现两条线交叉的情况,如图2所示,那么这时读会先后读到前后两帧的数据,出现花屏现象。

有时我们为了避免由于速率波动引起花屏问题,会放大vporch的时间让读和写尽量拉开距离,这样可以减少花屏现象出现的概率,这里的原理如图3所示

继续思考下一问题: 从上面的分析可以看出Panel上的像素数据是一行行更新下来的,那人眼为什么没有看到更新了一半的画面呢?

这个问题我并不知道答案,这可能涉及到人眼的生物学构造,人眼对事物的成像原理等复杂的原理,总之是在这个时间尺度内人眼看不到。

接下来我们从另一角度来研究一下这个问题,我们把视角切换到上帝视角,假如存在上帝之眼的话,他应该能看到这个更新了一半的画面,我们尝试用高速摄影机来模拟“上帝之眼”。

首先我们先准备一些测试代码, 我们写一个测试用apk, 下面这段代码是向Android框架注册一个Choreographer的监听,Choreographer是Android提供的一个获取vsync信号的通道。当下图中doFrame被调用到时我们这里可以暂时粗略理解为是上面所讨论的TE信号, 这里收到Vsync信号后通过Pthread的Condition通知到另一线程。这用于模拟一个vsync的消息泵。

Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {@Overridepublic void doFrame(long frameTimeNanos) {//当vsync信号来时会调用到这里Global.lock.lock();try {Global.syncCondition.signal();//通知另一条线程更新画面} catch (Exception e) {e.printStackTrace();} finally {Global.lock.unlock();}Choreographer.getInstance().removeFrameCallback(this);Choreographer.getInstance().postFrameCallback(this);}
});

下面代码中每收到一个vsync信号都会去画一帧画面,同时给帧编号编号加1(相当于给每一帧一个编号),如果当前的编号为奇数则画绿色,如果为偶数则画蓝色,那么画面应该是蓝绿交替出现:

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {.......@Overridepublic void run() {while(true) {Global.lock.lock();try {Global.syncCondition.await();//在这里等待vsync到来的通知消息} catch (InterruptedException e) {e.printStackTrace();} finally {Global.lock.unlock();}draw();//画蓝色或绿色}}........private void draw() {Canvas mCanvas = null;try {mCanvas = mSurfaceHolder.lockCanvas();if(autoNum %2 == 0) {mPaint.setColor(Color.BLUE);//如果为双数则画面画成蓝色} else {mPaint.setColor(Color.GREEN);//如果为单数则画面画成绿色}mCanvas.drawRect(0, 0, getRight(), getBottom(), mPaint);} catch (Exception e) {e.printStackTrace();} finally {if (mCanvas != null) {mSurfaceHolder.unlockCanvasAndPost(mCanvas);}}autoNum++;//数字加1}}

下面是高速摄影机看到的画面变化情况,从下图中可以看出来,画面从绿变蓝的过程中总是能看到先是上面部分变蓝色,接下来才会看到全部变蓝,由蓝变绿也是同样的现象,先是图像上面变成绿色接下来全部变绿色,在“上帝之眼”看来画面的变化是有前后两个画面各占一部分的情况的,这情况是上面是新画面下面是旧画面,但人眼是看不出来这种画面。

下面的图中发现画面是颜色渐变的,这是因为通过高速摄影机是画面再次感光形成的影像,由于物理世界中光线是有衍射及曝光时长因素的,所以最终在高速摄影机留下的图中是颜色渐变的。

2.5. 本章小结

在本章节中,我们了解到了一些显示硬件的一些组成要件,以及屏幕是如何按时序更新画面的,以及在画面更新过程中屏和SOC间的一些互动是如何完成的。那么接下来我们再来了解下SOC内部是如何把画面送过来的。

Android画面显示流程分析(1)相关推荐

  1. Android系统启动流程分析之安装应用

    2016六月 21 原 Android系统启动流程分析之安装应用 分类:Android系统源码研究 (295)  (0)  举报  收藏 跟随上一篇博客Android系统的启动流程简要分析继续分析an ...

  2. 【android系统】android系统升级流程分析(二)---update升级包分析

    接下来我们将通过几篇文章来分析update.zip包在具体Android系统升级的过程,来理解Android系统中Recovery模式服务的工作原理.今天让我先来分析下升级包update.zip. 一 ...

  3. 【android系统】android系统升级流程分析(一)---recovery模式中进行update包升级流程分析

    今天我们直接来看下android中具体的升级过程是如何的. 升级流程概述 升级的流程图: 升级流程分析 第一步:升级包获取 升级获取可以通过远程下载,也可直接拷贝到指定目录即可. 第二步:准备升级 然 ...

  4. android SystemUI 流程分析

    android4 SystemUI 流程分析 什么是SystemUI? 对于Phone来说SystemUI指的是:StatusBar(状态栏).NavigationBar(导航栏).而对于Tablet ...

  5. Android FM流程分析

    一,FM主要类介绍 FmMainActivity.java 主界面 FmService.java  核心 FmNative.java  调用JNI和底层通信 二,FM主要功能介绍 1,收音播放: 1 ...

  6. Android Gallery2流程分析

    Android 系统的多媒体数据provider packages/providers/MediaProvider/ 含有类MediaProvider.java.MediaScannerService ...

  7. android serviceconnection unbind流程,Android unbindService 流程分析

    基于Android 6.0的源码剖析, 分析bind service的启动流程. /frameworks/base/core/java/android/app/ContextImpl.java /fr ...

  8. Android otapackage流程分析三

    我们来看下增量升级包流程: 为了能够详细一点说明我这边是弄了几个不同的文件替换然后很好的分析,增量升级包制作要手动执行脚本 例如: ./build/tools/releasetools/ota_fro ...

  9. Android待机流程分析---锁屏、解锁模块

    以下分析基于android2.2的google源码.  开机启动时,首先执行PhoneWindowManager.systemReady()(这之前的流程不分析).调用KeyguardViewMed ...

最新文章

  1. sequence.pad_sequences 的用法举例
  2. PIL 学习笔记(3)
  3. Tears in Heaven
  4. SpringBatch 写xml文件(StaxEventItemWriter)用法(十四)
  5. php中显示不出图像,php – 无法显示图像,因为它包含错误
  6. python中home定义是什么_第48p,什么是函数?,Python中函数的定义
  7. cv2.imread读取图像结果none_python cv2.imread 读取中文路径的图片返回为None的问题
  8. ssl1072-砝码称重【dp练习】
  9. Epic Games创始人眼中的虚拟现实
  10. android中intent放数据类型,Android Intent传递数据底层分析详细介绍
  11. SpringSecurity Basic Authentication
  12. 大学概率论与数理统计知识点详细整理
  13. 微信测试号中被动消息回复的测试
  14. Windows Sockets概述
  15. reset清除所有浏览器默认样式
  16. 安卓系统怎么模拟java_电脑上安装安卓系统模拟器的方法(直接用JAVA虚拟成手机)...
  17. 伺服系统基于陷波滤波器双惯量伺服系统机械谐振抑制matlab Simulink仿真
  18. Flutter开发之——Card
  19. UE4 Matinee制作相机动画及其蓝图播放(UE4.11和UE4.19测试通过)
  20. 能在html中打开ppt吗,怎样在PPT中直接打开网页

热门文章

  1. 中国掀起数字化浪潮|沃丰科技AI外呼机器人助家电企业潜客筛选自动化
  2. mplayer配置文件_使用MPlayer和Lame将电影文件转换为wav和mp3文件
  3. 合振动的初相位推导_合振动的初相位确定方法
  4. 个人知识管理为什么要软件工具为主理念为次?
  5. 虚拟机上安装Ubuntu时遇到SQUASHFS错误解决办法:QUASHFS error: squashfsread_data failed to read block 0x3773d14e
  6. python爬虫-从QQ邮箱获取好友信息并爬取头像
  7. 使用Python建立时间序列(ARIMA、MA、AR)预测模型
  8. linux通过命令设置为utf-8编码,设置linux系统的编码为UTF-8
  9. profiles配置详解
  10. 城市时尚骑行 从拥有一辆潮流的cruiser自行车开始