SlideShare a Scribd company logo
Beyond Android Views - Window, Surface, Special Views and More Roger [email_address] [email_address] www.twitter.com/roger2yi + 易旭昕  in Google+
介绍隐藏在用户界面后面的系统底层模块  - Window ,  Surface , Canvas ,和它们之间的关系与交互 介绍一些特殊 View 的运作原理  - SurfaceView , GLSurfaceView , TextureView 介绍硬件加速绘图与非硬件加速绘图的差异 Major Contents
Activity and Views
View This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling.  View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.).
Activity 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理 应用在 Activity.onCreate 中构建用户界面,调用 Activity.setContentView 方法设置界面
Those things behind Activity and Views
System Services Activity Management Service Window Management Service Suface Flinger etc...
The Startup of an Activity in New Process AMS 接收到请求要在新的进程启动一个 Activity AMS 转发请求给 zygote 进程, zygote fork 一个新的进程,然后调用 ActivityThread.main 方法, ActivityThread 创建 MessageQueue , attach 到 AMS ,然后进入消息循环,这个线程就是主线程,也是所谓的 UI 线程 当 ActivityThread attch 到 AMS 后, AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY ) ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity ) 创建 Activity 后调用 onCreate ( performLaunchActivity ) 应用则在 onCreate 中设置 Content View ,然后开始跟用户的交互 ... ...
 
Window Android 中的 Window 是一个十分容易混淆的概念 它存在应用层面窗口和系统层面窗口的区别 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
android.view.Window Abstract base class for a top-level window look and behavior policy.  It provides standard UI policies such as a background, title area, default key processing, etc. 它是通常意义上我们理解的应用层面窗口, TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindow PhoneWindow 是抽象类 Window 的唯一实现 ActivityThread 在启动一个 Activity 的时候, Activity 会创建一个 PhoneWindow ActivityThread.handleLaunchActivity -> ActivityThread.performLaunchActivity  -> Activity.attach Activity.setContentView 实际上是调用 PhoneWindow.setContentView ,在该方法的第一次调用时, PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的 View Hierachy 的根节点
View Hierachy
 
WindowManager android.view.WindowManager The interface that apps use to talk to the window manager. 真正的实现是 WindowManagerImpl ,由 PhoneWindow 在 Activity 启动时创建 ActivityThread.handleLaunchActivity -> ActivityThread.performLaunchActivity -> Activity.attach -> PhoneWindow.setWindowManager 当 Activity 启动后, ActivityThread 将 DocorView 添加到 WindowManagerImpl 中 ActivityThread.handleLaunchActivity -> ActivityThread.handleResumeActivity  -> WindowManager.addView
Cont. WindowManagerImpl 负责跟 WMS 通讯 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责, ViewRootImpl 在 addView 时被创建 这里的 Window 是指系统层面的 Window ,除了之前的 PhoneWindow 外,其它如 Dialog , Menu 都拥有一个独立的 Window ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系,它是真正意义上的 View Hierachy 的根节点 ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl The top of a view hierarchy, implementing the needed protocol between View and the WindowManager This is for the most part an internal implementation detail WindowManagerImpl
Cont. ViewRootImpl 会打开一个 IWindowSession 用于跟 WMS 对话 并通过 IWindowSession 向 WMS 注册一个窗口(实际上是让 WMS 在服务端创建一个窗口( WindowState ),并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起) ActivityThread.handleLaunchActivity -> ActivityThread.handleResumeActivity  -> WindowManagerImpl.addView -> ViewRootImpl.setView
Cont. IWindow API back to a client window that the Window Manager uses to inform it of interesting things happening. 回调接口用于接收 WMS 关于窗口的消息 —— 显示 / 隐藏,大小改变,焦点变化等等 除了注册窗口外, ViewRootImpl 还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件 接收到的输入事件会先放在 UI 线程的消息循环中,然后通过 ViewRootImpl 进行分派,在它对应的 View Hierachy 上路由
 
 
Overall Flow ActivityThead 创建 Activity Activity 创建 PhoneWindow PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点, Client 端设置的 Content View 会 attach 到 DecorView 下面(间接) PhoneWindow 创建 WindowManagerImpl ActivityThead 把 DecorView 加到 WindowManagerImpl 里面 WindowManagerImpl 创建 ViewRootImpl ,并把 DecorView 传给它 ViewRootImpl 打开一个 Window Session 跟 WMS 通讯,通过 Session 注册一个窗口,最后客户端拥有一个 IWindow 回调接口,服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering 当 ViewRootImpl 建立跟 WMS 的联系,注册了窗口后,会发出第一次渲染 View Hierachy 的请求 ViewRootImpl.setView ViewRootImpl.requestLayout ViewRootImpl.scheduleTraversals 在第一次的 View Hierachy 的渲染中( ViewRootImpl.performTraversals ), ViewRootImpl 需要创建 Surface
Cont. 当 Surface 创建后,后续的渲染就可以通过获得 Surface 的 Canvas ( Surface.lockCanvas ) 然后遍历 View Hierachy ,把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面( View.onDraw ) 绘制完后需要解锁( Surface.unlockCanvasPost ),让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
 
Surface Handle onto a raw buffer that is being managed by the screen compositor. 每个 Window 都有一个 Surface ,由窗口在客户端的代理者 ViewRootImpl 所拥有 Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建 ViewRootImpl.performTraversals ViewRootImpl.relayoutWindow IWindowSession.relayout
Cont. ViewRootImpl 预先创建一个空的 Surface 对象( Java ),在需要创建真正的 Surface 的时候,它调用 IWindowSession.relayout ,这是一个 RPC ,最终是 WMS 的 relayoutWindow 被调用 WMS 调用 WindowState.createSurfaceLocked 创建了一个 Surface 对象( Java ),并把这个对象的数据传回给客户端,而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java ) 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface ,然后把 Surface 相关的信息再传回给客户端 客户端利用这些信息来创建一个 native Surface 对象,然后把它跟 Java Surface 对象绑定在一起 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer ),图像缓存可以看作是一块共享内存,在客户端和 SurfaceFlinger 之间共享
Surface & Canvas Surface ( Java )包含一个 Canvas ( Java ),而 Canvas ( Java )包含一个 native  的 SkCanvas 对象 当调用 Surface.lockCanvas 时 从图像缓存队列中取出一个可用的缓存 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Region 之外的区域),然后将这块缓存加锁,并设置为 Locked Buffer 获得新缓存的内存地址,根据内存地址构建一个 SkBitmap 把该 SkBitmap 设置到 SkCanvas 里面 返回跟 SkCanvas 对应的 Canvas ( Java ),透过 Canvas ( Java )绘制的内容实际上就是绘制到当前的缓存
Cont. 当调用 Surface.unlockCanvasAndPost 的时候 置空 SkCanvas ,设置一个空的 SkBitmap 将 Locked Buffer 解锁并返回到图像缓存队列里面 将 Posted Buffer 设置为 Locked Buffer ,旧的 Posted Buffer 就可以被下次取出来使用,设置 Locked Buffer 为空 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlinger 应用跟 SF 之间的关系是就像是生产者与消费者的关系 应用从 Surface 的 GraphicsBuffer 队列的前端取出一个缓存,然后进行绘制 绘制完毕后把该缓存放置回队列的后端(生产) 而 SF 则不断地将 Surface 的 GraphicsBuffer 队列的最后一个缓存绘制到屏幕上(消费) 两者在不同的进程,是异步进行的,对队列的访问需要进行同步
 
Overall Flow ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surface 客户端请求 WMS 创建 Surface ,并返回 Surface 相关的数据用于构建一个 native 的 Surface 对象,并把它跟 ViewRootImpl 的 Surface ( Java )绑定在一起 ViewRootImpl 在渲染时先从 Surface 获得 Canvas 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面 绘制完毕后解锁该 Surface SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface 绘制到屏幕上
Those special Views
SurfaceView Provides a dedicated drawing surface embedded inside of a view hierarchy. You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed.
Cont. Pros 可以跟 View Hierachy 较好地结合在一起,可以移动,改变大小,在上方叠加其它的 View 在单独的渲染线程进行渲染,渲染效率高 SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成,效率高,并且不占用应用本身的 UI 线程时间 Cons SurfaceView 的渲染毕竟跟真正的 View 不一样,它不是由 ViewRootImpl 渲染到当前的 Window Surface 上面 不能改变 Alpha ,不支持跟下方的 View 进行 Alpha 混合 不能做 Rotation , Skew 等变换
GLSurfaceView An implementation of SurfaceView that uses the dedicated surface for displaying OpenGL rendering. A GLSurfaceView provides the following features: Manages a surface, which is a special piece of memory that can be composited into the Android view system. Manages an EGL display, which enables OpenGL to render into a surface. Accepts a user-provided Renderer object that does the actual rendering. Renders on a dedicated thread to decouple rendering performance from the UI thread. Supports both on-demand and continuous rendering. Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.
Cont. GLSurfaceView 创建一个内部的线程 GLThread 在该线程运行环境下创建一个 EglContext 创建一个 EglSurface ( Window Surface ) 设置之前创建的 EglContext 为当前的 GL Context 并绑定到创建的 EglSurface 上 在该线程内就可以通过 EGL 指令在当前的 GL Context 上绘图
Cont. GLSurfaceView 支持两种不同的绘图模式 连续模式下, GLThread 会不断调用 Renderer.onDrawFrame 进行绘图 Dirty 模式下, GLThread 处于等待状态,直到程序发送绘图请求( GLSurfaceView.requestRender )才调用 Renderer.onDrawFrame 进行绘图,绘制完一帧后重新进入等待状态 在 Renderer.onDrawFrame 的回调中,应用可以通过 SDK 提供的 EGL API 绘图,也可以转到 native 端,使用 NDK 提供的 EGL API 绘图
 
TextureView Since Android 4.0 ,只在硬件加速环境下起作用 具备 SurfaceView 的特性 但是可以跟其它普通的 View 一样实现 Rotation , Screw 等变换 支持 Alpha ,可以跟它下方的 View 进行 Alpha 混合 可以基于 TextureView 创建一个 GL Surface ,在上面进行 OpenGL 渲染
Things become more complicated after Android 3.0 ...
HW Accelerated 2D Rendering Android 3.0 后开始支持硬件加速的 2D 绘图,原有的绘图流程变得更加复杂 所谓硬件加速的 2D 绘图,就是将 2D Graphics API 的实现改成使用 OpenGL API 来进行绘图 OpenGL 的绘图模式跟一般的 2D 绘图有很大区别,它需要先将绘图所需的各种素材如贴图,多边形顶点阵列, Shader 等先加载到当前的 GLContext ,然后流水线式的顺序执行绘图指令,通过这种方式来充分利用硬件的能力
ViewRootImpl 当 Actitity 的 View Hierachy 的根节点被添加到 WindowManager 的时候( WindowManager.addView ), WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImpl.setView ),并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer 在 ViewRootImpl 第一次渲染 View Hierachy 时,会创建 Surface ,如果开启硬件加速,则通过 HardwareRenderer 在当前的 UI 线程初始化 EGL 绘图环境(类似 GLSurfaceView )
Cont. 在 ViewRootImpl 真正渲染 View Hierachy 时,如果开启硬件加速,则从 HardwareRenderer 获得一个 HardwareCanvas ,然后 View Hierachy 的渲染通过 HardwareCanvas 来进行 HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定,通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layer 为了充分利用硬件加速的能力, Android 3.0 还引入了 DisplayList 和 Hardware Layer DisplayList 用于记录一系列 OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap , Paint , Shape , Shader ),当 View 的内容不发生变化时,可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object ,当内容不发生变化时,可以直接使用 Layer 进行 Layer Composite 获得更快的绘图速度
 
Reference Android 圖形系統 -- 設計與實做分析 How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich?
The End Thank you for your listening Yours Sincerely, Roger
Ad

More Related Content

Viewers also liked (8)

Acrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVMAcrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVM
Dong-Ho Lee
 
Android design and Custom views
Android design and Custom views Android design and Custom views
Android design and Custom views
Lars Vogel
 
[Android] Widget Event Handling
[Android] Widget Event Handling[Android] Widget Event Handling
[Android] Widget Event Handling
Nikmesoft Ltd
 
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspectiveAndroid graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Bin Chen
 
Android internals 07 - Android graphics (rev_1.1)
Android internals 07 - Android graphics (rev_1.1)Android internals 07 - Android graphics (rev_1.1)
Android internals 07 - Android graphics (rev_1.1)
Egor Elizarov
 
Android Data Binding in action using MVVM pattern - droidconUK
Android Data Binding in action using MVVM pattern - droidconUKAndroid Data Binding in action using MVVM pattern - droidconUK
Android Data Binding in action using MVVM pattern - droidconUK
Fabio Collini
 
Data Binding in Action using MVVM pattern
Data Binding in Action using MVVM patternData Binding in Action using MVVM pattern
Data Binding in Action using MVVM pattern
Fabio Collini
 
Design and Concepts of Android Graphics
Design and Concepts of Android GraphicsDesign and Concepts of Android Graphics
Design and Concepts of Android Graphics
National Cheng Kung University
 
Acrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVMAcrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVM
Dong-Ho Lee
 
Android design and Custom views
Android design and Custom views Android design and Custom views
Android design and Custom views
Lars Vogel
 
[Android] Widget Event Handling
[Android] Widget Event Handling[Android] Widget Event Handling
[Android] Widget Event Handling
Nikmesoft Ltd
 
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspectiveAndroid graphic system (SurfaceFlinger) : Design Pattern's perspective
Android graphic system (SurfaceFlinger) : Design Pattern's perspective
Bin Chen
 
Android internals 07 - Android graphics (rev_1.1)
Android internals 07 - Android graphics (rev_1.1)Android internals 07 - Android graphics (rev_1.1)
Android internals 07 - Android graphics (rev_1.1)
Egor Elizarov
 
Android Data Binding in action using MVVM pattern - droidconUK
Android Data Binding in action using MVVM pattern - droidconUKAndroid Data Binding in action using MVVM pattern - droidconUK
Android Data Binding in action using MVVM pattern - droidconUK
Fabio Collini
 
Data Binding in Action using MVVM pattern
Data Binding in Action using MVVM patternData Binding in Action using MVVM pattern
Data Binding in Action using MVVM pattern
Fabio Collini
 

Similar to Beyond Android Views - Window,Surface,Special Views,and More (20)

react-zh-hant.pdf
react-zh-hant.pdfreact-zh-hant.pdf
react-zh-hant.pdf
ssuser65180a
 
Android应用开发 - 沈大海
Android应用开发 - 沈大海Android应用开发 - 沈大海
Android应用开发 - 沈大海
Shaoning Pan
 
06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView
Tom Fan
 
Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎
PingLun Liao
 
Android社群分享Fragment
Android社群分享FragmentAndroid社群分享Fragment
Android社群分享Fragment
YiRen Xiong
 
建立視窗框架
建立視窗框架建立視窗框架
建立視窗框架
jiannrong
 
建立視窗框架
建立視窗框架建立視窗框架
建立視窗框架
jiannrong
 
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Gelis Wu
 
【项目分享】赶集移动Web App开发总结
【项目分享】赶集移动Web App开发总结 【项目分享】赶集移动Web App开发总结
【项目分享】赶集移动Web App开发总结
yangdj
 
Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門
Chui-Wen Chiu
 
Html5移动网站开发实践
Html5移动网站开发实践Html5移动网站开发实践
Html5移动网站开发实践
Web Zhao
 
Study mapapi v0.1
Study mapapi v0.1Study mapapi v0.1
Study mapapi v0.1
Paul Yang
 
由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...
由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...
由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...
ChungHsienTsai1
 
07 View Controllers
07 View Controllers07 View Controllers
07 View Controllers
Tom Fan
 
赶集团购开发总结4
赶集团购开发总结4赶集团购开发总结4
赶集团购开发总结4
yangdj
 
JdonFramework中文
JdonFramework中文JdonFramework中文
JdonFramework中文
banq jdon
 
Android 介面實作
Android 介面實作Android 介面實作
Android 介面實作
Richard Chang
 
Android应用开发 - 沈大海
Android应用开发 - 沈大海Android应用开发 - 沈大海
Android应用开发 - 沈大海
Shaoning Pan
 
06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView06 Subclassing UIView and UIScrollView
06 Subclassing UIView and UIScrollView
Tom Fan
 
Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎Android 2D 遊戲設計基礎
Android 2D 遊戲設計基礎
PingLun Liao
 
Android社群分享Fragment
Android社群分享FragmentAndroid社群分享Fragment
Android社群分享Fragment
YiRen Xiong
 
建立視窗框架
建立視窗框架建立視窗框架
建立視窗框架
jiannrong
 
建立視窗框架
建立視窗框架建立視窗框架
建立視窗框架
jiannrong
 
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Visual studio 2012 與 asp.net 4.5 (新功能與開發介紹) 第一天
Gelis Wu
 
【项目分享】赶集移动Web App开发总结
【项目分享】赶集移动Web App开发总结 【项目分享】赶集移动Web App开发总结
【项目分享】赶集移动Web App开发总结
yangdj
 
Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門Windows Mobile 6 遊戲開發入門
Windows Mobile 6 遊戲開發入門
Chui-Wen Chiu
 
Html5移动网站开发实践
Html5移动网站开发实践Html5移动网站开发实践
Html5移动网站开发实践
Web Zhao
 
Study mapapi v0.1
Study mapapi v0.1Study mapapi v0.1
Study mapapi v0.1
Paul Yang
 
由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...
由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...
由美國麻省理工學院媒體實驗室所開發的 Scratch 是一套圖形化程式設計軟體,適合學生作為學習程式設計的入門軟體,可以輕易製作劇情、動畫、遊戲、音樂等程...
ChungHsienTsai1
 
07 View Controllers
07 View Controllers07 View Controllers
07 View Controllers
Tom Fan
 
赶集团购开发总结4
赶集团购开发总结4赶集团购开发总结4
赶集团购开发总结4
yangdj
 
JdonFramework中文
JdonFramework中文JdonFramework中文
JdonFramework中文
banq jdon
 
Android 介面實作
Android 介面實作Android 介面實作
Android 介面實作
Richard Chang
 
Ad

More from rogeryi (13)

Why your Android Apps Suck
Why your Android Apps SuckWhy your Android Apps Suck
Why your Android Apps Suck
rogeryi
 
Web Page Rendering and Accelerated Compositing
Web Page Rendering and Accelerated CompositingWeb Page Rendering and Accelerated Compositing
Web Page Rendering and Accelerated Compositing
rogeryi
 
Android Hardware Accelerated 2D Rendering
Android Hardware Accelerated 2D RenderingAndroid Hardware Accelerated 2D Rendering
Android Hardware Accelerated 2D Rendering
rogeryi
 
Motion and gesture in Android
Motion and gesture in AndroidMotion and gesture in Android
Motion and gesture in Android
rogeryi
 
Voice recognization in Android
Voice recognization in AndroidVoice recognization in Android
Voice recognization in Android
rogeryi
 
Voice Recognization in Android
Voice Recognization in AndroidVoice Recognization in Android
Voice Recognization in Android
rogeryi
 
Layout Management - Android and Qt
Layout Management - Android and QtLayout Management - Android and Qt
Layout Management - Android and Qt
rogeryi
 
Character Encoding - Concepts and Practices
Character Encoding - Concepts and PracticesCharacter Encoding - Concepts and Practices
Character Encoding - Concepts and Practices
rogeryi
 
Java Memory Tips&Tricks
Java Memory Tips&TricksJava Memory Tips&Tricks
Java Memory Tips&Tricks
rogeryi
 
Build local web server in 5 minutes with mongoose
Build local web server in 5 minutes with mongooseBuild local web server in 5 minutes with mongoose
Build local web server in 5 minutes with mongoose
rogeryi
 
Android Event Retrospect
Android Event RetrospectAndroid Event Retrospect
Android Event Retrospect
rogeryi
 
Android event retrospect
Android event retrospectAndroid event retrospect
Android event retrospect
rogeryi
 
Android Event 02-02-2011 Retrospect
Android Event 02-02-2011 RetrospectAndroid Event 02-02-2011 Retrospect
Android Event 02-02-2011 Retrospect
rogeryi
 
Why your Android Apps Suck
Why your Android Apps SuckWhy your Android Apps Suck
Why your Android Apps Suck
rogeryi
 
Web Page Rendering and Accelerated Compositing
Web Page Rendering and Accelerated CompositingWeb Page Rendering and Accelerated Compositing
Web Page Rendering and Accelerated Compositing
rogeryi
 
Android Hardware Accelerated 2D Rendering
Android Hardware Accelerated 2D RenderingAndroid Hardware Accelerated 2D Rendering
Android Hardware Accelerated 2D Rendering
rogeryi
 
Motion and gesture in Android
Motion and gesture in AndroidMotion and gesture in Android
Motion and gesture in Android
rogeryi
 
Voice recognization in Android
Voice recognization in AndroidVoice recognization in Android
Voice recognization in Android
rogeryi
 
Voice Recognization in Android
Voice Recognization in AndroidVoice Recognization in Android
Voice Recognization in Android
rogeryi
 
Layout Management - Android and Qt
Layout Management - Android and QtLayout Management - Android and Qt
Layout Management - Android and Qt
rogeryi
 
Character Encoding - Concepts and Practices
Character Encoding - Concepts and PracticesCharacter Encoding - Concepts and Practices
Character Encoding - Concepts and Practices
rogeryi
 
Java Memory Tips&Tricks
Java Memory Tips&TricksJava Memory Tips&Tricks
Java Memory Tips&Tricks
rogeryi
 
Build local web server in 5 minutes with mongoose
Build local web server in 5 minutes with mongooseBuild local web server in 5 minutes with mongoose
Build local web server in 5 minutes with mongoose
rogeryi
 
Android Event Retrospect
Android Event RetrospectAndroid Event Retrospect
Android Event Retrospect
rogeryi
 
Android event retrospect
Android event retrospectAndroid event retrospect
Android event retrospect
rogeryi
 
Android Event 02-02-2011 Retrospect
Android Event 02-02-2011 RetrospectAndroid Event 02-02-2011 Retrospect
Android Event 02-02-2011 Retrospect
rogeryi
 
Ad

Beyond Android Views - Window,Surface,Special Views,and More

  • 1. Beyond Android Views - Window, Surface, Special Views and More Roger [email_address] [email_address] www.twitter.com/roger2yi + 易旭昕 in Google+
  • 2. 介绍隐藏在用户界面后面的系统底层模块 - Window , Surface , Canvas ,和它们之间的关系与交互 介绍一些特殊 View 的运作原理 - SurfaceView , GLSurfaceView , TextureView 介绍硬件加速绘图与非硬件加速绘图的差异 Major Contents
  • 4. View This class represents the basic building block for user interface components. A View occupies a rectangular area on the screen and is responsible for drawing and event handling. View is the base class for widgets, which are used to create interactive UI components (buttons, text fields, etc.).
  • 5. Activity 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理 应用在 Activity.onCreate 中构建用户界面,调用 Activity.setContentView 方法设置界面
  • 6. Those things behind Activity and Views
  • 7. System Services Activity Management Service Window Management Service Suface Flinger etc...
  • 8. The Startup of an Activity in New Process AMS 接收到请求要在新的进程启动一个 Activity AMS 转发请求给 zygote 进程, zygote fork 一个新的进程,然后调用 ActivityThread.main 方法, ActivityThread 创建 MessageQueue , attach 到 AMS ,然后进入消息循环,这个线程就是主线程,也是所谓的 UI 线程 当 ActivityThread attch 到 AMS 后, AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY ) ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity ) 创建 Activity 后调用 onCreate ( performLaunchActivity ) 应用则在 onCreate 中设置 Content View ,然后开始跟用户的交互 ... ...
  • 9.  
  • 10. Window Android 中的 Window 是一个十分容易混淆的概念 它存在应用层面窗口和系统层面窗口的区别 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
  • 11. android.view.Window Abstract base class for a top-level window look and behavior policy. It provides standard UI policies such as a background, title area, default key processing, etc. 它是通常意义上我们理解的应用层面窗口, TopLevelWindow or WindowPolicy 可能是一个更合适的名字
  • 12. PhoneWindow PhoneWindow 是抽象类 Window 的唯一实现 ActivityThread 在启动一个 Activity 的时候, Activity 会创建一个 PhoneWindow ActivityThread.handleLaunchActivity -> ActivityThread.performLaunchActivity -> Activity.attach Activity.setContentView 实际上是调用 PhoneWindow.setContentView ,在该方法的第一次调用时, PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的 View Hierachy 的根节点
  • 14.  
  • 15. WindowManager android.view.WindowManager The interface that apps use to talk to the window manager. 真正的实现是 WindowManagerImpl ,由 PhoneWindow 在 Activity 启动时创建 ActivityThread.handleLaunchActivity -> ActivityThread.performLaunchActivity -> Activity.attach -> PhoneWindow.setWindowManager 当 Activity 启动后, ActivityThread 将 DocorView 添加到 WindowManagerImpl 中 ActivityThread.handleLaunchActivity -> ActivityThread.handleResumeActivity -> WindowManager.addView
  • 16. Cont. WindowManagerImpl 负责跟 WMS 通讯 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责, ViewRootImpl 在 addView 时被创建 这里的 Window 是指系统层面的 Window ,除了之前的 PhoneWindow 外,其它如 Dialog , Menu 都拥有一个独立的 Window ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系,它是真正意义上的 View Hierachy 的根节点 ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
  • 17. ViewRootImpl The top of a view hierarchy, implementing the needed protocol between View and the WindowManager This is for the most part an internal implementation detail WindowManagerImpl
  • 18. Cont. ViewRootImpl 会打开一个 IWindowSession 用于跟 WMS 对话 并通过 IWindowSession 向 WMS 注册一个窗口(实际上是让 WMS 在服务端创建一个窗口( WindowState ),并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起) ActivityThread.handleLaunchActivity -> ActivityThread.handleResumeActivity -> WindowManagerImpl.addView -> ViewRootImpl.setView
  • 19. Cont. IWindow API back to a client window that the Window Manager uses to inform it of interesting things happening. 回调接口用于接收 WMS 关于窗口的消息 —— 显示 / 隐藏,大小改变,焦点变化等等 除了注册窗口外, ViewRootImpl 还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件 接收到的输入事件会先放在 UI 线程的消息循环中,然后通过 ViewRootImpl 进行分派,在它对应的 View Hierachy 上路由
  • 20.  
  • 21.  
  • 22. Overall Flow ActivityThead 创建 Activity Activity 创建 PhoneWindow PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点, Client 端设置的 Content View 会 attach 到 DecorView 下面(间接) PhoneWindow 创建 WindowManagerImpl ActivityThead 把 DecorView 加到 WindowManagerImpl 里面 WindowManagerImpl 创建 ViewRootImpl ,并把 DecorView 传给它 ViewRootImpl 打开一个 Window Session 跟 WMS 通讯,通过 Session 注册一个窗口,最后客户端拥有一个 IWindow 回调接口,服务端拥有一个 WindowState 跟该回调接口绑定
  • 23. View Hierachy Rendering 当 ViewRootImpl 建立跟 WMS 的联系,注册了窗口后,会发出第一次渲染 View Hierachy 的请求 ViewRootImpl.setView ViewRootImpl.requestLayout ViewRootImpl.scheduleTraversals 在第一次的 View Hierachy 的渲染中( ViewRootImpl.performTraversals ), ViewRootImpl 需要创建 Surface
  • 24. Cont. 当 Surface 创建后,后续的渲染就可以通过获得 Surface 的 Canvas ( Surface.lockCanvas ) 然后遍历 View Hierachy ,把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面( View.onDraw ) 绘制完后需要解锁( Surface.unlockCanvasPost ),让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
  • 25.  
  • 26. Surface Handle onto a raw buffer that is being managed by the screen compositor. 每个 Window 都有一个 Surface ,由窗口在客户端的代理者 ViewRootImpl 所拥有 Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建 ViewRootImpl.performTraversals ViewRootImpl.relayoutWindow IWindowSession.relayout
  • 27. Cont. ViewRootImpl 预先创建一个空的 Surface 对象( Java ),在需要创建真正的 Surface 的时候,它调用 IWindowSession.relayout ,这是一个 RPC ,最终是 WMS 的 relayoutWindow 被调用 WMS 调用 WindowState.createSurfaceLocked 创建了一个 Surface 对象( Java ),并把这个对象的数据传回给客户端,而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java ) 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface ,然后把 Surface 相关的信息再传回给客户端 客户端利用这些信息来创建一个 native Surface 对象,然后把它跟 Java Surface 对象绑定在一起 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer ),图像缓存可以看作是一块共享内存,在客户端和 SurfaceFlinger 之间共享
  • 28. Surface & Canvas Surface ( Java )包含一个 Canvas ( Java ),而 Canvas ( Java )包含一个 native 的 SkCanvas 对象 当调用 Surface.lockCanvas 时 从图像缓存队列中取出一个可用的缓存 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Region 之外的区域),然后将这块缓存加锁,并设置为 Locked Buffer 获得新缓存的内存地址,根据内存地址构建一个 SkBitmap 把该 SkBitmap 设置到 SkCanvas 里面 返回跟 SkCanvas 对应的 Canvas ( Java ),透过 Canvas ( Java )绘制的内容实际上就是绘制到当前的缓存
  • 29. Cont. 当调用 Surface.unlockCanvasAndPost 的时候 置空 SkCanvas ,设置一个空的 SkBitmap 将 Locked Buffer 解锁并返回到图像缓存队列里面 将 Posted Buffer 设置为 Locked Buffer ,旧的 Posted Buffer 就可以被下次取出来使用,设置 Locked Buffer 为空 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
  • 30. SurfaceFlinger 应用跟 SF 之间的关系是就像是生产者与消费者的关系 应用从 Surface 的 GraphicsBuffer 队列的前端取出一个缓存,然后进行绘制 绘制完毕后把该缓存放置回队列的后端(生产) 而 SF 则不断地将 Surface 的 GraphicsBuffer 队列的最后一个缓存绘制到屏幕上(消费) 两者在不同的进程,是异步进行的,对队列的访问需要进行同步
  • 31.  
  • 32. Overall Flow ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surface 客户端请求 WMS 创建 Surface ,并返回 Surface 相关的数据用于构建一个 native 的 Surface 对象,并把它跟 ViewRootImpl 的 Surface ( Java )绑定在一起 ViewRootImpl 在渲染时先从 Surface 获得 Canvas 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面 绘制完毕后解锁该 Surface SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface 绘制到屏幕上
  • 34. SurfaceView Provides a dedicated drawing surface embedded inside of a view hierarchy. You can control the format of this surface and, if you like, its size; the SurfaceView takes care of placing the surface at the correct location on the screen The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed.
  • 35. Cont. Pros 可以跟 View Hierachy 较好地结合在一起,可以移动,改变大小,在上方叠加其它的 View 在单独的渲染线程进行渲染,渲染效率高 SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成,效率高,并且不占用应用本身的 UI 线程时间 Cons SurfaceView 的渲染毕竟跟真正的 View 不一样,它不是由 ViewRootImpl 渲染到当前的 Window Surface 上面 不能改变 Alpha ,不支持跟下方的 View 进行 Alpha 混合 不能做 Rotation , Skew 等变换
  • 36. GLSurfaceView An implementation of SurfaceView that uses the dedicated surface for displaying OpenGL rendering. A GLSurfaceView provides the following features: Manages a surface, which is a special piece of memory that can be composited into the Android view system. Manages an EGL display, which enables OpenGL to render into a surface. Accepts a user-provided Renderer object that does the actual rendering. Renders on a dedicated thread to decouple rendering performance from the UI thread. Supports both on-demand and continuous rendering. Optionally wraps, traces, and/or error-checks the renderer's OpenGL calls.
  • 37. Cont. GLSurfaceView 创建一个内部的线程 GLThread 在该线程运行环境下创建一个 EglContext 创建一个 EglSurface ( Window Surface ) 设置之前创建的 EglContext 为当前的 GL Context 并绑定到创建的 EglSurface 上 在该线程内就可以通过 EGL 指令在当前的 GL Context 上绘图
  • 38. Cont. GLSurfaceView 支持两种不同的绘图模式 连续模式下, GLThread 会不断调用 Renderer.onDrawFrame 进行绘图 Dirty 模式下, GLThread 处于等待状态,直到程序发送绘图请求( GLSurfaceView.requestRender )才调用 Renderer.onDrawFrame 进行绘图,绘制完一帧后重新进入等待状态 在 Renderer.onDrawFrame 的回调中,应用可以通过 SDK 提供的 EGL API 绘图,也可以转到 native 端,使用 NDK 提供的 EGL API 绘图
  • 39.  
  • 40. TextureView Since Android 4.0 ,只在硬件加速环境下起作用 具备 SurfaceView 的特性 但是可以跟其它普通的 View 一样实现 Rotation , Screw 等变换 支持 Alpha ,可以跟它下方的 View 进行 Alpha 混合 可以基于 TextureView 创建一个 GL Surface ,在上面进行 OpenGL 渲染
  • 41. Things become more complicated after Android 3.0 ...
  • 42. HW Accelerated 2D Rendering Android 3.0 后开始支持硬件加速的 2D 绘图,原有的绘图流程变得更加复杂 所谓硬件加速的 2D 绘图,就是将 2D Graphics API 的实现改成使用 OpenGL API 来进行绘图 OpenGL 的绘图模式跟一般的 2D 绘图有很大区别,它需要先将绘图所需的各种素材如贴图,多边形顶点阵列, Shader 等先加载到当前的 GLContext ,然后流水线式的顺序执行绘图指令,通过这种方式来充分利用硬件的能力
  • 43. ViewRootImpl 当 Actitity 的 View Hierachy 的根节点被添加到 WindowManager 的时候( WindowManager.addView ), WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImpl.setView ),并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer 在 ViewRootImpl 第一次渲染 View Hierachy 时,会创建 Surface ,如果开启硬件加速,则通过 HardwareRenderer 在当前的 UI 线程初始化 EGL 绘图环境(类似 GLSurfaceView )
  • 44. Cont. 在 ViewRootImpl 真正渲染 View Hierachy 时,如果开启硬件加速,则从 HardwareRenderer 获得一个 HardwareCanvas ,然后 View Hierachy 的渲染通过 HardwareCanvas 来进行 HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定,通过它调用 EGL API 来完成真正的绘制
  • 45. DisplayList and Hardware Layer 为了充分利用硬件加速的能力, Android 3.0 还引入了 DisplayList 和 Hardware Layer DisplayList 用于记录一系列 OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap , Paint , Shape , Shader ),当 View 的内容不发生变化时,可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object ,当内容不发生变化时,可以直接使用 Layer 进行 Layer Composite 获得更快的绘图速度
  • 46.  
  • 47. Reference Android 圖形系統 -- 設計與實做分析 How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich?
  • 48. The End Thank you for your listening Yours Sincerely, Roger